How GenAI Cost Tracking Works
Beakpoint calculates per-request costs for Large Language Model (LLM) API calls automatically. If your application is instrumented with OpenTelemetry GenAI semantic conventions and sending spans to Beakpoint, costs are calculated regardless of whether the LLM is called directly, through AWS Bedrock, Azure OpenAI, or Azure AI Foundry.
This page explains the mechanics: how platforms are detected, how model names are resolved to pricing, and how costs are calculated.
Platform Detection
Beakpoint identifies the GenAI platform from span attributes. The primary signal is gen_ai.system (or its newer equivalent gen_ai.provider.name), with server.address used as a secondary signal for implicit Azure detection.
| Platform | How Detected | Resolves To |
|---|---|---|
| OpenAI (direct) | gen_ai.system = openai | openai |
| Anthropic (direct) | gen_ai.system = anthropic | anthropic |
| AWS Bedrock | gen_ai.system = aws.bedrock | Provider extracted from model ID (see below) |
| Azure OpenAI (explicit) | gen_ai.system = azure.ai.openai | openai |
| Azure OpenAI (implicit) | gen_ai.system = openai + server.address ending .openai.azure.com | openai |
| Azure AI Foundry | gen_ai.system = azure.ai.inference or az.ai.inference | Provider inferred from model name (see below) |
gen_ai.system vs gen_ai.provider.name
OpenTelemetry semantic conventions v1.37.0+ introduced gen_ai.provider.name as the replacement for gen_ai.system. Beakpoint accepts both. When both are present, gen_ai.provider.name takes precedence.
Most auto-instrumentation libraries now set gen_ai.provider.name. If your library only sets gen_ai.system, that works too — see the Track LLM Costs guide if you need to backfill the newer attribute.
Model Name Normalization
Model IDs vary across platforms and SDK versions. Beakpoint normalizes them before looking up pricing:
| Normalization | Example | Result |
|---|---|---|
| OpenAI date suffixes stripped | gpt-5.4-mini-2026-01-15 | gpt-5.4-mini |
| Anthropic date suffixes stripped | claude-sonnet-4-20250514 | claude-sonnet-4 |
| Bedrock version suffixes stripped | anthropic.claude-sonnet-4-20250514-v1:0 | claude-sonnet-4 |
| Bedrock cross-region prefixes stripped | us.anthropic.claude-sonnet-4-v1:0 | claude-sonnet-4 |
| Legacy Anthropic aliases resolved | claude-3-5-sonnet | claude-sonnet-4 |
You never need to normalize model IDs yourself — pass the ID exactly as your SDK provides it.
AWS Bedrock Model ID Parsing
Bedrock model IDs follow a specific format: [region.]provider.model-name[-date]-v{version}[:{variant}]
The pricing engine automatically:
- Strips cross-region prefixes —
us.,eu.,apac.,global.,us-gov.— sous.anthropic.claude-sonnet-4-20250514-v1:0resolves the same asanthropic.claude-sonnet-4-20250514-v1:0 - Extracts the provider — the segment before the first
.(e.g.anthropic,amazon,meta,mistral,cohere) - Strips version suffixes —
-v1:0,-v2:0, etc. - Strips date suffixes —
-20250514, etc. - Resolves to the canonical model — e.g.
anthropic.claude-sonnet-4-20250514-v1:0→ provideranthropic, modelclaude-sonnet-4
Azure AI Foundry Provider Inference
Azure AI Foundry (AI Inference) is a multi-model gateway. Since gen_ai.system identifies the gateway rather than the underlying provider, Beakpoint infers the provider from the model name:
| Model name pattern | Resolved provider |
|---|---|
Contains gpt, or starts with o1, o3, o4 | openai |
Starts with claude | anthropic |
Starts with mistral, codestral, ministral, pixtral | mistral |
Starts with meta-llama, llama | meta |
Starts with cohere, command | cohere |
Starts with jamba, ai21 | ai21 |
Starts with phi | microsoft |
| Anything else | azure.ai.inference (fallback) |
Cost Calculation
Once the platform is detected and the model ID is normalized, cost is calculated using per-million-token rates from Beakpoint's pricing tables:
cost = (input_tokens / 1,000,000 × input_price) + (output_tokens / 1,000,000 × output_price)
where input_price and output_price are per-million-token rates for the detected model.
For models that support prompt caching (Anthropic, OpenAI), cache token counters are applied at their respective rates when present.
Costs are calculated on the parent GenAI span — the one carrying gen_ai.request.model, gen_ai.usage.input_tokens, and gen_ai.usage.output_tokens. This prevents double-counting when child spans (e.g., retry logic) duplicate token counters.
Required Span Attributes
Across all platforms, the pricing engine reads these attributes:
| Attribute | Required? | Description |
|---|---|---|
gen_ai.system | Yes (or gen_ai.provider.name) | Identifies the platform |
gen_ai.request.model | Yes | Model ID as sent to the provider |
gen_ai.usage.input_tokens | Yes | Input/prompt token count |
gen_ai.usage.output_tokens | Yes | Output/completion token count |
gen_ai.response.model | Optional | Fallback if gen_ai.request.model is absent |
server.address | Optional | Used for implicit Azure OpenAI and Azure AI Foundry detection |
For platform-specific optional attributes (prompt cache tokens, reasoning tokens), see the reference pages under GenAI / LLM cost calculation tags.
Next Steps
- Track LLM Costs — step-by-step setup guide for all platforms
- OpenAI cost tags — supported models and pricing
- Anthropic Claude cost tags — supported models and pricing
- AWS Bedrock cost tags — Bedrock-specific models and pricing
- Azure OpenAI cost tags — Azure OpenAI detection and pricing
- Azure AI Foundry cost tags — AI Foundry detection and pricing