< Summary

Information
Class: NexusLabs.Needlr.AgentFramework.Workflows.Diagnostics.DiagnosticsExtensions
Assembly: NexusLabs.Needlr.AgentFramework.Workflows
File(s): /home/runner/work/needlr/needlr/src/NexusLabs.Needlr.AgentFramework.Workflows/Diagnostics/DiagnosticsExtensions.cs
Line coverage
100%
Covered lines: 37
Uncovered lines: 0
Coverable lines: 37
Total lines: 66
Line coverage: 100%
Branch coverage
62%
Covered branches: 5
Total branches: 8
Branch coverage: 62.5%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
UsingDiagnostics(...)62.5%88100%

File(s)

/home/runner/work/needlr/needlr/src/NexusLabs.Needlr.AgentFramework.Workflows/Diagnostics/DiagnosticsExtensions.cs

#LineLine coverage
 1using Microsoft.Extensions.AI;
 2using Microsoft.Extensions.DependencyInjection;
 3
 4using NexusLabs.Needlr.AgentFramework;
 5using NexusLabs.Needlr.AgentFramework.Diagnostics;
 6using NexusLabs.Needlr.AgentFramework.Progress;
 7using NexusLabs.Needlr.AgentFramework.Workflows.Budget;
 8
 9namespace NexusLabs.Needlr.AgentFramework.Workflows.Diagnostics;
 10
 11/// <summary>
 12/// Extension methods for wiring agent diagnostics into the <see cref="AgentFrameworkSyringe"/>.
 13/// </summary>
 14public static class DiagnosticsExtensions
 15{
 16    /// <summary>
 17    /// Enables agent-run diagnostics for every agent created by the factory.
 18    /// Wires the agent-run, chat-completion, and function-calling middleware layers,
 19    /// and emits <see cref="IAgentMetrics"/> counters/histograms for OpenTelemetry.
 20    /// Automatically includes token tracking via <c>UsingTokenTracking()</c>.
 21    /// </summary>
 22    public static AgentFrameworkSyringe UsingDiagnostics(
 23        this AgentFrameworkSyringe syringe)
 24    {
 3725        ArgumentNullException.ThrowIfNull(syringe);
 26
 3727        syringe = syringe.UsingTokenTracking();
 28
 3729        var result = syringe.Configure(opts =>
 3730        {
 3531            var metrics = opts.ServiceProvider.GetRequiredService<IAgentMetrics>();
 3532            var genAiTokenMetrics = opts.ServiceProvider.GetRequiredService<IGenAiTokenMetrics>();
 3533            var progressAccessor = opts.ServiceProvider.GetRequiredService<IProgressReporterAccessor>();
 3534            var metricsOptions = opts.ServiceProvider.GetService<AgentFrameworkMetricsOptions>();
 3535            var chatMiddleware = new DiagnosticsChatClientMiddleware(
 3536                metrics, progressAccessor,
 3537                metricsOptions?.ChatCompletionActivityMode ?? ChatCompletionActivityMode.Always,
 3538                genAiTokenMetrics);
 3739
 3740            // Register the real collector via the DI-managed holder — NOT a static field.
 3541            var holder = opts.ServiceProvider.GetRequiredService<ChatCompletionCollectorHolder>();
 3542            holder.SetCollector(chatMiddleware);
 3743
 3744            // Register the tool call collector via the DI-managed holder.
 3545            var toolCallCollector = new ToolCallCollector();
 3546            var toolCallHolder = opts.ServiceProvider.GetRequiredService<ToolCallCollectorHolder>();
 3547            toolCallHolder.SetCollector(toolCallCollector);
 3748
 3549            var existingFactory = opts.ChatClientFactory;
 3550            opts.ChatClientFactory = sp =>
 3551            {
 4452                var innerClient = existingFactory?.Invoke(sp)
 4453                    ?? sp.GetRequiredService<IChatClient>();
 3554
 4455                return new DiagnosticsRecordingChatClient(innerClient, chatMiddleware);
 3556            };
 7257        });
 58
 3759        return result with
 3760        {
 3761            Plugins = (result.Plugins ?? [])
 3762                .Append(new AgentDiagnosticsPlugin(syringe.ServiceProvider))
 3763                .ToList()
 3764        };
 65    }
 66}