You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(llmobs): sampling decisions, rates, and propagation (#9030)
* feat(llmobs): add sampling decisions, rates, and propagation
Compute a keep/drop decision + rate once on the root LLMObs span and
inherit it across spans and services (via x-datadog-tags). Spans are
always shipped; the decision is recorded in the event _dd block so the
backend can honor it. Mirrors dd-trace-py.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* refactor(llmobs): address sampling PR review comments
- Match dd-trace-py: only the true trace root makes a fresh sampling
decision; a span under a propagated LLMObs parent inherits whatever
was propagated (possibly none) instead of starting a divergent one.
- Reuse the shared formatKnuthRate (hoisted to sampler.js) instead of a
bespoke llmobs formatRate.
- Rename handleLLMObsParentIdInjection -> handleLLMObsInjection.
- Declare llmobs.sampleRate in the public index.d.ts (fixes config-names
lint) and tag sample_rate on enablement telemetry.
- Drop redundant comments flagged in review.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* chore(llmobs): regenerate config types after merging master
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* refactor(llmobs): address follow-up sampling review comments
- Rebuild the sampler lazily from the live config rate so a disable/
re-enable (or any rate change) is reflected, instead of caching one
sampler at construction.
- Tweak the injection comment wording.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* refactor(llmobs): export formatKnuthRate from priority_sampler.js
Keep the formatter in priority_sampler.js (export it) instead of
hoisting to sampler.js, per review.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* refactor(llmobs): build the sampler once in the tagger constructor
The sample rate is set at init and not mutable at runtime, so the
per-span lazy rebuild was unnecessary work on a hot path. Build it once
at construction.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* Update packages/dd-trace/src/llmobs/tagger.js
* refactor(llmobs): address sampling review comments and make sampler config-reactive
- Mirror `llmobs.sampleRate` in the v5 type declarations (index.d.v5.ts), per
the repo type policy requiring non-v6-only public APIs in both declaration
surfaces (PR review).
- Register DD_LLMOBS_SAMPLE_RATE as implementation "A" in
supported-configurations.json (PR review); generated types are unchanged.
- Build the LLMObs sampler lazily and rebuild it when config.llmobs.sampleRate
changes, instead of fixing it for the tagger's lifetime, so a future remote
config update to the sample rate takes effect without re-instantiation.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(llmobs): match DD_LLMOBS_SAMPLE_RATE default to config registry (1.0)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* refactor(llmobs): address remaining sampling review comments
- Drop the redundant #samplerRate field; use sampler.rate() for the rebuild check.
- Move formatKnuthRate to the shared src/util.js so the LLMObs tagger no longer
imports priority_sampler just for a string formatter.
- Reword the sampleRate JSDoc in index.d.ts and index.d.v5.ts ("honored at
ingestion time").
- Test rates that exercise the formatter: 1/3 (6-decimal cap) and 0.25
(trailing-zero stripping).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
0 commit comments