首页
/ Dify Enterprise Telemetry 数据字典:信号、属性与查询模式的完整参考指南

Dify Enterprise Telemetry 数据字典:信号、属性与查询模式的完整参考指南

2026-09-05 16:34:41作者:翟江哲Frasier

本文基于 Dify 企业版遥测模块的数据字典文档(DATA_DICTIONARY.md),系统梳理 Dify Enterprise 通过 OpenTelemetry 发出的全部可观测信号——包括 Span 追踪、Counter 计数器、Histogram 直方图与结构化日志的属性定义、Token 指标的多层去重模型,以及可直接用于 Prometheus/Tempo 的查询模式。读完后你可以准确解读每一条 dify.* 指标与日志字段的含义、正确编写 PromQL 聚合查询,并结合源码理解确定性 Trace ID 关联机制的底层实现。

一、信号体系总览:Slim Span + Rich Companion Log

Dify Enterprise 采用「精简 Span + 丰富伴随日志」的遥测架构(详见 README.md),目标是高保真可观测性而不压垮追踪存储:

  • Traces(Spans):只捕获工作流与节点的结构、标识与时序信息,保持 Span 轻量;
  • Structured Logs:为每个事件提供深度上下文(输入、输出、元数据),通过 trace_idspan_id 与 Span 关联;
  • Metrics:提供 100% 精确的 Counter 与 Histogram,用于用量、性能与错误跟踪。

数据字典中的所有信号分为四类:Resource Attributes(附着在每个信号上)、Traces/SpansCounters 与 HistogramsStructured Logs

二、Resource Attributes:所有信号的公共属性

以下属性附着在每一条 Span、Metric 与 Log 上:

Attribute Type Example
service.name string dify
host.name string dify-api-7f8b

从源码结构看,这两个属性在 exporter.py 中构建 OTEL Resource 时写入:service.name 取自 APPLICATION_NAME 配置(默认 langgenius/dify),host.name 取自进程主机名(socket.gethostname())。

三、Traces(Spans):工作流与节点的追踪信号

3.1 dify.workflow.run Span

工作流运行的根 Span,属性定义如下:

Attribute Type Description
dify.trace_id string Business trace ID (Workflow Run ID)
dify.tenant_id string Tenant identifier
dify.app_id string Application identifier
dify.workflow.id string Workflow definition ID
dify.workflow.run_id string Unique ID for this run
dify.workflow.status string succeededfailedstopped
dify.workflow.error string Error message if failed
dify.workflow.elapsed_time float Total execution time (seconds)
dify.invoke_from string apiwebappdebug
dify.conversation.id string Conversation ID (optional)
dify.message.id string Message ID (optional)
dify.invoked_by string User ID who triggered the run
gen_ai.usage.total_tokens int Total tokens across all nodes (optional)
gen_ai.user.id string End-user identifier (optional)
dify.parent.trace_id string Parent workflow trace ID (optional)
dify.parent.workflow.run_id string Parent workflow run ID (optional)
dify.parent.node.execution_id string Parent node execution ID (optional)
dify.parent.app.id string Parent app ID (optional)

dify.parent.* 四个属性专门服务于嵌套子工作流场景:当一个工作流通过 Tool 或 Sub-workflow 节点调用另一个工作流时,内层 dify.workflow.run Span 通过这些属性指回外层的 Trace、运行 ID、触发节点与所属应用,实现跨工作流的父子关联。

3.2 dify.node.execution Span

节点执行的 Span,每个工作流节点对应一条:

Attribute Type Description
dify.trace_id string Business trace ID
dify.tenant_id string Tenant identifier
dify.app_id string Application identifier
dify.workflow.id string Workflow definition ID
dify.workflow.run_id string Workflow Run ID
dify.message.id string Message ID (optional)
dify.conversation.id string Conversation ID (optional)
dify.node.execution_id string Unique node execution ID
dify.node.id string Node ID in workflow graph
dify.node.type string Node type(取值见附录
dify.node.title string Display title
dify.node.status string succeededfailed
dify.node.error string Error message if failed
dify.node.elapsed_time float Execution time (seconds)
dify.node.index int Execution order index
dify.node.predecessor_node_id string Triggering node ID
dify.node.iteration_id string Iteration ID (optional)
dify.node.loop_id string Loop ID (optional)
dify.node.parallel_id string Parallel branch ID (optional)
dify.node.invoked_by string User ID who triggered execution
gen_ai.usage.input_tokens int Prompt tokens (LLM nodes only)
gen_ai.usage.output_tokens int Completion tokens (LLM nodes only)
gen_ai.usage.total_tokens int Total tokens (LLM nodes only)
gen_ai.request.model string LLM model name (LLM nodes only)
gen_ai.provider.name string LLM provider name (LLM nodes only)
gen_ai.user.id string End-user identifier (optional)

3.3 dify.node.execution.draft Span

属性与 dify.node.execution 完全相同,专门在 Preview/Debug 调试运行(单节点独立运行)时发出。关键区别在于:Draft 执行以 node_execution_id 作为 correlation ID,因此它自成一条 Trace,不是任何工作流 Trace 的子 Span。

3.4 确定性 ID 关联机制(源码印证)

上述三类 Span 之所以能在异步任务、跨服务场景下稳定关联,源自 id_generator.py 中的 CorrelationIdGenerator

  • trace_id:由业务 correlation ID(workflow_run_id 或 draft 场景下的 node_execution_id)直接推导——generate_trace_id() 返回 uuid.UUID(correlation_id).int,即整个 UUID 的 128 位整数值(id_generator.py#L58-L65);
  • span_id:当设置了 span_id_source 时,取 UUID(source_id) 的低 64 位,并保证非零(OTEL 要求 span_id 非 0),见 compute_deterministic_span_id()id_generator.py#L39-L46)。

export_span()exporter.py#L178-L239 中还处理了跨工作流链接:通过 trace_correlation_overrideparent_span_id_source 参数,内层工作流的根 Span 可以挂到外层工具节点的 Span 上(构造 is_remote=TrueSpanContext)。同时源码刻意使用显式空 Context 作为根 Span 的父上下文,避免根 Span 意外继承 Celery/HTTP 自动注入的环境追踪上下文,导致一条逻辑 Trace 被拆成两条。

三种典型场景(来自 README.md):

# 场景 A:简单工作流 —— 所有 Span/Log 共享同一 trace_id
trace_id = UUID(workflow_run_id)
├── [root span] dify.workflow.run (span_id = hash(workflow_run_id))
│   ├── [child] dify.node.execution - "Start" (span_id = hash(node_exec_id_1))
│   ├── [child] dify.node.execution - "LLM"
│   └── [child] dify.node.execution - "End"

# 场景 B:嵌套子工作流 —— 内外层共享 trace_id = UUID(outer_workflow_run_id)
#   内层通过 dify.parent.trace_id / dify.parent.node.execution_id 等属性回指外层

# 场景 C:Draft 节点调试 —— 自成 Trace
trace_id = UUID(node_execution_id)   ← 独立 Trace,不属于任何工作流
└── dify.node.execution.draft (span_id = hash(node_execution_id))

四、Counters:100% 精确的累计计数器

所有 Counter 均为累计值且以 100% 精度发出(不受 Span 采样率影响)。在 exporter.py#L151-L164 中可以看到全部 Counter 的注册代码,与字典一一对应。

4.1 Token Counters

Metric Unit Description
dify.tokens.total {token} Total tokens consumed
dify.tokens.input {token} Input (prompt) tokens
dify.tokens.output {token} Output (completion) tokens

统一标签集: tenant_idapp_idoperation_typemodel_providermodel_namenode_type(仅 node_execution 时非空)。

⚠️ 警告: 工作流层的 dify.tokens.total 已包含全部节点 token,聚合时必须用 operation_type 过滤以避免重复计数。

Token 指标层级与查询模式 —— Token 指标在多层级发出,理解该层级是防止重复计数的关键:

App-level total
├── workflow          ← sum of all node_execution tokens (DO NOT add both)
│   └── node_execution ← per-node breakdown
├── message           ← independent (non-workflow chat apps only)
├── rule_generate     ← independent helper LLM call
├── code_generate     ← independent helper LLM call
├── structured_output ← independent helper LLM call
└── instruction_modify← independent helper LLM call

核心规则: workflow 层 token 已经包含所有 node_execution token,二者绝不可相加。

源码层面这一设计有明确的约束文档:entities/__init__.py#L54-L99 中的 TokenMetricLabels 模型强制所有 token 计数器使用完全一致的标签集合(frozen=True,禁止额外字段),其设计说明写道:「Without this unified structure, tokens get double-counted when querying totals because workflow.total_tokens is already the sum of all node tokens」。operation_type 标签将工作流级聚合、节点级明细与独立 LLM 辅助调用区分开,同时保持标签基数一致以便统一查询。

常用 PromQL 查询:

# ── 总量 ──────────────────────────────────────────────────
# 应用级总量(排除 node_execution 避免重复计数)
sum by (app_id) (dify_tokens_total{operation_type!="node_execution"})

# 单应用总量
sum (dify_tokens_total{app_id="<app_id>", operation_type!="node_execution"})

# 按租户总量
sum by (tenant_id) (dify_tokens_total{operation_type!="node_execution"})

# ── 下钻 ──────────────────────────────────────────────
# 某应用的工作流层 token
sum (dify_tokens_total{app_id="<app_id>", operation_type="workflow"})

# 某应用内的节点级分布
sum by (node_type) (dify_tokens_total{app_id="<app_id>", operation_type="node_execution"})

# 某应用的模型维度分布
sum by (model_provider, model_name) (dify_tokens_total{app_id="<app_id>"})

# 各模型输入 vs 输出
sum by (model_name) (dify_tokens_input_total{app_id="<app_id>"})
sum by (model_name) (dify_tokens_output_total{app_id="<app_id>"})

# ── 速率 ───────────────────────────────────────────
# 每小时 token 消耗速率
sum(rate(dify_tokens_total{operation_type!="node_execution"}[1h]))

# 按应用的消耗速率
sum by (app_id) (rate(dify_tokens_total{operation_type!="node_execution"}[1h]))

注意一个字典中明确的细节:应用名只存在于 Span 属性(dify.app.name),不在 metric 标签中——指标查询请使用 app_id。如果手头只有应用名,可在 Tempo / Jaeger 中通过 Trace 查询反查:

{ resource.dify.app.name = "My Chatbot" } | select(resource.dify.app.id)

4.2 Request Counters

Metric Unit Description
dify.requests.total {request} Total operations count

按类型区分的标签集:

type Additional Labels
workflow tenant_idapp_idstatusinvoke_from
node tenant_idapp_idnode_typemodel_providermodel_namestatus
draft_node tenant_idapp_idnode_typemodel_providermodel_namestatus
message tenant_idapp_idmodel_providermodel_namestatusinvoke_from
tool tenant_idapp_idtool_name
moderation tenant_idapp_id
suggested_question tenant_idapp_idmodel_providermodel_name
dataset_retrieval tenant_idapp_id
generate_name tenant_idapp_id
prompt_generation tenant_idapp_idoperation_typemodel_providermodel_namestatus

4.3 Error Counters

Metric Unit Description
dify.errors.total {error} Total failed operations

按类型区分的标签集:

type Additional Labels
workflow tenant_idapp_id
node tenant_idapp_idnode_typemodel_providermodel_name
draft_node tenant_idapp_idnode_typemodel_providermodel_name
message tenant_idapp_idmodel_providermodel_name
tool tenant_idapp_idtool_name
prompt_generation tenant_idapp_idoperation_typemodel_providermodel_name

4.4 其他 Counters

Metric Unit Labels
dify.feedback.total {feedback} tenant_idapp_idrating
dify.dataset.retrievals.total {retrieval} tenant_idapp_iddataset_idembedding_model_providerembedding_modelrerank_model_providerrerank_model
dify.app.created.total {app} tenant_idapp_idmode
dify.app.updated.total {app} tenant_idapp_id
dify.app.deleted.total {app} tenant_idapp_id

五、Histograms:耗时分布

Metric Unit Labels
dify.workflow.duration s tenant_idapp_idstatus
dify.node.duration s tenant_idapp_idnode_typemodel_providermodel_nameplugin_name
dify.message.duration s tenant_idapp_idmodel_providermodel_name
dify.message.time_to_first_token s tenant_idapp_idmodel_providermodel_name
dify.tool.duration s tenant_idapp_idtool_name
dify.prompt_generation.duration s tenant_idapp_idoperation_typemodel_providermodel_name

这六个 Histogram 在 exporter.py#L165-L176 中通过 meter.create_histogram(..., unit="s") 注册,配合 PeriodicExportingMetricReader 周期性推送到 OTLP 端点。

六、Structured Logs:伴随日志与独立日志

6.1 Span Companion Logs(信号类型 span_detail

与 Span 伴随的日志,携带 Span 的全部属性,并补充业务上下文。

dify.workflow.run 伴随日志附加属性:

Additional Attribute Type Always Present Description
dify.app.name string No Application display name
dify.workspace.name string No Workspace display name
dify.workflow.version string Yes Workflow definition version
dify.workflow.inputs string/JSON Yes Input parameters (content-gated)
dify.workflow.outputs string/JSON Yes Output results (content-gated)
dify.workflow.query string No User query text (content-gated)

事件属性:dify.event.name = "dify.workflow.run"dify.event.signal = "span_detail",并携带 trace_idspan_idtenant_iduser_id

dify.node.executiondify.node.execution.draft 伴随日志附加属性:

Additional Attribute Type Always Present Description
dify.app.name string No Application display name
dify.workspace.name string No Workspace display name
dify.invoke_from string No Invocation source
gen_ai.tool.name string No Tool name (tool nodes only)
dify.node.total_price float No Cost (LLM nodes only)
dify.node.currency string No Currency code (LLM nodes only)
dify.node.iteration_index int No Iteration index (iteration nodes)
dify.node.loop_index int No Loop index (loop nodes)
dify.plugin.name string No Plugin name (tool/knowledge nodes)
dify.credential.name string No Credential name (plugin nodes)
dify.credential.id string No Credential ID (plugin nodes)
dify.dataset.ids JSON array No Dataset IDs (knowledge nodes)
dify.dataset.names JSON array No Dataset names (knowledge nodes)
dify.node.inputs string/JSON Yes Node inputs (content-gated)
dify.node.outputs string/JSON Yes Node outputs (content-gated)
dify.node.process_data string/JSON No Processing data (content-gated)

事件属性:dify.event.name"dify.node.execution""dify.node.execution.draft"dify.event.signal = "span_detail"

6.2 Standalone Logs(信号类型 metric_only

无结构化 Span 伴随的独立日志事件,每个事件均为一个字典条目。以下逐一列出核心属性。

dify.message.run —— 非工作流聊天应用的单次消息生成:

Attribute Type Description
dify.event.name string "dify.message.run"
dify.event.signal string "metric_only"
trace_id string OTEL trace ID (32-char hex)
span_id string OTEL span ID (16-char hex)
tenant_id / user_id string Tenant / User identifier (user 可选)
dify.app_id string Application identifier
dify.message.id string Message identifier
dify.conversation.id string Conversation ID (optional)
dify.workflow.run_id string Workflow run ID (optional)
dify.invoke_from string service-apiweb-appdebuggerexplore
gen_ai.provider.name / gen_ai.request.model string LLM provider / model
gen_ai.usage.input_tokens / output_tokens / total_tokens int Token 用量
dify.message.status string succeededfailed
dify.message.error string Error message (if failed)
dify.message.duration float Duration (seconds)
dify.message.time_to_first_token float TTFT (seconds)
dify.message.inputs / dify.message.outputs string/JSON Inputs / Outputs (content-gated)

dify.tool.execution —— 工具调用:除公共字段(event.nameevent.signaltrace_idspan_idtenant_idapp_idmessage.id)外,包含 dify.tool.namedify.tool.durationdify.tool.statussucceeded/failed)、dify.tool.error,以及四个 content-gated 字段 dify.tool.inputsdify.tool.outputsdify.tool.parametersdify.tool.config(均为 string/JSON)。

dify.moderation.check —— 内容审核:含 dify.moderation.typeinput/output)、dify.moderation.actionpass/block/flag)、dify.moderation.flagged(boolean)、dify.moderation.categories(JSON array)、dify.moderation.query(content-gated)。

dify.suggested_question.generation —— 建议问题生成:含 dify.suggested_question.count(int)、dify.suggested_question.durationdify.suggested_question.statusdify.suggested_question.errordify.suggested_question.questions(JSON array,content-gated)。

dify.dataset.retrieval —— 知识库检索:含 dify.dataset.iddify.dataset.namedify.dataset.embedding_providers(JSON array,每库一个)、dify.dataset.embedding_models(JSON array)、dify.retrieval.rerank_providerdify.retrieval.rerank_modeldify.retrieval.query(content-gated)、dify.retrieval.document_count(int)、dify.retrieval.durationdify.retrieval.statusdify.retrieval.errordify.dataset.documents(JSON array,content-gated)。

dify.generate_name.execution —— 会话命名:含 dify.conversation.iddify.generate_name.durationdify.generate_name.statusdify.generate_name.errordify.generate_name.inputs(content-gated)、dify.generate_name.outputs(生成的名称,content-gated)。

dify.prompt_generation.execution —— 提示词生成类操作(规则生成、代码生成等辅助 LLM 调用):含 dify.prompt_generation.operation_type(取值见附录)、gen_ai.provider.namegen_ai.request.model、三个 gen_ai.usage.* token 字段、dify.prompt_generation.durationstatuserror,以及 content-gated 的 dify.prompt_generation.instructiondify.prompt_generation.output

应用生命周期事件(均无 trace_id/span_id,仅 event.nameevent.signaltenant_iddify.app_id 加一个时间戳):

  • dify.app.createddify.app.modechatcompletionagent-chatworkflow)+ dify.app.created_at(ISO 8601);
  • dify.app.updateddify.app.updated_at
  • dify.app.deleteddify.app.deleted_at

dify.feedback.created —— 用户反馈:含 dify.message.iddify.feedback.ratinglike/dislike/null)、dify.feedback.content(content-gated)、dify.feedback.created_at(ISO 8601),以及 trace_idspan_id

dify.telemetry.rehydration_failed —— 遥测系统健康诊断事件:含 dify.telemetry.error(错误信息)、dify.telemetry.payload_type(取值见附录)、dify.telemetry.correlation_id

6.3 事件处理管线(源码印证)

从源码结构看,这些 metric_only 事件并非在请求线程中直接导出,而是先封装为 TelemetryEnvelope 投递到独立的 enterprise_telemetry Celery 队列,再由 metric_handler.py 中的 EnterpriseMetricHandler.handle() 统一处理:先做基于 Redis(带 TTL)的幂等去重,再按 TelemetryCase 路由到 app_createdmessage_runtool_executiondataset_retrieval 等具体处理器,并对需要内容还原的事件执行 payload rehydration;rehydration 失败时发出上文所述的 dify.telemetry.rehydration_failed 诊断事件。该处理器还会记录 enterprise_telemetry.handler.processed_total / deduped_total 等运维诊断计数器。

七、Content-Gated Attributes:内容门控

ENTERPRISE_INCLUDE_CONTENT=false(默认值,见 README.md 配置表)时,下列内容敏感属性不会被明文传出,而是被替换为引用字符串 ref:{id_type}={uuid},防止业务数据泄漏到 OTEL Collector 一侧:

Attribute Signal
dify.workflow.inputs / dify.workflow.outputs / dify.workflow.query dify.workflow.run
dify.node.inputs / dify.node.outputs / dify.node.process_data dify.node.execution
dify.message.inputs / dify.message.outputs dify.message.run
dify.tool.inputs / dify.tool.outputs / dify.tool.parameters / dify.tool.config dify.tool.execution
dify.moderation.query dify.moderation.check
dify.suggested_question.questions dify.suggested_question.generation
dify.retrieval.query / dify.dataset.documents dify.dataset.retrieval
dify.generate_name.inputs / dify.generate_name.outputs dify.generate_name.execution
dify.prompt_generation.instruction / dify.prompt_generation.output dify.prompt_generation.execution
dify.feedback.content dify.feedback.created

引用字符串示例:

ref:workflow_run_id=550e8400-e29b-41d4-a716-446655440000
ref:node_execution_id=660e8400-e29b-41d4-a716-446655440001
ref:message_id=770e8400-e29b-41d4-a716-446655440002

需要还原真实内容时,使用 UUID 查询 Dify 数据库即可。门控开关在导出器初始化时读取:exporter.py#L115self.include_content = config.ENTERPRISE_INCLUDE_CONTENT

八、附录:取值枚举与空值行为

Operation Types

  • workflownode_executionmessagerule_generatecode_generatestructured_outputinstruction_modify

Node Types

  • startendanswerllmknowledge-retrievalknowledge-indexif-elsecodetemplate-transformquestion-classifierhttp-requesttooldatasourcevariable-aggregatorloopiterationparameter-extractorassignerdocument-extractorlist-operatoragenttrigger-webhooktrigger-scheduletrigger-pluginhuman-input

Workflow Statuses

  • runningsucceededfailedstoppedpartial-succeededpaused

Payload Types

  • workflownodemessagetoolmoderationsuggested_questiondataset_retrievalgenerate_nameprompt_generationappfeedback

Null Value Behavior

  • Spans: null 值的属性直接省略,不出现在 Span 中;
  • Logs: null 值以 JSON null 形式保留;
  • Content-Gated: 内容敏感属性被替换为引用字符串,而不是置为 null

九、实现入口索引

主题 文件路径
数据字典(本文主体) api/enterprise/telemetry/DATA_DICTIONARY.md
配置与架构说明 api/enterprise/telemetry/README.md
Counter/Histogram 注册、Span 导出 api/enterprise/telemetry/exporter.py
确定性 Trace/Span ID 生成 api/enterprise/telemetry/id_generator.py
信号/事件/指标名称枚举与统一标签模型 api/enterprise/telemetry/entities/__init__.py
Span 级追踪处理(token 层级设计说明) api/enterprise/telemetry/enterprise_trace.py
事件去重、路由与 payload 还原 api/enterprise/telemetry/metric_handler.py
结构化日志发射 api/enterprise/telemetry/telemetry_log.py

需要提醒的适用前提:本文所述遥测信号仅在 DEPLOYMENT_EDITION=ENTERPRISEENTERPRISE_TELEMETRY_ENABLED=true 时生效(见 README.md 配置表);Span 采样率由 ENTERPRISE_OTEL_SAMPLING_RATE 控制(默认 1.0),而 Metric 始终以 100% 精度发出,因此用量统计类查询(第四节的 PromQL)不受采样影响。

登录后查看全文
热门项目推荐
相关项目推荐