From cb6ebbecc2a8be8dabb68011d3abe47bdaed50bb Mon Sep 17 00:00:00 2001 From: "g.verdier" Date: Fri, 10 Oct 2025 10:34:26 +0200 Subject: [PATCH] Give FunctionInvokingChatClient span a more OTELy name --- .../ChatCompletion/FunctionInvokingChatClient.cs | 4 ++-- .../Microsoft.Extensions.AI/OpenTelemetryConsts.cs | 1 + .../ChatCompletion/FunctionInvokingChatClientTests.cs | 8 ++++---- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/Libraries/Microsoft.Extensions.AI/ChatCompletion/FunctionInvokingChatClient.cs b/src/Libraries/Microsoft.Extensions.AI/ChatCompletion/FunctionInvokingChatClient.cs index febf0a1336e..ff71e9f83ed 100644 --- a/src/Libraries/Microsoft.Extensions.AI/ChatCompletion/FunctionInvokingChatClient.cs +++ b/src/Libraries/Microsoft.Extensions.AI/ChatCompletion/FunctionInvokingChatClient.cs @@ -269,7 +269,7 @@ public override async Task GetResponseAsync( // A single request into this GetResponseAsync may result in multiple requests to the inner client. // Create an activity to group them together for better observability. - using Activity? activity = _activitySource?.StartActivity($"{nameof(FunctionInvokingChatClient)}.{nameof(GetResponseAsync)}"); + using Activity? activity = _activitySource?.StartActivity(OpenTelemetryConsts.GenAI.OrchestrateToolsName); // Copy the original messages in order to avoid enumerating the original messages multiple times. // The IEnumerable can represent an arbitrary amount of work. @@ -408,7 +408,7 @@ public override async IAsyncEnumerable GetStreamingResponseA // A single request into this GetStreamingResponseAsync may result in multiple requests to the inner client. // Create an activity to group them together for better observability. - using Activity? activity = _activitySource?.StartActivity($"{nameof(FunctionInvokingChatClient)}.{nameof(GetStreamingResponseAsync)}"); + using Activity? activity = _activitySource?.StartActivity(OpenTelemetryConsts.GenAI.OrchestrateToolsName); UsageDetails? totalUsage = activity is { IsAllDataRequested: true } ? new() : null; // tracked usage across all turns, to be used for activity purposes // Copy the original messages in order to avoid enumerating the original messages multiple times. diff --git a/src/Libraries/Microsoft.Extensions.AI/OpenTelemetryConsts.cs b/src/Libraries/Microsoft.Extensions.AI/OpenTelemetryConsts.cs index c9b4a1ded1c..3def478d0e1 100644 --- a/src/Libraries/Microsoft.Extensions.AI/OpenTelemetryConsts.cs +++ b/src/Libraries/Microsoft.Extensions.AI/OpenTelemetryConsts.cs @@ -35,6 +35,7 @@ public static class GenAI public const string ChatName = "chat"; public const string EmbeddingsName = "embeddings"; public const string ExecuteToolName = "execute_tool"; + public const string OrchestrateToolsName = "orchestrate_tools"; // Non-standard public const string GenerateContentName = "generate_content"; public const string SystemInstructions = "gen_ai.system_instructions"; diff --git a/test/Libraries/Microsoft.Extensions.AI.Tests/ChatCompletion/FunctionInvokingChatClientTests.cs b/test/Libraries/Microsoft.Extensions.AI.Tests/ChatCompletion/FunctionInvokingChatClientTests.cs index 7a3c09db438..27c0d3ff0d6 100644 --- a/test/Libraries/Microsoft.Extensions.AI.Tests/ChatCompletion/FunctionInvokingChatClientTests.cs +++ b/test/Libraries/Microsoft.Extensions.AI.Tests/ChatCompletion/FunctionInvokingChatClientTests.cs @@ -678,11 +678,11 @@ public async Task FunctionInvocationTrackedWithActivity(bool enableTelemetry, bo Func configure = b => b.Use(c => new FunctionInvokingChatClient(new OpenTelemetryChatClient(c, sourceName: sourceName) { EnableSensitiveData = enableSensitiveData })); - await InvokeAsync(() => InvokeAndAssertAsync(options, plan, configurePipeline: configure), streaming: false); + await InvokeAsync(() => InvokeAndAssertAsync(options, plan, configurePipeline: configure)); - await InvokeAsync(() => InvokeAndAssertStreamingAsync(options, plan, configurePipeline: configure), streaming: true); + await InvokeAsync(() => InvokeAndAssertStreamingAsync(options, plan, configurePipeline: configure)); - async Task InvokeAsync(Func work, bool streaming) + async Task InvokeAsync(Func work) { var activities = new List(); using TracerProvider? tracerProvider = enableTelemetry ? @@ -700,7 +700,7 @@ async Task InvokeAsync(Func work, bool streaming) activity => Assert.Equal("chat", activity.DisplayName), activity => Assert.Equal("execute_tool Func1", activity.DisplayName), activity => Assert.Equal("chat", activity.DisplayName), - activity => Assert.Equal(streaming ? "FunctionInvokingChatClient.GetStreamingResponseAsync" : "FunctionInvokingChatClient.GetResponseAsync", activity.DisplayName)); + activity => Assert.Equal("orchestrate_tools", activity.DisplayName)); var executeTool = activities[1]; if (enableSensitiveData)