◉GEMINI LABJP
●TTS — The three TTS preview models shut down on 12/18 per the deprecations page, not 11/17●CLI 0.68 — Gemini CLI stable is v0.68.0, with v0.69.0-preview.0 (11/10) on the preview channel●GEMINI 2.5 — gemini-2.5-pro and 2.5-flash shut down on the API on 12/1, 16 days left. Move to 3.8 Flash or 3.5 Flash-Lite●NODE 26 — On Node 26, Gemini CLI's timeout settings reportedly stop applying to model requests●OMNI 1.1 — From 12/3, requests to gemini-omni-1.1-flash are routed to 1.2 Flash automatically●NEW — Getting Consistent JSON Through the OpenAI-Compatible Layer, in Three Steps●TTS — The three TTS preview models shut down on 12/18 per the deprecations page, not 11/17●CLI 0.68 — Gemini CLI stable is v0.68.0, with v0.69.0-preview.0 (11/10) on the preview channel●GEMINI 2.5 — gemini-2.5-pro and 2.5-flash shut down on the API on 12/1, 16 days left. Move to 3.8 Flash or 3.5 Flash-Lite●NODE 26 — On Node 26, Gemini CLI's timeout settings reportedly stop applying to model requests●OMNI 1.1 — From 12/3, requests to gemini-omni-1.1-flash are routed to 1.2 Flash automatically●NEW — Getting Consistent JSON Through the OpenAI-Compatible Layer, in Three Steps
Articles/API / SDK
◈ API / SDK/2026-04-25Advanced

Tracing Gemini API in Production with OpenTelemetry: See Every Step of a Single Request

After three months of running Gemini API in production, plain logs stop telling you why latency, cost, or failures spike. This guide walks through wrapping Gemini in OpenTelemetry — Python and Node.js code, GenAI semantic conventions, sampling, and Grafana/Datadog wiring — so you can see the full anatomy of every request.

gemini-api291opentelemetrytracingobservability14production140

✦ Premium Article

Three months into running Gemini API in production, the access log stopped being enough. Average latency looked fine, error rates looked fine, but real users kept hitting "the spinner just sat there for nine seconds" or "this user's bill jumped 8x overnight." Once I caught myself spending more time crafting Cloud Logging filters than actually finding the bottleneck, I finally introduced OpenTelemetry distributed tracing — and within a week I could explain every awkward request my service made.

This guide is the version of that journey I wish I had read before starting. We will wrap Gemini API calls in OpenTelemetry spans, follow the official GenAI Semantic Conventions, instrument streaming and Function Calling loops, and set up the whole thing so you can swap Grafana Tempo, Jaeger, and Datadog APM behind a single config flag — no vendor lock-in.

Why distributed tracing matters more for Gemini than for ordinary APIs

A backend that calls Gemini behaves quite differently from a CRUD API. A single user request usually fans out into retrieval, vector search, model calls, possible Function Calling loops, and post-processing. Each leg has its own failure mode and latency profile, and aggregate dashboards systematically hide the worst experiences.

Three real failure cases I have personally hit:

  • Average latency stayed at 1.8s, but gemini-2.5-pro calls with long prompts pinned at 12s, leaving the UI spinner running long enough that users thought the page had crashed.
  • Function Calling that was supposed to terminate in one hop occasionally looped to five hops on certain inputs, burning roughly 8x the tokens of a normal request.
  • Vector retrieval flipped between 200ms and 4 seconds depending on the day, and I wasted a week blaming Gemini before realizing the retriever was the problem.

You cannot chase any of these from a histogram. Distributed tracing reframes the problem: each user request becomes a single trace, and every internal step (model call, retrieval, JSON repair, guardrail) becomes a span you can lay out on a timeline. The moment you can replay a slow request frame by frame, the diagnostics conversation goes from speculation to evidence.

OpenTelemetry concepts, framed for a Gemini backend

You only need a handful of concepts before writing code:

  • Trace: the full record of one user request, identified by a single trace_id.
  • Span: the smallest unit inside a trace. Make one per measurable step — a Gemini call, a Pinecone lookup, a JSON validation pass.
  • Context propagation: the wiring that keeps spans nested across services. The HTTP traceparent header is what carries it.
  • Span attributes: key-value tags on each span (token counts, model name, end-user ID).
  • Span events: discrete in-span markers (streaming chunk arrivals, guardrail trips).

OpenTelemetry now publishes GenAI Semantic Conventions that standardize attribute names. Sticking to them is the cheapest insurance you can buy against future migration pain. The ones you will use constantly:

  • gen_ai.system — vendor identifier (google.gemini for our purposes)
  • gen_ai.request.model — the model you asked for (e.g., gemini-2.5-pro)
  • gen_ai.response.model — the model that actually answered (Google occasionally routes)
  • gen_ai.usage.input_tokens / gen_ai.usage.output_tokens — token usage
  • gen_ai.request.temperature, gen_ai.request.top_p, etc. — sampling parameters
  • gen_ai.response.finish_reasons — array of completion reasons

Once every span carries these consistently, your dashboards do not care which backend you ship traces to. You will thank yourself for the discipline six months from now when the on-call rotation changes hands.

✦

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
✦Engineers stuck debugging Gemini latency, runaway cost, or silent retries can stand up span-level tracing today and see exactly where a request spends its time
✦You will learn the OpenTelemetry GenAI semantic conventions and a concrete pattern for emitting tokens, model choice, cache hits, and finish reasons consistently across every call
✦Streaming responses and Function Calling loops included — you can wire the same setup to Grafana Tempo, Jaeger, or Datadog APM without changing application code
Secure payment via Stripe · Cancel anytime
✦

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Gemini Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • ✦Copy-paste ready implementation code
  • ✦New advanced guides published daily
  • ✦$5/mo or $10 for lifetime access
View Membership →

Related Articles

◈ API / SDK2026-04-23
Gemini API × Langfuse — A Production Playbook for LLM Observability
A practical, production-grade guide to wiring Gemini API into Langfuse — tracing architecture, cost attribution, LLM-as-Judge on live traffic, PII masking, and sampling — with runnable code.
◈ API / SDK2026-07-04
When Gemini API Leaks Japanese Into Your English Output Once in a While — Field Notes on Measuring the Contamination Rate and Tightening It in Stages
You told Gemini to answer in English, and 3 out of 100 runs slip a Japanese sentence into the tail. Here is why you cannot stop that 'once in a while', and a production pattern that measures the contamination rate as an SLO and tightens it with graded recovery, with working code.
◈ API / SDK2026-07-15
Sample what you already accepted — an audit budget that catches silent quality drift
A confidence gate only ever looks at output the model hesitated on. Silent drift sinks into the batch that sailed through. Working from a fixed 30-minutes-a-day review budget, this walks through deriving detection time from the binomial, reallocating the same budget across risk strata, and catching slow decay with a cumulative monitor.