[OTel] Emit gen_ai.response.model on LLM node spans (GenAI semconv conformance)
- Dominant language
- TypeScript
- Stars
- 156k
- Forks
- 24.6k
- Avg merge
- 22h 9m
- Merged PRs (30d)
- 610
Description
### Summary
The native OTel instrumentation (`api/extensions/otel/`) sets
`gen_ai.request.model` on LLM node spans but never sets `gen_ai.response.model`.
`gen_ai.response.model` is a first-class attribute in the OpenTelemetry GenAI
semantic conventions registry
(https://github.com/open-telemetry/semantic-conventions-genai). Several
observability backends key their GenAI model-level aggregations on
`gen_ai.response.model` specifically, not on `gen_ai.request.model`. In
practice this means the model breakdown views in those backends render empty
for Dify workloads, even though Dify is emitting otherwise-correct GenAI spans.
We hit this while building an open-source OTel conformance bridge for Dify
(https://github.com/obs-plugins/dynatrace-otel-bridge) and currently patch it
in the OTel Collector with an OTTL processor. Fixing it at the source in Dify
would benefit every backend, not just ours.
### Proposed change
Add `RESPONSE_MODEL = "gen_ai.response.model"` to `LLMAttributes` in
`api/extensions/otel/semconv/gen_ai.py`, and set it in
`api/extensions/otel/parser/llm.py` alongside the existing `REQUEST_MODEL`.
This is purely additive — no existing attribute is renamed or removed — so it
is backward-compatible with all current consumers (Langfuse, Arize Phoenix,
Opik) and does not require an `OTEL_SEMCONV_STABILITY_OPT_IN` gate.
### Known limitation (worth discussing)
Dify currently derives the model name from `process_data["model_name"]`, which
is the *requested* model. The model actually returned by the provider
(`LLMResult.model`) is not surfaced in `NodeRunResult`. The GenAI spec allows
`gen_ai.response.model` to be set on the instrumentation's best knowledge, so
using the same source is valid and immediately useful. The complete fix would
be for `graphon` to expose `LLMResult.model` in `process_data`. Happy to follow
up with a separate issue there if maintainers agree.
### Scope
I have a broader GenAI semconv conformance audit of the current OTel layer
(missing `gen_ai.workflow.name`, singular `gen_ai.response.finish_reason` vs.
the spec's plural array, absent GenAI metrics, non-spec `gen_ai.operation.name`
values). I'm intentionally keeping this issue narrow and additive. If
maintainers are open to it, I'd be glad to open a tracking issue for the rest.
### Request
Please assign this issue to me so I can open the PR, per CONTRIBUTING.md.
Contributor guide
Research direction
Start by reading api/extensions/otel/semconv/gen_ai.py and api/extensions/otel/parser/llm.py, then trace how process_data["model_name"] is used for LLM node span attributes. Add the response-model attribute alongside the request-model attribute and verify that generated LLM spans contain both attributes without removing existing ones.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- observability-sre
- Issue type
- Feature
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 78/100