This guide covers OpenTelemetry for LLMs with production-focused examples and trade-offs.
When an IDE agent feels “slow,” the bottleneck might be retrieval, a tool Lambda cold start, Bedrock queueing, or your own JSON schema validator. Without distributed traces, teams guess and scale the wrong tier. OpenTelemetry for LLM workflows means W3C trace context across every hop — proxy, tools, Bedrock, and databases — with attributes that make token latency debuggable.⚡ TL;DR: Start a root span per user action (agent.turn). Propagatetraceparentthrough HTTP, SQS, and Bedrock request metadata. Recordgen_ai.*attributes (model, input/output tokens, cache hit). Tail-sample errors and slow turns. Illustrative debug win: cut MTTR for “assistant p99 > 8s” from hours to minutes by seeing tool vs model breakdown.
Span model for an agent turn — OpenTelemetry for LLMs
agent.turn (root)
├─ context.assemble
├─ retrieve.kb
├─ gen_ai.chat (Bedrock Converse)
│ └─ gen_ai.tool.search_repo
│ └─ aws.lambda.invoke
└─ patch.validate
import { trace, SpanStatusCode, context, propagation } from "@opentelemetry/api";
const tracer = trace.getTracer("cheatcoders-agent");
export async function runTurn(userId: string, prompt: string) {
return tracer.startActiveSpan("agent.turn", async (span) => {
span.setAttribute("user.id", userId);
span.setAttribute("agent.prompt_chars", prompt.length);
try {
const answer = await converseWithTools(prompt);
span.setStatus({ code: SpanStatusCode.OK });
return answer;
} catch (err) {
span.recordException(err as Error);
span.setStatus({ code: SpanStatusCode.ERROR });
throw err;
} finally {
span.end();
}
});
}
Instrument Bedrock with gen_ai attributes
import {
BedrockRuntimeClient,
ConverseCommand,
} from "@aws-sdk/client-bedrock-runtime";
export async function converse(modelId: string, messages: any[]) {
return tracer.startActiveSpan("gen_ai.chat", async (span) => {
span.setAttribute("gen_ai.system", "aws.bedrock");
span.setAttribute("gen_ai.request.model", modelId);
const started = Date.now();
const resp = await new BedrockRuntimeClient({}).send(
new ConverseCommand({
modelId,
messages,
inferenceConfig: { maxTokens: 2048 },
})
);
span.setAttribute("gen_ai.response.model", modelId);
span.setAttribute("gen_ai.usage.input_tokens", resp.usage?.inputTokens ?? 0);
span.setAttribute("gen_ai.usage.output_tokens", resp.usage?.outputTokens ?? 0);
span.setAttribute("gen_ai.latency_ms", Date.now() - started);
span.end();
return resp;
});
}
Propagate across queues and AppSync
// Inject W3C headers when enqueueing tool work
const carrier: Record<string, string> = {};
propagation.inject(context.active(), carrier);
await sqs.send({
QueueUrl,
MessageBody: JSON.stringify({ args }),
MessageAttributes: {
traceparent: { DataType: "String", StringValue: carrier["traceparent"] },
},
});
propagation.extract before starting the child span. Missing this link is why service maps “lie” during incidents.
Tail sampling and cost
At IDE volume you cannot keep 100% of successful fast turns.# illustrative collector policy
policies:
- name: errors
type: status_code
status_code: ERROR
- name: slow-agent
type: latency
threshold_ms: 5000
- name: baseline
type: probabilistic
sampling_percentage: 5
gen_ai.chat p95 and tool error rates — not just host CPU. Pair with LLM cost controls so latency and spend dashboards sit side by side.
Correlate IDE, CI, and cloud backends
Developers feel latency in the IDE; the spans often live in CI runners and AWS. Carry asession.id / pr.number baggage key from the first hop:
import { propagation, context } from "@opentelemetry/api";
export function withPrBaggage<T>(pr: number, fn: () => Promise<T>) {
// Use baggage API in your SDK version; illustrative attribute mirror:
return tracer.startActiveSpan("ci.agent.job", async (span) => {
span.setAttribute("ci.pr", pr);
span.setAttribute("ci.pipeline", process.env.GITHUB_WORKFLOW ?? "local");
try {
return await fn();
} finally {
span.end();
}
});
}
gen_ai.request.model and tool.name before blaming “Bedrock is slow.” Cold tool Lambdas show up as child gaps — fix with provisioned concurrency schedules, not bigger models. Pair with Lambda cold-start discipline when tools run on Lambda.
Closing checklist
✅ Dos – ✅ One root span per agent turn with stable name – ✅ Record model, tokens, cache hit, tool name attributes – ✅ Propagatetraceparent across HTTP, SQS, Lambda
– ✅ Tail-sample errors and slow turns
– ✅ Dashboard tool vs model latency breakdown
❌ Don’ts
– ❌ Don’t log raw prompts containing secrets into span attributes
– ❌ Don’t rely on logs alone for cross-service LLM latency
– ❌ Don’t sample only at the edge and lose tool children
– ❌ Don’t attach megabytes of retrieval chunks onto spans
– ❌ Don’t forget AppSync/API Gateway header allowlists for trace context
Related reading
- Amazon Bedrock Agents: Tool Use, Memory, and Production Guardrails
- LLM Coding Agents on AWS: Safe Tool Sandboxes with Lambda
- LLM Cost Controls: Token Budgets Per PR and Per Engineer (companion)
- Node.js Event Loop Lag: Catch p99 Stalls Before Users Feel Them
Related: Day 39: Observability: Traces Across Prompt, Retrieval, Tools · Bedrock Prompt Caching (and Batch Inference): Cut Latency and Cost · Microservices vs Monolith: When to Split and When to Stay Merged
Related: Day 72: Prompt Caching Pitfalls · Prompt Engineering for Developers: The Patterns That 10x Your AI Coding Output · Prompt Engineering for Developers: Patterns That Produce Production-Ready Code Every Time
Watch: 100 Days of AI on YouTube
Short videos from CheatCoders, one AI engineering topic per day.
Most viewed
- Python Decorators Explained: From Simple Wrappers to Production Patterns
- Claude Code vs Cursor vs GitHub Copilot: Choose by Workflow, and Set Up One Repo That Works With All Three
- AI Agent Frameworks in 2025: LangGraph vs CrewAI vs AutoGen vs Raw API
- Python String Methods: Every str Method With Real Production Examples
- Css Animation Performance: Performance-Optimized Motion for Modern UIs
Newly added
- AWS Systems Manager Parameter Store: Hierarchical Runtime Config for Coding Agents
- Amazon Cognito Identity Pools: Federate Coding-Agent Tool Callers Without Long-Lived Keys
- Amazon Athena for Coding Agents: Query Tool Audit Logs and Eval Traces on S3 Without a Warehouse
- AWS Batch for Coding Agents: Parallel Overnight PR Reviews and Long-Running Jobs Without Lambda Timeouts
- Amazon Bedrock Prompt Management: Version and A/B Test Coding-Agent System Prompts
Deep-dive PDF
Get the expanded guide for this post — extra diagrams-style checklists, failure modes, and a production walkthrough. Free when you subscribe to CheatCoders.
Already subscribed? or open the subscribe page.
Discover more from CheatCoders
Subscribe to get the latest posts sent to your email.

Pingback: Lambda SnapStart for Python: Pitfalls Beyond the Java Marketing - CheatCoders
Pingback: Node Worker Threads: SharedArrayBuffer Protocols Without Data Races - CheatCoders
Pingback: Lambda Log Buffering: Cut CloudWatch Ingestion Without Losing Correlation - CheatCoders