Skip to content

feat: Last9LogToSpanProcessor — bridge GenAI log events onto spans (v1.1.0)#11

Merged
prathamesh-sonpatki merged 2 commits intomainfrom
feat/log-to-span-bridge
Apr 19, 2026
Merged

feat: Last9LogToSpanProcessor — bridge GenAI log events onto spans (v1.1.0)#11
prathamesh-sonpatki merged 2 commits intomainfrom
feat/log-to-span-bridge

Conversation

@prathamesh-sonpatki
Copy link
Copy Markdown
Member

@prathamesh-sonpatki prathamesh-sonpatki commented Apr 19, 2026

Summary

  • Adds Last9LogToSpanProcessor, a new LogRecordProcessor that promotes
    GenAI log events emitted by opentelemetry-instrumentation-openai-v2 onto
    the active span as flat + indexed attributes + span events so the Last9
    LLM dashboard renders prompts, completions, and tool calls.
  • Last9SpanProcessor gains an optional log_processor= kwarg for per-span
    counter cleanup.
  • Bumps version to 1.1.0.

Why

opentelemetry-instrumentation-openai-v2 (v2+) follows the new OTel GenAI
semantic conventions — it emits message content, tool calls, and completions
as OTel log events, not as span attributes. The Last9 LLM dashboard reads
span attributes (gen_ai.prompt, gen_ai.completion) and span events
(gen_ai.content.prompt, gen_ai.content.completion), so those payloads
were invisible until now.

This bridge closes the gap without monkey-patching the openai SDK. Works for
any framework that routes LLM calls through openai-v2 (AutoGen, LangChain,
direct usage).

Test plan

  • Unit test suite: uv run pytest tests/ -x -q — 117 passing.
  • End-to-end demo with AutoGen AssistantAgent + tool call; chat span
    carries gen_ai.prompt, gen_ai.completion, gen_ai.content.prompt
    event, and gen_ai.content.completion event.
  • Unit tests for Last9LogToSpanProcessor itself (follow-up — coverage
    currently 21%, functionally verified via integration demo).

Notes

Python 3.14 users must pin wrapt<2 because
opentelemetry-instrumentation-openai-v2 2.3b0 calls
wrap_function_wrapper(module=..., name=..., wrapper=...) and wrapt 2.0
renamed the first kwarg to target=. Without the pin, instrumentation fails
silently. README + CHANGELOG call this out.

Not in scope

  • Tool-call argument / result capture on AutoGen's own execute_tool span
    (tracked as Phase 2 — requires wrapping autogen_core.tools.FunctionTool.run_json).
  • Anthropic / google-genai bridges (deferred per customer priority).

🤖 Generated with Claude Code

prathamesh-sonpatki and others added 2 commits April 20, 2026 00:38
opentelemetry-instrumentation-openai-v2 (v2+) follows the new GenAI semantic
conventions and emits prompts, completions, and tool calls as OTel log events
rather than span attributes. The Last9 LLM dashboard reads span attributes and
events, so those payloads never reached the dashboard.

Last9LogToSpanProcessor listens for gen_ai.* log records and promotes their
payloads onto the active span as:
  - flat attrs gen_ai.prompt / gen_ai.completion (JSON arrays)
  - span events gen_ai.content.prompt / gen_ai.content.completion
  - indexed gen_ai.prompt.{i}.* / gen_ai.completion.{i}.* (AgentOps/Traceloop)

Last9SpanProcessor now accepts log_processor= and frees per-span counter
state when its span ends.

Bumps version to 1.1.0.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Covers:
- Flat + indexed attrs set on prompt/user/system/tool/assistant events
- Completion event with tool_calls, finish_reason, index
- Multi-prompt accumulation preserves order
- Unrelated event names ignored
- Non-dict body ignored
- Truncation applied beyond max_content_length
- cleanup_span releases per-span state on span end
- Tool messages capture tool_call.id
- Orphan log record (no active span) dropped

Coverage: log_processor.py 21% -> 94%; total 78% -> 86%.

Also applies black formatting to satisfy CI.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@prathamesh-sonpatki prathamesh-sonpatki merged commit 2444a89 into main Apr 19, 2026
7 checks passed
@prathamesh-sonpatki prathamesh-sonpatki deleted the feat/log-to-span-bridge branch April 19, 2026 19:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant