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
TruLens defines its own OTEL semantic conventions under the ai.observability.* namespace (src/otel/semconv/trulens/otel/semconv/trace.py), but the official OpenTelemetry GenAI Semantic Conventions use the gen_ai.* namespace. Currently zerogen_ai.* attributes are emitted anywhere in the codebase — TruLens telemetry is invisible to standard OTEL GenAI dashboards and backends.
The Gap
Namespace mismatch
TruLens uses ai.observability.* for everything. OTEL GenAI uses gen_ai.*. There is zero overlap at the namespace level.
~17 attributes have conceptual equivalents but different keys
The GENERATION inner class in trace.py defines no attributes in Python — generation-specific attributes (model, temperature, messages, tokens) only exist in the TypeScript dashboard constants (src/dashboard/react_components/record_viewer_otel/src/constants/span.ts), suggesting they were planned but never wired into the Python instrumentation layer.
Summary
TruLens defines its own OTEL semantic conventions under the
ai.observability.*namespace (src/otel/semconv/trulens/otel/semconv/trace.py), but the official OpenTelemetry GenAI Semantic Conventions use thegen_ai.*namespace. Currently zerogen_ai.*attributes are emitted anywhere in the codebase — TruLens telemetry is invisible to standard OTEL GenAI dashboards and backends.The Gap
Namespace mismatch
TruLens uses
ai.observability.*for everything. OTEL GenAI usesgen_ai.*. There is zero overlap at the namespace level.~17 attributes have conceptual equivalents but different keys
ai.observability.cost.modelgen_ai.request.modelai.observability.cost.num_prompt_tokensgen_ai.usage.input_tokensai.observability.cost.num_completion_tokensgen_ai.usage.output_tokensai.observability.generation.temperature(TS only)gen_ai.request.temperatureai.observability.generation.input_messages(TS only)gen_ai.input.messagesai.observability.generation.output_messages(TS only)gen_ai.output.messagesai.observability.retrieval.query_textgen_ai.retrieval.query.textai.observability.retrieval.retrieved_contextsgen_ai.retrieval.documentsai.observability.mcp.tool_namegen_ai.tool.nameai.observability.mcp.input_argumentsgen_ai.tool.call.argumentsai.observability.mcp.output_contentgen_ai.tool.call.resultai.observability.span_type(enum attr)gen_ai.operation.nameOTEL GenAI attributes TruLens doesn't capture at all
gen_ai.operation.name(chat,text_completion,embeddings, etc.)gen_ai.provider.name(e.g.,openai,anthropic)gen_ai.response.model(actual model that responded, may differ from requested)gen_ai.response.id,gen_ai.response.finish_reasonsgen_ai.request.max_tokens,gen_ai.request.top_p,gen_ai.request.top_kgen_ai.request.frequency_penalty,gen_ai.request.presence_penaltygen_ai.conversation.id(related: we filed Add conversation_id Support for Thread-Based Trace Grouping #2423 for conversation_id support)gen_ai.tool.definitions,gen_ai.tool.call.id,gen_ai.tool.typegen_ai.system_instructionsserver.address/server.porterror.typePython GENERATION class is empty
The
GENERATIONinner class intrace.pydefines no attributes in Python — generation-specific attributes (model, temperature, messages, tokens) only exist in the TypeScript dashboard constants (src/dashboard/react_components/record_viewer_otel/src/constants/span.ts), suggesting they were planned but never wired into the Python instrumentation layer.What
Phase 1: Emit
gen_ai.*alongsideai.observability.*gen_ai.operation.name,gen_ai.request.model,gen_ai.usage.input_tokens,gen_ai.usage.output_tokens,gen_ai.request.temperature,gen_ai.provider.namegen_ai.retrieval.query.text,gen_ai.retrieval.documentsgen_ai.tool.name,gen_ai.tool.call.arguments,gen_ai.tool.call.resultai.observability.*attributes stay as-isPhase 2: Populate the empty Python GENERATION class
model,temperature,input_messages,output_messages,input_token_count,output_token_countto the PythonGENERATIONclass intrace.pyPhase 3: Capture missing OTEL GenAI attributes
gen_ai.response.finish_reasons,gen_ai.response.idgen_ai.request.max_tokens,gen_ai.request.top_pwhere available from provider responsesgen_ai.provider.namebased on which TruLens provider is activeerror.typefor standardized error classificationWhat to keep as TruLens-specific (
ai.observability.*)These have no OTEL GenAI equivalent and should remain in the TruLens namespace:
eval_root.*,eval.*)cost.cost,cost.cost_currency)cost.num_reasoning_tokens)graph_task.*,graph_node.*,workflow.*)reranking.*)mcp.server_name,mcp.input_schema,mcp.output_is_error,mcp.execution_time_ms)record_id,run.name,input_id,span_groups)References
src/otel/semconv/trulens/otel/semconv/trace.pysrc/dashboard/react_components/record_viewer_otel/src/constants/span.tsDifficulty
Medium-Hard (phased approach recommended)