You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Tracing is the only telemetry pillar still using pre-plugin instrumentation. Metrics (#443) and logging (#442) both migrated to the canonical plugin/hook pattern during their epics; tracing needs the same treatment to unblock the rest of epic #444.
Each of 5 backends (openai, ollama, huggingface, litellm, watsonx) calls these helpers inline (~20 call sites total).
The active span is stored in mot._meta["_telemetry_span"] so it can survive the asyncio.create_task boundary and be closed in post_processing() / error path.
Tracing reads raw provider responses for attribute extraction instead of mot.generation.
Scope
Create mellea/telemetry/tracing_plugins.py following mellea/telemetry/metrics_plugins.py as the reference. Example structure:
BackendTracingPlugin (priority ~50) — hooks generation_post_call in FIRE_AND_FORGET mode, reads payload.model_output.generation, emits the backend generation span with gen_ai.* attributes.
Register plugins through a _TRACING_PLUGIN_CLASSES tuple inside tracing.py at import time when tracing is enabled.
Remove all direct tracing imports from mellea/backends/*.py. Delete the ~20 inline instrumentation calls.
Remove the mot._meta["_telemetry_span"] stash. Spans now live inside the plugin and don't need to round-trip through the MOT.
Phase 1 (foundation). No internal deps. Blocks all of Phase 2 and Phase 3. Sequencing within Phase 1: this issue → {{NEW-B}} → {{NEW-C}}; all three likely land as a single PR per the epic plan.
Background
Tracing is the only telemetry pillar still using pre-plugin instrumentation. Metrics (#443) and logging (#442) both migrated to the canonical plugin/hook pattern during their epics; tracing needs the same treatment to unblock the rest of epic #444.
Current state
mellea/telemetry/backend_instrumentation.pyexposesinstrument_generate_from_context,instrument_generate_from_raw,start_generate_span,record_token_usage,record_response_metadata.mot._meta["_telemetry_span"]so it can survive theasyncio.create_taskboundary and be closed inpost_processing()/ error path.mot.generation.Scope
mellea/telemetry/tracing_plugins.pyfollowingmellea/telemetry/metrics_plugins.pyas the reference. Example structure:BackendTracingPlugin(priority ~50) — hooksgeneration_post_callinFIRE_AND_FORGETmode, readspayload.model_output.generation, emits the backend generation span withgen_ai.*attributes._TRACING_PLUGIN_CLASSEStuple insidetracing.pyat import time when tracing is enabled.mellea/backends/*.py. Delete the ~20 inline instrumentation calls.mot._meta["_telemetry_span"]stash. Spans now live inside the plugin and don't need to round-trip through the MOT.mellea/telemetry/tracing.pyas the low-level setup module (tracer provider, exporters,Tracercreation). Plugins consumeget_application_tracer()/get_backend_tracer().gen_ai.provider.name,gen_ai.conversation.id,llm.prompt_template.*,gen_ai.request.{temperature, top_p, top_k, frequency_penalty, presence_penalty},error.type, cache/reasoning tokens).Phase & dependencies
Phase 1 (foundation). No internal deps. Blocks all of Phase 2 and Phase 3. Sequencing within Phase 1: this issue → {{NEW-B}} → {{NEW-C}}; all three likely land as a single PR per the epic plan.
Coordination notes
GENERATION_POST_CALLfires (see feat: streaming validation — per-chunk requirement checking with early exit #891 discussion, ModelOutputThunk structural cleanup — ._meta partitioning, raw responses, _thinking #909 comment thread). Whatever resolves that concern forTokenMetricsPluginapplies here identically.backend_instrumentation.pyinto the plugin added here.Acceptance criteria
mellea/telemetry/tracing_plugins.pyexists with at leastBackendTracingPlugin.mellea/backends/imports frommellea.telemetry.backend_instrumentationormellea.telemetry.tracing.mot._meta["_telemetry_span"]is not set or read anywhere (closes ModelOutputThunk structural cleanup — ._meta partitioning, raw responses, _thinking #909 item 2).Parent epic: #444