diff --git a/src/Libraries/Microsoft.Extensions.AI/ChatCompletion/OpenTelemetryChatClient.cs b/src/Libraries/Microsoft.Extensions.AI/ChatCompletion/OpenTelemetryChatClient.cs index 264832508ae..bbe684bb7bd 100644 --- a/src/Libraries/Microsoft.Extensions.AI/ChatCompletion/OpenTelemetryChatClient.cs +++ b/src/Libraries/Microsoft.Extensions.AI/ChatCompletion/OpenTelemetryChatClient.cs @@ -570,6 +570,11 @@ private void TraceResponse( _ = activity.AddTag(OpenTelemetryConsts.GenAI.Usage.OutputTokens, (int)outputTokens); } + if (response.Usage?.CachedInputTokenCount is long cachedInputTokens) + { + _ = activity.AddTag(OpenTelemetryConsts.GenAI.Usage.CacheReadInputTokens, (int)cachedInputTokens); + } + // Log all additional response properties as raw values on the span. // Since AdditionalProperties has undefined meaning, we treat it as potentially sensitive data. if (EnableSensitiveData && response.AdditionalProperties is { } props) diff --git a/src/Libraries/Microsoft.Extensions.AI/OpenTelemetryConsts.cs b/src/Libraries/Microsoft.Extensions.AI/OpenTelemetryConsts.cs index fa7e36333ce..d2fefa64002 100644 --- a/src/Libraries/Microsoft.Extensions.AI/OpenTelemetryConsts.cs +++ b/src/Libraries/Microsoft.Extensions.AI/OpenTelemetryConsts.cs @@ -138,6 +138,7 @@ public static class Usage { public const string InputTokens = "gen_ai.usage.input_tokens"; public const string OutputTokens = "gen_ai.usage.output_tokens"; + public const string CacheReadInputTokens = "gen_ai.usage.cache_read.input_tokens"; } } diff --git a/test/Libraries/Microsoft.Extensions.AI.Tests/ChatCompletion/OpenTelemetryChatClientTests.cs b/test/Libraries/Microsoft.Extensions.AI.Tests/ChatCompletion/OpenTelemetryChatClientTests.cs index e7206b05ff5..f67c62f0ed4 100644 --- a/test/Libraries/Microsoft.Extensions.AI.Tests/ChatCompletion/OpenTelemetryChatClientTests.cs +++ b/test/Libraries/Microsoft.Extensions.AI.Tests/ChatCompletion/OpenTelemetryChatClientTests.cs @@ -44,6 +44,7 @@ public async Task ExpectedInformationLogged_Async(bool enableSensitiveData, bool InputTokenCount = 10, OutputTokenCount = 20, TotalTokenCount = 42, + CachedInputTokenCount = 5, }, AdditionalProperties = new() { @@ -84,6 +85,7 @@ async static IAsyncEnumerable CallbackAsync( InputTokenCount = 10, OutputTokenCount = 20, TotalTokenCount = 42, + CachedInputTokenCount = 5, })], AdditionalProperties = new() { @@ -180,6 +182,7 @@ async static IAsyncEnumerable CallbackAsync( Assert.Equal("""["stop"]""", activity.GetTagItem("gen_ai.response.finish_reasons")); Assert.Equal(10, activity.GetTagItem("gen_ai.usage.input_tokens")); Assert.Equal(20, activity.GetTagItem("gen_ai.usage.output_tokens")); + Assert.Equal(5, activity.GetTagItem("gen_ai.usage.cache_read.input_tokens")); Assert.Equal(enableSensitiveData ? "abcdefgh" : null, activity.GetTagItem("system_fingerprint")); Assert.Equal(enableSensitiveData ? "value2" : null, activity.GetTagItem("AndSomethingElse"));