Skip to content

llmobs: add MetricKey constants for cache breakdown and other token metrics (parity with dd-trace-py) #4769

@dohyun-ko

Description

@dohyun-ko

Summary

llmobs/option.go only exposes three token metric keys as typed constants:

MetricKeyInputTokens  = \"input_tokens\"
MetricKeyOutputTokens = \"output_tokens\"
MetricKeyTotalTokens  = \"total_tokens\"

The Python SDK (ddtrace/llmobs/_constants.py) defines a broader, standardised set that the Datadog LLM Observability backend recognises for built-in dashboards (cache breakdown widget, cost monitors, etc.):

Python const Value
INPUT_TOKENS_METRIC_KEY input_tokens
OUTPUT_TOKENS_METRIC_KEY output_tokens
TOTAL_TOKENS_METRIC_KEY total_tokens
CACHE_READ_INPUT_TOKENS_METRIC_KEY cache_read_input_tokens
CACHE_WRITE_INPUT_TOKENS_METRIC_KEY cache_write_input_tokens
CACHE_WRITE_1H_INPUT_TOKENS_METRIC_KEY ephemeral_1h_input_tokens
CACHE_WRITE_5M_INPUT_TOKENS_METRIC_KEY ephemeral_5m_input_tokens
REASONING_OUTPUT_TOKENS_METRIC_KEY reasoning_output_tokens
BILLABLE_CHARACTER_COUNT_METRIC_KEY billable_character_count
TIME_TO_FIRST_TOKEN_METRIC_KEY time_to_first_token

In dd-trace-go, callers currently have to write these as string literals — losing typo safety and discoverability:

opts = append(opts, llmobs.WithAnnotatedMetrics(map[string]float64{
    llmobs.MetricKeyInputTokens: float64(input),
    \"cache_read_input_tokens\": float64(cacheRead),  // no constant
    \"cache_write_input_tokens\": float64(cacheWrite),
}))

Proposal

Add typed constants in llmobs/option.go next to the existing trio:

const (
    // existing
    MetricKeyInputTokens  = \"input_tokens\"
    MetricKeyOutputTokens = \"output_tokens\"
    MetricKeyTotalTokens  = \"total_tokens\"

    // new
    MetricKeyCacheReadInputTokens     = \"cache_read_input_tokens\"
    MetricKeyCacheWriteInputTokens    = \"cache_write_input_tokens\"
    MetricKeyEphemeral1HInputTokens   = \"ephemeral_1h_input_tokens\"
    MetricKeyEphemeral5MInputTokens   = \"ephemeral_5m_input_tokens\"
    MetricKeyReasoningOutputTokens    = \"reasoning_output_tokens\"
    MetricKeyBillableCharacterCount   = \"billable_character_count\"
    MetricKeyTimeToFirstToken         = \"time_to_first_token\"
)

Motivation

We instrument Anthropic prompt caching and need to push cache_read_input_tokens / cache_write_input_tokens to enable the Datadog cache breakdown dashboard. Currently we use string literals, which is fine functionally but loses parity with the Python SDK and adds a code review burden every time a new metric key is added on the backend side.

Happy to send a PR if this is welcome. Per CONTRIBUTING.md I'm opening this issue first to discuss.

References

Metadata

Metadata

Assignees

Labels

proposalmore in depth change that requires full team approvalproposal/acceptedAccepted proposals

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions