.agents/skills/llmobs-integration/references/reference-implementations.md
Working examples of LLMObs plugins in dd-trace-js.
Location: packages/dd-trace/src/llmobs/plugins/base.js
The abstract base class all plugins extend.
Key methods:
start(ctx) - Registers span, captures contextgetLLMObsSpanRegisterOptions(ctx) - Abstract, must implementsetLLMObsTags(ctx) - Abstract, must implementasyncEnd(ctx) - Calls setLLMObsTagsend(ctx) - Restores contextTagger methods (accessed via this._tagger):
tagLLMIO, tagEmbeddingIO, tagRetrievalIO, tagTextIOtagMetadata, tagMetrics, tagSpanTags, tagPromptLocation: packages/dd-trace/src/llmobs/plugins/openai/index.js
Category: LLM API Client
Characteristics:
messages: [{role, content}])usage.prompt_tokens, usage.completion_tokens)choices[0].message)Good for: Learning basic plugin structure
Location: packages/datadog-plugin-anthropic/src/llmobs.js
Category: LLM API Client
Characteristics:
content: [{type: 'text', text: '...'}])usage.input_tokens, usage.output_tokens)Good for: Handling non-standard message formats
Location: packages/datadog-plugin-google-genai/src/llmobs.js
Category: LLM API Client
Characteristics:
contents: [{role, parts: [{text}]}])candidates[0].content.parts)Good for: Complex nested structures, role normalization
Location: packages/datadog-plugin-ai-sdk/src/llmobs.js
Category: Multi-Provider Framework
Characteristics:
Good for: Provider abstraction patterns
Location: packages/datadog-plugin-langchain-langgraph/src/llmobs.js
Category: Pure Orchestration
Characteristics:
invoke, stream)Good for: Workflow instrumentation, non-LLM span kinds
| Plugin | Category | Format Complexity | Special Features |
|---|---|---|---|
| OpenAI | LLM Client | Simple | Standard reference |
| Anthropic | LLM Client | Medium | Nested content arrays |
| Google GenAI | LLM Client | Complex | Multi-level nesting, role normalization |
| Vercel AI SDK | Multi-Provider | Medium | Provider abstraction |
| LangGraph | Orchestration | Simple | Workflow spans, state management |
// Messages: Simple array
inputs.messages → [{role, content}]
// Response: choices array
results.choices[0].message → {role, content}
// Tokens: Standard names
usage.prompt_tokens, usage.completion_tokens
// Messages: Content blocks
msg.content[0].text → Extract text from blocks
// Response: Content array
results.content.filter(c => c.type === 'text')
// Tokens: Different names
usage.input_tokens, usage.output_tokens
// Messages: Parts format
contents → [{role, parts: [{text}]}]
// Response: Candidates
candidates[0].content.parts → Join text
// Tokens: Mixed names
usageMetadata.promptTokenCount, candidatesTokenCount
// Input: State objects
StateGraph state → Extract relevant fields
// Output: State changes
Track state transitions, not LLM responses
// Span kind: 'workflow' not 'llm'
kind: 'workflow' for graph execution
Pattern: Accumulate deltas from chunk.choices[0].delta.content
Pattern: Accumulate from chunk.delta.text or chunk.content_block.text
Some plugins integrate LLMObs with tracing plugins using CompositePlugin. The plugin class declares a static plugins field mapping keys to plugin classes.
See packages/datadog-plugin-google-genai/src/index.js for a reference implementation.
Test files demonstrate expected span structure and assertions:
Locations:
packages/dd-trace/test/llmobs/plugins/openai/index.spec.jspackages/dd-trace/test/llmobs/plugins/anthropic/index.spec.jspackages/dd-trace/test/llmobs/plugins/google-genai/index.spec.jspackages/dd-trace/test/llmobs/plugins/langchain-langgraph/index.spec.jsbase.js to understand abstract methodsSimple formats (messages array): Use OpenAI pattern
Nested content: Use Anthropic pattern
Multi-level nesting: Use Google pattern
Multiple providers: Use Vercel AI SDK pattern
Orchestration/workflows: Use LangGraph pattern
Streaming: Check OpenAI streaming implementation
CompositePlugin: Check Anthropic integration