mirror of
https://github.com/davidkaya/aryx.git
synced 2026-07-24 05:28:46 +02:00
fix: correct OTEL instrumentation wiring for agent traces
- 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>
This commit is contained in:
@@ -14,7 +14,7 @@ internal static class OpenTelemetrySetup
|
||||
|
||||
private static readonly string[] ActivitySourceNames =
|
||||
[
|
||||
"Microsoft.Agents.AI",
|
||||
"Experimental.Microsoft.Agents.AI",
|
||||
"Microsoft.Agents.AI.Workflows",
|
||||
];
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adapts a synchronous <see cref="IDisposable"/> to <see cref="IAsyncDisposable"/>
|
||||
/// so it can be tracked in the async disposal pipeline.
|
||||
/// </summary>
|
||||
private sealed class SyncDisposableAdapter(IDisposable inner) : IAsyncDisposable
|
||||
{
|
||||
public ValueTask DisposeAsync()
|
||||
{
|
||||
inner.Dispose();
|
||||
return ValueTask.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
@@ -614,8 +614,8 @@ function TelemetrySection({
|
||||
placeholder={DEFAULT_OTEL_ENDPOINT}
|
||||
/>
|
||||
<p className="mt-1.5 text-[11px] text-[var(--color-text-muted)]">
|
||||
Use <span className="font-mono">bun run aspire</span> 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.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user