From 3a3e1d5eab75df44c9eb300c8fd64dbee22d9a12 Mon Sep 17 00:00:00 2001 From: David Kaya Date: Thu, 16 Apr 2026 11:52:13 +0200 Subject: [PATCH] fix: correct OTEL instrumentation wiring for agent traces MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fix ActivitySource name from 'Microsoft.Agents.AI' to 'Experimental.Microsoft.Agents.AI' matching the Agent Framework default - Wrap agents with UseOpenTelemetry() via AIAgentBuilder so agent invocation spans are emitted to the configured OTLP collector - Add proper disposal of OpenTelemetryAgent wrappers via SyncDisposableAdapter bridging IDisposable to IAsyncDisposable - Enable workflow-level telemetry on WorkflowRunner custom graph builds via WithOpenTelemetry() (HandoffWorkflowBuilder and GroupChatWorkflowBuilder do not expose this API — framework limitation) - Fix settings panel help text to be user-facing instead of dev jargon - Update test assertion for corrected ActivitySource name Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../Services/OpenTelemetrySetup.cs | 2 +- .../Providers/Copilot/CopilotAgentBundle.cs | 20 ++++++++++++++++++- .../Aryx.AgentHost/Services/WorkflowRunner.cs | 2 +- .../OpenTelemetrySetupTests.cs | 2 +- src/renderer/components/SettingsPanel.tsx | 4 ++-- 5 files changed, 24 insertions(+), 6 deletions(-) diff --git a/sidecar/src/Aryx.AgentHost/Services/OpenTelemetrySetup.cs b/sidecar/src/Aryx.AgentHost/Services/OpenTelemetrySetup.cs index bd781ac..cb03e88 100644 --- a/sidecar/src/Aryx.AgentHost/Services/OpenTelemetrySetup.cs +++ b/sidecar/src/Aryx.AgentHost/Services/OpenTelemetrySetup.cs @@ -14,7 +14,7 @@ internal static class OpenTelemetrySetup private static readonly string[] ActivitySourceNames = [ - "Microsoft.Agents.AI", + "Experimental.Microsoft.Agents.AI", "Microsoft.Agents.AI.Workflows", ]; diff --git a/sidecar/src/Aryx.AgentHost/Services/Providers/Copilot/CopilotAgentBundle.cs b/sidecar/src/Aryx.AgentHost/Services/Providers/Copilot/CopilotAgentBundle.cs index 9f1c207..ccfc4ab 100644 --- a/sidecar/src/Aryx.AgentHost/Services/Providers/Copilot/CopilotAgentBundle.cs +++ b/sidecar/src/Aryx.AgentHost/Services/Providers/Copilot/CopilotAgentBundle.cs @@ -87,8 +87,13 @@ internal sealed class CopilotAgentBundle : ProviderAgentBundle name: definition.GetAgentName(), description: NormalizeOptionalString(definition.Config.Description)); - agents.Add(agent); + AIAgent instrumentedAgent = new AIAgentBuilder(agent).UseOpenTelemetry().Build(); + agents.Add(instrumentedAgent); disposables.Add(agent); + if (instrumentedAgent is IDisposable instrumentedDisposable) + { + disposables.Add(new SyncDisposableAdapter(instrumentedDisposable)); + } } // The bundle owns the shared client — disposed after all agents. @@ -328,4 +333,17 @@ internal sealed class CopilotAgentBundle : ProviderAgentBundle { return string.IsNullOrWhiteSpace(value) ? null : value.Trim(); } + + /// + /// Adapts a synchronous to + /// so it can be tracked in the async disposal pipeline. + /// + private sealed class SyncDisposableAdapter(IDisposable inner) : IAsyncDisposable + { + public ValueTask DisposeAsync() + { + inner.Dispose(); + return ValueTask.CompletedTask; + } + } } diff --git a/sidecar/src/Aryx.AgentHost/Services/WorkflowRunner.cs b/sidecar/src/Aryx.AgentHost/Services/WorkflowRunner.cs index 7b52f1b..ab2a412 100644 --- a/sidecar/src/Aryx.AgentHost/Services/WorkflowRunner.cs +++ b/sidecar/src/Aryx.AgentHost/Services/WorkflowRunner.cs @@ -112,7 +112,7 @@ internal sealed class WorkflowRunner builder = builder.WithName(workflowDefinition.Name); } - return builder.WithOutputFrom(routes[endNode.Id].Exit).Build(); + return builder.WithOutputFrom(routes[endNode.Id].Exit).WithOpenTelemetry().Build(); } private WorkflowNodeRoute CreateNodeRoute( diff --git a/sidecar/tests/Aryx.AgentHost.Tests/OpenTelemetrySetupTests.cs b/sidecar/tests/Aryx.AgentHost.Tests/OpenTelemetrySetupTests.cs index 78db225..789f72d 100644 --- a/sidecar/tests/Aryx.AgentHost.Tests/OpenTelemetrySetupTests.cs +++ b/sidecar/tests/Aryx.AgentHost.Tests/OpenTelemetrySetupTests.cs @@ -27,7 +27,7 @@ public sealed class OpenTelemetrySetupTests Assert.Equal(OtlpExportProtocol.Grpc, configuration.Protocol); Assert.Collection( configuration.ActivitySourceNames, - source => Assert.Equal("Microsoft.Agents.AI", source), + source => Assert.Equal("Experimental.Microsoft.Agents.AI", source), source => Assert.Equal("Microsoft.Agents.AI.Workflows", source)); } diff --git a/src/renderer/components/SettingsPanel.tsx b/src/renderer/components/SettingsPanel.tsx index 4511c75..0f41ed7 100644 --- a/src/renderer/components/SettingsPanel.tsx +++ b/src/renderer/components/SettingsPanel.tsx @@ -614,8 +614,8 @@ function TelemetrySection({ placeholder={DEFAULT_OTEL_ENDPOINT} />

- Use bun run aspire to launch the Aspire Dashboard locally at this default endpoint. - Changes take effect on the next sidecar session. + The URL of any OTLP-compatible collector (e.g. Jaeger, Aspire Dashboard, Grafana Alloy). + Changes take effect on the next session.