< Summary

Information
Class: NexusLabs.Needlr.AgentFramework.Langfuse.LangfuseSession
Assembly: NexusLabs.Needlr.AgentFramework.Langfuse
File(s): /home/runner/work/needlr/needlr/src/NexusLabs.Needlr.AgentFramework.Langfuse/LangfuseSession.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 58
Coverable lines: 58
Total lines: 133
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 12
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%210%
get_IsEnabled()100%210%
get_ScoresFailed()100%210%
get_Datasets()100%210%
get_ScoreConfigs()100%210%
Flush(...)0%620%
BeginScenario(...)100%210%
BeginExperimentRun(...)100%210%
AddTraceCommentAsync(...)100%210%
Dispose()0%2040%
ToTimeoutMilliseconds(...)0%4260%

File(s)

/home/runner/work/needlr/needlr/src/NexusLabs.Needlr.AgentFramework.Langfuse/LangfuseSession.cs

#LineLine coverage
 1using System.Threading;
 2
 3using OpenTelemetry;
 4using OpenTelemetry.Metrics;
 5using OpenTelemetry.Trace;
 6
 7namespace NexusLabs.Needlr.AgentFramework.Langfuse;
 8
 9/// <summary>
 10/// Active <see cref="ILangfuseSession"/> backed by OpenTelemetry tracer and (optionally) meter
 11/// providers that export to Langfuse over OTLP/HTTP.
 12/// </summary>
 13internal sealed class LangfuseSession : ILangfuseSession
 14{
 15    private readonly TracerProvider _tracerProvider;
 16    private readonly MeterProvider? _meterProvider;
 17    private readonly HttpClient _httpClient;
 18    private readonly LangfuseScoreRecorder _recorder;
 19    private readonly LangfuseScoreFailureSink _failureSink;
 20    private readonly LangfuseCommentRecorder _commentRecorder;
 21    private readonly LangfuseApiClient _apiClient;
 22    private readonly Action<string>? _diagnostics;
 23    private int _disposed;
 24
 025    public LangfuseSession(
 026        TracerProvider tracerProvider,
 027        MeterProvider? meterProvider,
 028        HttpClient httpClient,
 029        LangfuseScoreRecorder recorder,
 030        LangfuseScoreFailureSink failureSink,
 031        LangfuseCommentRecorder commentRecorder,
 032        LangfuseApiClient apiClient,
 033        Action<string>? diagnostics)
 34    {
 035        ArgumentNullException.ThrowIfNull(tracerProvider);
 036        ArgumentNullException.ThrowIfNull(httpClient);
 037        ArgumentNullException.ThrowIfNull(recorder);
 038        ArgumentNullException.ThrowIfNull(failureSink);
 039        ArgumentNullException.ThrowIfNull(commentRecorder);
 040        ArgumentNullException.ThrowIfNull(apiClient);
 41
 042        _tracerProvider = tracerProvider;
 043        _meterProvider = meterProvider;
 044        _httpClient = httpClient;
 045        _recorder = recorder;
 046        _failureSink = failureSink;
 047        _commentRecorder = commentRecorder;
 048        _apiClient = apiClient;
 049        _diagnostics = diagnostics;
 50
 051        Datasets = new LangfuseDatasetClient(apiClient);
 052        ScoreConfigs = new LangfuseScoreConfigClient(apiClient);
 053    }
 54
 55    /// <inheritdoc />
 056    public bool IsEnabled => true;
 57
 58    /// <inheritdoc />
 059    public int ScoresFailed => _failureSink.FailedCount;
 60
 61    /// <inheritdoc />
 062    public ILangfuseDatasetClient Datasets { get; }
 63
 64    /// <inheritdoc />
 065    public ILangfuseScoreConfigClient ScoreConfigs { get; }
 66
 67    /// <inheritdoc />
 68    public bool Flush(TimeSpan? timeout = null)
 69    {
 070        var timeoutMs = ToTimeoutMilliseconds(timeout);
 071        var traces = _tracerProvider.ForceFlush(timeoutMs);
 072        var metrics = _meterProvider?.ForceFlush(timeoutMs) ?? true;
 073        return traces && metrics;
 74    }
 75
 76    /// <inheritdoc />
 77    public ILangfuseScenario BeginScenario(
 78        string name,
 79        string? sessionId = null,
 80        string? userId = null,
 81        IEnumerable<string>? tags = null,
 82        IReadOnlyDictionary<string, string>? metadata = null) =>
 083        new LangfuseScenario(_recorder, name, sessionId, userId, tags, metadata);
 84
 85    /// <inheritdoc />
 86    public ILangfuseExperimentRun BeginExperimentRun(string datasetName, string runName, string? runDescription = null)
 87    {
 088        ArgumentException.ThrowIfNullOrWhiteSpace(datasetName);
 089        ArgumentException.ThrowIfNullOrWhiteSpace(runName);
 90
 091        return new LangfuseExperimentRun(
 092            _apiClient,
 093            _recorder,
 094            datasetName,
 095            runName,
 096            runDescription,
 097            _diagnostics);
 98    }
 99
 100    /// <inheritdoc />
 101    public Task AddTraceCommentAsync(string traceId, string content, CancellationToken cancellationToken = default) =>
 0102        _commentRecorder.AddTraceCommentAsync(traceId, content, cancellationToken);
 103
 104    /// <inheritdoc />
 105    public void Dispose()
 106    {
 0107        if (Interlocked.Exchange(ref _disposed, 1) != 0)
 108        {
 0109            return;
 110        }
 111
 0112        Flush();
 0113        _tracerProvider.Dispose();
 0114        _meterProvider?.Dispose();
 0115        _httpClient.Dispose();
 0116    }
 117
 118    private static int ToTimeoutMilliseconds(TimeSpan? timeout)
 119    {
 0120        if (timeout is null)
 121        {
 0122            return Timeout.Infinite;
 123        }
 124
 0125        if (timeout.Value == Timeout.InfiniteTimeSpan)
 126        {
 0127            return Timeout.Infinite;
 128        }
 129
 0130        var ms = (long)timeout.Value.TotalMilliseconds;
 0131        return ms < 0 ? Timeout.Infinite : (int)Math.Min(ms, int.MaxValue);
 132    }
 133}