> ## Documentation Index
> Fetch the complete documentation index at: https://braintrust.dev/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# UI cache hit rate shows zero with raw metrics

> Fix a 0% cache hit rate in the UI by mapping provider cache token fields to the normalized metrics Braintrust expects from custom logging.

export const plans_0 = "Any"

export const deployments_0 = "Any"

export const data_plane_version_0 = undefined

export const use_case_0 = "Map provider cache token fields to Braintrust metrics when the UI shows a 0% cache hit rate"

<Note>
  **Applies to:**

  * Plan - {plans_0}
  * Deployment - {deployments_0}
  * {data_plane_version_0}
  * {use_case_0}
</Note>

## Summary

The UI can show a 0% cache hit rate when custom logging includes provider cache fields but omits the normalized metrics Braintrust expects. Map the provider fields to `metrics.prompt_cached_tokens` and `metrics.prompt_cache_creation_tokens`.

## What is happening

Braintrust integrations can normalize provider usage fields automatically. With custom logging, raw fields such as `cache_read_input_tokens` and `cache_creation_input_tokens` do not populate the normalized metrics automatically.

Log these metrics on the LLM span:

* `prompt_tokens`, including uncached input, cache reads, and cache creation tokens.
* `completion_tokens`.
* `prompt_cached_tokens` for cache reads.
* `prompt_cache_creation_tokens` for cache writes.

The UI calculates the cache hit rate as `prompt_cached_tokens / prompt_tokens`. If `prompt_cached_tokens` is absent, cached reads are treated as zero. The cache hit label also requires `completion_tokens` to be reported.

This guide assumes the span already reports normalized `prompt_tokens` and `completion_tokens`. If your custom logging only reports provider-specific input and output token fields, normalize those fields too.

The normalized cache metrics also affect cache token breakdowns and cache-aware cost calculations.

## Fix or suggestion

### Option 1: add normalized metrics

Map the provider usage fields to the normalized metrics when you log the span. For an Anthropic-style usage response:

```typescript theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
const usage = response.usage;
const cachedReadTokens = usage.cache_read_input_tokens ?? 0;
const cacheCreationTokens = usage.cache_creation_input_tokens ?? 0;
const promptTokens =
  usage.input_tokens + cachedReadTokens + cacheCreationTokens;

span.log({
  metrics: {
    prompt_tokens: promptTokens,
    completion_tokens: usage.output_tokens,
    prompt_cached_tokens: cachedReadTokens,
    prompt_cache_creation_tokens: cacheCreationTokens,
  },
});
```

The resulting span metrics use the following shape:

```json theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
{
  "prompt_tokens": 1000,
  "completion_tokens": 200,
  "prompt_cached_tokens": 600,
  "prompt_cache_creation_tokens": 100
}
```

<Note>
  `prompt_tokens` includes all input tokens. In this example, the cache hit rate is 60% because 600 of 1,000 prompt tokens were cache reads.
</Note>

### Option 2: use an integration or SDK wrapper

If one is available for your provider, use a Braintrust integration or SDK wrapper that normalizes the usage response. For more information about logging token metrics for a custom client, see [Wrap a custom LLM client](/instrument/advanced-tracing#wrap-a-custom-llm-client).

## How to confirm it worked

1. Export or view the raw span JSON for the affected span and confirm `metrics` includes:
   * `prompt_tokens`.
   * `completion_tokens`.
   * `prompt_cached_tokens`.
   * `prompt_cache_creation_tokens`.

2. Run a SQL query to inspect the normalized metrics:

```sql theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
SELECT
  created,
  id,
  span_id,
  metrics.prompt_tokens,
  metrics.cache_read_input_tokens,
  metrics.cache_creation_input_tokens,
  metrics.prompt_cached_tokens,
  metrics.prompt_cache_creation_tokens
FROM project_logs('<PROJECT_ID>', shape => 'spans')
WHERE created >= now() - INTERVAL 1 DAY
  AND span_attributes.type = 'llm'
ORDER BY created DESC
LIMIT 50
```

If the raw cache fields contain values but the normalized cache metrics are null or zero, update your custom logging.

3. Verify that the UI displays the expected cache hit rate.

## Notes

* This guide applies to custom instrumentation or provider-specific fields that have not been normalized.
