feat(metrics): Add new histograms for chunk latency, results, and sources in AdvisoryAiMetrics
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled

feat(telemetry): Record chunk latency, result count, and source count in AdvisoryAiTelemetry

fix(endpoint): Include telemetry source count in advisory chunks endpoint response

test(metrics): Enhance WebServiceEndpointsTests to validate new metrics for chunk latency, results, and sources

refactor(tests): Update test utilities for Deno language analyzer tests

chore(tests): Add performance tests for AdvisoryGuardrail with scenarios and blocked phrases

docs: Archive Sprint 137 design document for scanner and surface enhancements
This commit is contained in:
master
2025-11-10 22:26:43 +02:00
parent 56c687253f
commit b059bc7675
22 changed files with 427 additions and 37 deletions

View File

@@ -531,7 +531,14 @@ public sealed class WebServiceEndpointsTests : IAsyncLifetime
var metrics = await CaptureMetricsAsync(
AdvisoryAiMetrics.MeterName,
new[] { "advisory_ai_chunk_requests_total", "advisory_ai_chunk_cache_hits_total" },
new[]
{
"advisory_ai_chunk_requests_total",
"advisory_ai_chunk_cache_hits_total",
"advisory_ai_chunk_latency_milliseconds",
"advisory_ai_chunk_segments",
"advisory_ai_chunk_sources"
},
async () =>
{
const string url = "/advisories/CVE-2025-0001/chunks?tenant=tenant-a";
@@ -556,6 +563,17 @@ public sealed class WebServiceEndpointsTests : IAsyncLifetime
var cacheHit = Assert.Single(cacheHitMeasurements!);
Assert.Equal(1, cacheHit.Value);
Assert.Equal("hit", GetTagValue(cacheHit, "result"));
Assert.True(metrics.TryGetValue("advisory_ai_chunk_latency_milliseconds", out var latencyMeasurements));
Assert.Equal(2, latencyMeasurements!.Count);
Assert.All(latencyMeasurements!, measurement => Assert.True(measurement.Value > 0));
Assert.True(metrics.TryGetValue("advisory_ai_chunk_segments", out var segmentMeasurements));
Assert.Equal(2, segmentMeasurements!.Count);
Assert.Contains(segmentMeasurements!, measurement => GetTagValue(measurement, "truncated") == "false");
Assert.True(metrics.TryGetValue("advisory_ai_chunk_sources", out var sourceMeasurements));
Assert.Equal(2, sourceMeasurements!.Count);
}
[Fact]
@@ -2161,7 +2179,7 @@ public sealed class WebServiceEndpointsTests : IAsyncLifetime
}
};
listener.SetMeasurementEventCallback<long>((instrument, measurement, tags, state) =>
void RecordMeasurement(Instrument instrument, double measurement, ReadOnlySpan<KeyValuePair<string, object?>> tags)
{
if (!measurementMap.TryGetValue(instrument.Name, out var list))
{
@@ -2175,7 +2193,13 @@ public sealed class WebServiceEndpointsTests : IAsyncLifetime
}
list.Add(new MetricMeasurement(instrument.Name, measurement, tagDictionary));
});
}
listener.SetMeasurementEventCallback<long>((instrument, measurement, tags, state)
=> RecordMeasurement(instrument, measurement, tags));
listener.SetMeasurementEventCallback<double>((instrument, measurement, tags, state)
=> RecordMeasurement(instrument, measurement, tags));
listener.Start();
try
@@ -2239,7 +2263,7 @@ public sealed class WebServiceEndpointsTests : IAsyncLifetime
return new JwtSecurityTokenHandler().WriteToken(token);
}
private sealed record MetricMeasurement(string Instrument, long Value, IReadOnlyDictionary<string, object?> Tags);
private sealed record MetricMeasurement(string Instrument, double Value, IReadOnlyDictionary<string, object?> Tags);
private sealed class DemoJob : IJob
{