synergy moats product advisory implementations
This commit is contained in:
@@ -0,0 +1,143 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// P0ProductMetricsTests.cs
|
||||
// Sprint: SPRINT_20260117_028_Telemetry_p0_metrics
|
||||
// Tests for P0 Product Metrics
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
using System.Diagnostics.Metrics;
|
||||
using StellaOps.Telemetry.Core;
|
||||
using Xunit;
|
||||
|
||||
namespace StellaOps.Telemetry.Core.Tests;
|
||||
|
||||
public sealed class P0ProductMetricsTests : IDisposable
|
||||
{
|
||||
private readonly P0ProductMetrics _metrics;
|
||||
private readonly MeterListener _listener;
|
||||
private readonly List<(string Name, object Value, KeyValuePair<string, object?>[] Tags)> _recordedMeasurements;
|
||||
|
||||
public P0ProductMetricsTests()
|
||||
{
|
||||
_metrics = new P0ProductMetrics();
|
||||
_recordedMeasurements = new();
|
||||
_listener = new MeterListener();
|
||||
|
||||
_listener.InstrumentPublished = (instrument, listener) =>
|
||||
{
|
||||
if (instrument.Meter.Name == P0ProductMetrics.MeterName)
|
||||
{
|
||||
listener.EnableMeasurementEvents(instrument);
|
||||
}
|
||||
};
|
||||
|
||||
_listener.SetMeasurementEventCallback<double>((instrument, measurement, tags, state) =>
|
||||
{
|
||||
_recordedMeasurements.Add((instrument.Name, measurement, tags.ToArray()));
|
||||
});
|
||||
|
||||
_listener.SetMeasurementEventCallback<long>((instrument, measurement, tags, state) =>
|
||||
{
|
||||
_recordedMeasurements.Add((instrument.Name, measurement, tags.ToArray()));
|
||||
});
|
||||
|
||||
_listener.Start();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MeterName_IsCorrect()
|
||||
{
|
||||
Assert.Equal("StellaOps.P0Metrics", P0ProductMetrics.MeterName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RecordTimeToFirstVerifiedRelease_RecordsMeasurement()
|
||||
{
|
||||
_metrics.RecordTimeToFirstVerifiedRelease(
|
||||
durationSeconds: 3600.0,
|
||||
tenant: "test-tenant",
|
||||
deploymentType: "fresh");
|
||||
|
||||
var measurement = _recordedMeasurements.FirstOrDefault(m =>
|
||||
m.Name == "stella_time_to_first_verified_release_seconds");
|
||||
|
||||
Assert.NotNull(measurement);
|
||||
Assert.Equal(3600.0, measurement.Value);
|
||||
Assert.Contains(measurement.Tags, t => t.Key == "tenant" && (string?)t.Value == "test-tenant");
|
||||
Assert.Contains(measurement.Tags, t => t.Key == "deployment_type" && (string?)t.Value == "fresh");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RecordWhyBlockedLatency_RecordsMeasurement()
|
||||
{
|
||||
_metrics.RecordWhyBlockedLatency(
|
||||
durationSeconds: 30.0,
|
||||
tenant: "test-tenant",
|
||||
surface: "cli",
|
||||
resolutionType: "immediate");
|
||||
|
||||
var measurement = _recordedMeasurements.FirstOrDefault(m =>
|
||||
m.Name == "stella_why_blocked_latency_seconds");
|
||||
|
||||
Assert.NotNull(measurement);
|
||||
Assert.Equal(30.0, measurement.Value);
|
||||
Assert.Contains(measurement.Tags, t => t.Key == "surface" && (string?)t.Value == "cli");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RecordSupportBurden_RecordsMeasurement()
|
||||
{
|
||||
_metrics.RecordSupportBurden(
|
||||
minutes: 15,
|
||||
tenant: "test-tenant",
|
||||
category: "config",
|
||||
month: "2026-01");
|
||||
|
||||
var measurement = _recordedMeasurements.FirstOrDefault(m =>
|
||||
m.Name == "stella_support_burden_minutes_total");
|
||||
|
||||
Assert.NotNull(measurement);
|
||||
Assert.Equal(15L, measurement.Value);
|
||||
Assert.Contains(measurement.Tags, t => t.Key == "category" && (string?)t.Value == "config");
|
||||
Assert.Contains(measurement.Tags, t => t.Key == "month" && (string?)t.Value == "2026-01");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RecordDeterminismRegression_RecordsMeasurement()
|
||||
{
|
||||
_metrics.RecordDeterminismRegression(
|
||||
tenant: "test-tenant",
|
||||
component: "scanner",
|
||||
severity: "policy");
|
||||
|
||||
var measurement = _recordedMeasurements.FirstOrDefault(m =>
|
||||
m.Name == "stella_determinism_regressions_total");
|
||||
|
||||
Assert.NotNull(measurement);
|
||||
Assert.Equal(1L, measurement.Value);
|
||||
Assert.Contains(measurement.Tags, t => t.Key == "component" && (string?)t.Value == "scanner");
|
||||
Assert.Contains(measurement.Tags, t => t.Key == "severity" && (string?)t.Value == "policy");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Dispose_DoesNotThrow()
|
||||
{
|
||||
var metrics = new P0ProductMetrics();
|
||||
var exception = Record.Exception(() => metrics.Dispose());
|
||||
Assert.Null(exception);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MultipleDispose_DoesNotThrow()
|
||||
{
|
||||
var metrics = new P0ProductMetrics();
|
||||
metrics.Dispose();
|
||||
var exception = Record.Exception(() => metrics.Dispose());
|
||||
Assert.Null(exception);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_listener.Dispose();
|
||||
_metrics.Dispose();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<LangVersion>preview</LangVersion>
|
||||
<IsPackable>false</IsPackable>
|
||||
<IsTestProject>true</IsTestProject>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" />
|
||||
<PackageReference Include="Moq" />
|
||||
<PackageReference Include="xunit" />
|
||||
<PackageReference Include="xunit.runner.visualstudio">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="coverlet.collector">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\src\Telemetry\StellaOps.Telemetry.Core\StellaOps.Telemetry.Core\StellaOps.Telemetry.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
Reference in New Issue
Block a user