Skip to content

feat(datadog): emit litellm.overhead.latency as a standalone Datadog metric#28548

Merged
ishaan-berri merged 4 commits into
BerriAI:litellm_shin_may21_2from
oss-agent-shin:feat/datadog-overhead-metric
May 22, 2026
Merged

feat(datadog): emit litellm.overhead.latency as a standalone Datadog metric#28548
ishaan-berri merged 4 commits into
BerriAI:litellm_shin_may21_2from
oss-agent-shin:feat/datadog-overhead-metric

Conversation

@oss-agent-shin

Copy link
Copy Markdown
Contributor

Summary

Closes LIT-3203 — emit LiteLLM overhead as a Datadog metric.

litellm_overhead_time_ms (= total request time − LLM-API time) was already:

  • computed in ResponseMetadata and stored in hidden_params
  • exposed in StandardLoggingPayload.hidden_params
  • emitted by the Prometheus integration as litellm_overhead_latency_metric
  • embedded in Datadog LLM Observability span metadata

What was missing: a standalone time-series metric sent to the Datadog Metrics API (/api/v2/series) — the same path that already carries litellm.request.total_latency and litellm.llm_api.latency.

Changes

litellm/integrations/datadog/datadog_metrics.py

  • _add_metrics_from_log() now reads hidden_params["litellm_overhead_time_ms"] from the StandardLoggingPayload
  • If the value is present, a new gauge series litellm.overhead.latency (value in seconds, consistent with other latency metrics) is appended to the queue
  • Tags match the other latency metrics (provider, model, team, env, service, version) — status_code is intentionally omitted (it's a latency metric, not a request-count)

tests/test_litellm/integrations/datadog/test_datadog_metrics.py

  • test_overhead_latency_metric_emitted — verifies the metric is emitted with the correct value (250 ms → 0.25 s) and correct tags
  • test_overhead_latency_metric_absent_when_no_hidden_params — verifies no metric is emitted when hidden_params has no overhead value
  • Updated existing test_add_metrics_from_log comment to clarify why it still expects exactly 3 series

Test plan

uv run pytest tests/test_litellm/integrations/datadog/test_datadog_metrics.py -v

All 12 tests pass:

tests/test_litellm/integrations/datadog/test_datadog_metrics.py::test_add_metrics_from_log PASSED
tests/test_litellm/integrations/datadog/test_datadog_metrics.py::test_overhead_latency_metric_emitted PASSED
tests/test_litellm/integrations/datadog/test_datadog_metrics.py::test_overhead_latency_metric_absent_when_no_hidden_params PASSED
... (12/12 passed in 0.39s)

🤖 Generated with Claude Code

shin-berri and others added 4 commits May 13, 2026 22:37
chore(ci): promote internal staging to main
…metric

Adds a new `litellm.overhead.latency` gauge metric to `DatadogMetricsLogger`
(the `/api/v2/series` path). The value is sourced from
`hidden_params["litellm_overhead_time_ms"]` already computed in
`ResponseMetadata` and exposed in `StandardLoggingPayload`.

Matches the Prometheus integration which exposes the same value via
`litellm_overhead_latency_metric`. Emitted in seconds (ms ÷ 1000) for
consistency with the other latency series.

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.


Shin seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.
You have signed the CLA already but the status is still pending? Let us recheck it.

@codspeed-hq

codspeed-hq Bot commented May 22, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 16 untouched benchmarks


Comparing oss-agent-shin:feat/datadog-overhead-metric (845d048) with main (79b4578)

Open in CodSpeed

@greptile-apps

greptile-apps Bot commented May 22, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds litellm.overhead.latency as a new standalone Datadog time-series gauge metric, complementing the existing litellm.request.total_latency and litellm.llm_api.latency series. The value is sourced from the already-computed litellm_overhead_time_ms field in hidden_params and converted from milliseconds to seconds to stay consistent with the other latency metrics.

  • _add_metrics_from_log in datadog_metrics.py reads hidden_params[\"litellm_overhead_time_ms\"] and conditionally appends the new gauge series; the metric is skipped when the field is absent, preserving backward compatibility.
  • Two new mock-only unit tests cover the emitted and absent cases, and the existing test_add_metrics_from_log comment is updated to explain why it still expects exactly 3 series.

Confidence Score: 4/5

The change is additive and gated on the presence of a single field in hidden_params; existing metrics are unaffected and the new metric is safe to merge.

The implementation is correct and well-tested. The only notable issue is that _extract_tags is called a second time to build the overhead metric's tag set when the result is just the already-computed tags list with status_code filtered out — a minor redundancy with a small maintenance risk if new tags are added to _extract_tags in the future.

Only datadog_metrics.py warrants a second look for the redundant _extract_tags call; the test file is clean.

Important Files Changed

Filename Overview
litellm/integrations/datadog/datadog_metrics.py Adds litellm.overhead.latency gauge metric by reading hidden_params["litellm_overhead_time_ms"] from the StandardLoggingPayload; logic is correct but _extract_tags is called a second time unnecessarily when a simple filter on the already-computed tags list would suffice.
tests/test_litellm/integrations/datadog/test_datadog_metrics.py Adds two focused unit tests for the new overhead latency metric (presence and absence paths), uses mocks only (no real network calls), and correctly updates the existing test comment. Coverage is solid.

Reviews (1): Last reviewed commit: "feat(datadog): emit litellm.overhead.lat..." | Re-trigger Greptile

Comment on lines +147 to +151
# 3. LiteLLM Overhead Latency Metric (total - llm_api time)
hidden_params = log.get("hidden_params", {}) or {}
litellm_overhead_time_ms = hidden_params.get("litellm_overhead_time_ms")
if litellm_overhead_time_ms is not None:
overhead_tags = self._extract_tags(log) # no status_code on latency metric

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 The overhead metric calls _extract_tags a second time, but the result is simply tags (computed at line 117) minus the status_code entry. This creates both an unnecessary second traversal of the payload and a subtle maintenance risk: any future tag added in _extract_tags will be picked up by the two existing latency series but may be silently missing from the overhead series if developers forget to consider this secondary call site. Building overhead_tags by filtering the already-computed tags list is cheaper and keeps both derivations in sync.

Suggested change
# 3. LiteLLM Overhead Latency Metric (total - llm_api time)
hidden_params = log.get("hidden_params", {}) or {}
litellm_overhead_time_ms = hidden_params.get("litellm_overhead_time_ms")
if litellm_overhead_time_ms is not None:
overhead_tags = self._extract_tags(log) # no status_code on latency metric
# 3. LiteLLM Overhead Latency Metric (total - llm_api time)
hidden_params = log.get("hidden_params", {}) or {}
litellm_overhead_time_ms = hidden_params.get("litellm_overhead_time_ms")
if litellm_overhead_time_ms is not None:
# Reuse the already-computed tags, dropping status_code (overhead is a
# pure latency signal, not tied to a request outcome).
overhead_tags = [t for t in tags if not t.startswith("status_code:")]

@codecov

codecov Bot commented May 22, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@ishaan-berri ishaan-berri changed the base branch from main to litellm_shin_may21_2 May 22, 2026 04:06
@ishaan-berri ishaan-berri merged commit e892e8f into BerriAI:litellm_shin_may21_2 May 22, 2026
41 of 45 checks passed
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.

5 participants