Add structured metadata to log records for programmatic consumption
维护者通常 1 天内回复
还没有人认领这个 Issue。
评估
- 难度
- 4/5
- 预计耗时
- 3-5 天
- 新手友好度
- 48/100
- Issue 类型
- 功能
- 描述清晰度
- 基本清楚
- 活跃度
- 冷清
- 技术栈
- python
调研方向
定位用于单次 LLM 调用的 Python logging 调用点,记录失败情况以及工作流结束时的使用情况摘要。首先跟踪这些调用如何获取模型、令牌、延迟、重试、状态和失败数据,然后验证自定义 handler 能够收集带命名空间的 dd_event 字典,同时保持现有日志输出不变。
由索引模型根据 Issue 内容生成。
描述
Priority Level
Medium (Nice to have)
Is your feature request related to a problem? Please describe.
Downstream tools and pipelines that build on Data Designer currently have no programmatic way to access per-call telemetry (model used, token counts, latency, retries, failure reasons). The only signals available are human-readable log messages, which means consumers must either:
- Parse log strings with brittle regex to extract stats
- Set DD's log level to INFO/DEBUG and hope the right messages propagate
- Infer failures indirectly (e.g. by diffing input vs output record IDs)
This makes it difficult to build observability dashboards, compute cost estimates, track model usage across runs, or diagnose slow pipelines — all without resorting to fragile log parsing.
Describe the solution you'd like
Attach structured metadata to Python LogRecord objects via the extra parameter at key call sites. This requires no new dependencies and no changes to existing log output — the human-readable messages stay exactly as they are.
Concretely, add a namespaced extra dict (e.g. dd_event) to log calls at these sites:
- Per-LLM call — model alias, input/output tokens, latency, retries, status (success/failed/filtered), error message if any
- Record failure — record ID, column, failure reason, attempt number
- Model usage summary — aggregate token counts and request counts per model at workflow end
Example:
# Existing log line stays unchanged for human readers
logger.debug(
"LLM call to %s completed in %dms",
model_alias, latency_ms,
extra={"dd_event": {
"type": "llm_call",
"model": model_alias,
"column": column_name,
"record_id": record_id,
"input_tokens": 285,
"output_tokens": 130,
"latency_ms": 340,
"retries": 0,
"status": "success",
}},
)
Consumers attach a lightweight handler to collect events:
class EventCollector(logging.Handler):
def __init__(self):
super().__init__()
self.events = []
def emit(self, record):
event = getattr(record, "dd_event", None)
if event:
self.events.append(event)
This enables several use cases without DD needing to expose new public API:
- Live monitoring — attach a handler during
create()/preview()to stream events as they happen - Offline analytics — write events to JSONL for post-hoc cost analysis, latency profiling, or model comparison
- Observability integration — forward events to Prometheus, OpenTelemetry, or custom dashboards
- Debugging — filter events by record ID to trace a single record's journey through the pipeline
Describe alternatives you've considered
-
Structured fields on
CreateResult/PreviewResult(e.g.result.model_usage,result.failed_records). This would be cleaner for aggregate stats but doesn't support live streaming and requires new public API surface. Could complement the logging approach for summary data. -
Callback / event hook parameter on
create()/preview()(e.g.on_event=my_handler). More explicit contract with typed event dataclasses, but a larger API change and less idiomatic Python than logging. -
Adopting
structlogfor structured logging throughout DD. Powerful but adds a dependency and is a bigger architectural change. Theextraapproach is a stepping stone that's compatible with a future structlog migration.
Additional context
Using a single namespaced key (dd_event) rather than flat extra keys avoids collisions with LogRecord's built-in attributes and with any other libraries that use extra. The convention is simple: if dd_event is present on a record, it contains a typed dict with a "type" discriminator field.
This is a non-breaking, additive change — existing users who don't attach a custom handler see zero difference in behavior or output.
- 主要语言
- Python
- 星标
- 2.4k
- 派生
- 243
- 平均合并
- 1 天 3 小时
- 30 天内合并 PR
- 90
环境准备
- 没有 Dockerfile 或 Docker Compose 文件
- 有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
NVIDIA-NeMo/DataDesigner 的其他 Issue
-
Structured-output prompt schemas escape non-ASCII text as \uXXXX可能已有人在做 @spped2000 于 1 天前认领。 未关闭triaged
难度 2/5 1-3 小时 新手友好度 76/100
NVIDIA-NeMo/DataDesigner#1130 · 2 条评论 ·
维护者通常 1 天内回复
-
needs-discussion triaged
难度 2/5 1-3 小时 新手友好度 85/100
NVIDIA-NeMo/DataDesigner#1129 · 3 条评论 ·
维护者通常 1 天内回复
-
Allow huggingface-hub 2.x (widen cap from <2 to <3)可能已有人在做 @davanstrien 于 6 天前认领。 未关闭enhancement triaged
难度 2/5 1-3 小时 新手友好度 72/100
NVIDIA-NeMo/DataDesigner#1110 · 1 条评论 ·
维护者通常 1 天内回复
-
Local seed path containing a single quote breaks the DuckDB query可能重新可做 关联的 PR 已关闭且未合并。 未关闭bug triaged
难度 2/5 1-3 小时 新手友好度 67/100
NVIDIA-NeMo/DataDesigner#1102 · 3 条评论 ·
维护者通常 1 天内回复
-
enforce \from future import annotations` via ruff FA102 rule`可能已有人在做 @chethanuk 于 55 天前认领。 未关闭task
难度 2/5 1-3 小时 新手友好度 82/100
NVIDIA-NeMo/DataDesigner#760 ·
维护者通常 1 天内回复
查看 NVIDIA-NeMo/DataDesigner 的全部 Issue
相似的 Issue
-
bug
难度 2/5 1-3 小时 新手友好度 69/100
jejjohnson/gaussx#752 ·
维护者通常 1 天内回复
-
难度 1/5 1 小时以内 新手友好度 85/100
521xueweihan/HelloGitHub#4270 ·
-
enhancement owner: den-haag
难度 2/5 1-3 小时 新手友好度 67/100
维护者通常 6 天内回复
-
难度 2/5 1-3 小时 新手友好度 78/100
ok-oldking/ok-wuthering-waves#1828 ·
维护者通常 1 天内回复
-
lesson-submission pending-review
难度 1/5 1 小时以内 新手友好度 65/100
Ikalus1988/MisakaNet#4512 ·
维护者通常 1 天内回复