Skip to content

feat(ai): Add ModelMetadata config with context size and utilization#5814

Open
constantinius wants to merge 5 commits intomasterfrom
constantinius/feat/event-normalization/model-context-usage
Open

feat(ai): Add ModelMetadata config with context size and utilization#5814
constantinius wants to merge 5 commits intomasterfrom
constantinius/feat/event-normalization/model-context-usage

Conversation

@constantinius
Copy link
Copy Markdown
Contributor

@constantinius constantinius commented Apr 10, 2026

Closes https://linear.app/getsentry/issue/TET-2220/relay-implement-context-window-usage-per-span

Introduce a new llmModelMetadata global config that extends the existing model cost data with context window size. The new ModelMetadata struct replaces ModelCosts throughout the normalization pipeline, with ModelCosts only retained for backwards-compatible deserialization on GlobalConfig. This config and its schema is introduced is introduced in getsentry/sentry#112656

When ai_model_metadata is present it is used entirely; otherwise ai_model_costs is converted to the new format as a fallback.

For each AI span, if the model has a configured context size, set gen_ai.context.window_size and compute gen_ai.context.utilization as total_tokens / context_window_size. These fields were introduced with getsentry/sentry-conventions#315

Co-Authored-By: Claude [email protected]

Introduce a new `llmModelMetadata` global config that extends the existing model cost data with context window size. The new `ModelMetadata` struct replaces `ModelCosts` throughout the normalization pipeline, with `ModelCosts` only retained for backwards-compatible deserialization on GlobalConfig.

When `ai_model_metadata` is present it is used entirely; otherwise `ai_model_costs` is converted to the new format as a fallback.

For each AI span, if the model has a configured context size, set `gen_ai.context.window_size` and compute `gen_ai.context.utilization` as `total_tokens / context_window_size`.

Co-Authored-By: Claude <[email protected]>
@constantinius constantinius requested a review from a team as a code owner April 10, 2026 17:19
@linear-code
Copy link
Copy Markdown

linear-code bot commented Apr 10, 2026

@constantinius constantinius requested a review from a team April 10, 2026 17:35
input_cache_write_per_token: 0.0,
}),
context_size: None,
},
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Bug: The NormalizeSpanConfig is cloned for every span, causing a potentially expensive HashMap clone in a tight loop, which may degrade performance under high load.
Severity: MEDIUM

Suggested Fix

Pass NormalizeSpanConfig by reference instead of by value to the normalization function. This will avoid the expensive HashMap clone for every span, replacing it with a cheap reference copy.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.

Location: relay-event-normalization/src/event.rs#L2329

Potential issue: The `NormalizeSpanConfig` struct, which contains an owned
`Option<ModelMetadata>` wrapping a `HashMap`, is cloned for every individual span during
processing. This occurs within a loop that iterates over all spans in an envelope.
Cloning a `HashMap` is an expensive operation that allocates new memory and copies all
its elements. When processing envelopes with a high volume of spans and configured model
metadata, this repeated cloning can lead to significant CPU and memory pressure, causing
performance degradation.

Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit c5f4e71. Configure here.

/// Configuration for AI model cost calculation
ai_model_costs: Option<&'a ModelCosts>,
/// Metadata for AI models including costs and context size.
ai_model_metadata: Option<ModelMetadata>,
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Per-span deep clone of ModelMetadata HashMap

Low Severity

The ai_model_metadata field changed from Option<&'a ModelCosts> (a borrowed reference) to Option<ModelMetadata> (an owned value containing a HashMap<Pattern, ModelMetadataEntry>). Since NormalizeSpanConfig is .clone()'d for every span item in the envelope (line 106), the entire HashMap — including heap-allocated Pattern keys with internal Strings — is deep-cloned per span. The previous code only cloned a pointer. For envelopes with many spans this introduces unnecessary allocations.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit c5f4e71. Configure here.

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.

1 participant