diff --git a/containers/api-proxy/otel.js b/containers/api-proxy/otel.js index 286cce7b2..ded43aeef 100644 --- a/containers/api-proxy/otel.js +++ b/containers/api-proxy/otel.js @@ -449,17 +449,17 @@ function setTokenAttributes(span, { provider, model, normalizedUsage, streaming 'gen_ai.usage.input_tokens': normalizedUsage.input_tokens, 'gen_ai.usage.output_tokens': normalizedUsage.output_tokens, 'gen_ai.request.stream': streaming, - // Cache and reasoning as strings (Sentry drops unknown numeric attrs but keeps strings) - 'awf.cache_read_tokens': String(normalizedUsage.cache_read_tokens), - 'awf.cache_write_tokens': String(normalizedUsage.cache_write_tokens), - 'awf.reasoning_tokens': String(normalizedUsage.reasoning_tokens || 0), + // Cache and reasoning as strings — avoid "token" in name (Sentry PII scrubber redacts it) + 'awf.cached_read': String(normalizedUsage.cache_read_tokens), + 'awf.cached_write': String(normalizedUsage.cache_write_tokens), + 'awf.reasoning': String(normalizedUsage.reasoning_tokens || 0), }); span.addEvent('gen_ai.usage', { 'gen_ai.usage.input_tokens': normalizedUsage.input_tokens, 'gen_ai.usage.output_tokens': normalizedUsage.output_tokens, - 'awf.cache_read_tokens': String(normalizedUsage.cache_read_tokens), - 'awf.cache_write_tokens': String(normalizedUsage.cache_write_tokens), - 'awf.reasoning_tokens': String(normalizedUsage.reasoning_tokens || 0), + 'awf.cached_read': String(normalizedUsage.cache_read_tokens), + 'awf.cached_write': String(normalizedUsage.cache_write_tokens), + 'awf.reasoning': String(normalizedUsage.reasoning_tokens || 0), }); } catch { /* best-effort */ } } diff --git a/containers/api-proxy/otel.test.js b/containers/api-proxy/otel.test.js index 8d655eccb..afc8f0405 100644 --- a/containers/api-proxy/otel.test.js +++ b/containers/api-proxy/otel.test.js @@ -235,16 +235,16 @@ describe('otel — setTokenAttributes', () => { expect(s.attributes['gen_ai.response.model']).toBe('gpt-4o'); expect(s.attributes['gen_ai.usage.input_tokens']).toBe(1000); expect(s.attributes['gen_ai.usage.output_tokens']).toBe(500); - expect(s.attributes['awf.cache_read_tokens']).toBe('200'); - expect(s.attributes['awf.cache_write_tokens']).toBe('50'); + expect(s.attributes['awf.cached_read']).toBe('200'); + expect(s.attributes['awf.cached_write']).toBe('50'); expect(s.attributes['gen_ai.request.stream']).toBe(false); const usageEvent = s.events.find(e => e.name === 'gen_ai.usage'); expect(usageEvent).toBeDefined(); expect(usageEvent.attributes['gen_ai.usage.input_tokens']).toBe(1000); expect(usageEvent.attributes['gen_ai.usage.output_tokens']).toBe(500); - expect(usageEvent.attributes['awf.cache_read_tokens']).toBe('200'); - expect(usageEvent.attributes['awf.cache_write_tokens']).toBe('50'); + expect(usageEvent.attributes['awf.cached_read']).toBe('200'); + expect(usageEvent.attributes['awf.cached_write']).toBe('50'); }); test('does not set gen_ai.response.model when model is "unknown"', async () => {