Skip to content
Prev Previous commit
Next Next commit
Update tests
  • Loading branch information
rajkumar-rangaraj committed Sep 18, 2025
commit c75e04e35c7a3983e67f50e16a724741cf8d53eb
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,10 @@ public void ValidateRequestDurationMetric()

standardMetricCustomProcessor._meterProvider?.ForceFlush();

Assert.Single(metricTelemetryItems);

var metricTelemetry = metricTelemetryItems.Last()!;
Assert.Equal("MetricData", metricTelemetry.Data.BaseType);
// Find the specific Request Duration metric among possibly many perf counter metrics.
var metricTelemetry = GetMetricTelemetry(metricTelemetryItems, StandardMetricConstants.RequestDurationMetricIdValue);
Assert.NotNull(metricTelemetry);
Assert.Equal("MetricData", metricTelemetry!.Data.BaseType);
var metricData = (MetricsData)metricTelemetry.Data.BaseData;
Assert.True(metricData.Properties.TryGetValue(StandardMetricConstants.RequestSuccessKey, out var isSuccess));
Assert.Equal("True", isSuccess);
Expand Down Expand Up @@ -99,10 +99,9 @@ public void ValidateRequestDurationMetricNew()

standardMetricCustomProcessor._meterProvider?.ForceFlush();

Assert.Single(metricTelemetryItems);

var metricTelemetry = metricTelemetryItems.Last()!;
Assert.Equal("MetricData", metricTelemetry.Data.BaseType);
var metricTelemetry = GetMetricTelemetry(metricTelemetryItems, StandardMetricConstants.RequestDurationMetricIdValue);
Assert.NotNull(metricTelemetry);
Assert.Equal("MetricData", metricTelemetry!.Data.BaseType);
var metricData = (MetricsData)metricTelemetry.Data.BaseData;
Assert.True(metricData.Properties.TryGetValue(StandardMetricConstants.RequestSuccessKey, out var isSuccess));
Assert.Equal("True", isSuccess);
Expand Down Expand Up @@ -151,10 +150,9 @@ public void ValidateRequestDurationMetricConsumerKind()

standardMetricCustomProcessor._meterProvider?.ForceFlush();

Assert.Single(metricTelemetryItems);

var metricTelemetry = metricTelemetryItems.Last()!;
Assert.Equal("MetricData", metricTelemetry.Data.BaseType);
var metricTelemetry = GetMetricTelemetry(metricTelemetryItems, StandardMetricConstants.RequestDurationMetricIdValue);
Assert.NotNull(metricTelemetry);
Assert.Equal("MetricData", metricTelemetry!.Data.BaseType);
var metricData = (MetricsData)metricTelemetry.Data.BaseData;
Assert.True(metricData.Properties.TryGetValue(StandardMetricConstants.RequestSuccessKey, out var isSuccess));
Assert.Equal("True", isSuccess);
Expand Down Expand Up @@ -208,10 +206,9 @@ public void ValidateDependencyDurationMetric(bool isAzureSDK)

standardMetricCustomProcessor._meterProvider?.ForceFlush();

Assert.Single(metricTelemetryItems);

var metricTelemetry = metricTelemetryItems.Last()!;
Assert.Equal("MetricData", metricTelemetry.Data.BaseType);
var metricTelemetry = GetMetricTelemetry(metricTelemetryItems, StandardMetricConstants.DependencyDurationMetricIdValue);
Assert.NotNull(metricTelemetry);
Assert.Equal("MetricData", metricTelemetry!.Data.BaseType);
var metricData = (MetricsData)metricTelemetry.Data.BaseData;
Assert.True(metricData.Properties.TryGetValue(StandardMetricConstants.DependencySuccessKey, out var isSuccess));
Assert.Equal("True", isSuccess);
Expand Down Expand Up @@ -277,10 +274,9 @@ public void ValidateDependencyDurationMetricForProducerKind(bool isAzureSDKSpan)

standardMetricCustomProcessor._meterProvider?.ForceFlush();

Assert.Single(metricTelemetryItems);

var metricTelemetry = metricTelemetryItems.Last()!;
Assert.Equal("MetricData", metricTelemetry.Data.BaseType);
var metricTelemetry = GetMetricTelemetry(metricTelemetryItems, StandardMetricConstants.DependencyDurationMetricIdValue);
Assert.NotNull(metricTelemetry);
Assert.Equal("MetricData", metricTelemetry!.Data.BaseType);
var metricData = (MetricsData)metricTelemetry.Data.BaseData;
Assert.True(metricData.Properties.TryGetValue(StandardMetricConstants.DependencySuccessKey, out var isSuccess));
Assert.Equal("True", isSuccess);
Expand Down Expand Up @@ -345,10 +341,9 @@ public void ValidateDependencyDurationMetricNew(bool isAzureSDK)

standardMetricCustomProcessor._meterProvider?.ForceFlush();

Assert.Single(metricTelemetryItems);

var metricTelemetry = metricTelemetryItems.Last()!;
Assert.Equal("MetricData", metricTelemetry.Data.BaseType);
var metricTelemetry = GetMetricTelemetry(metricTelemetryItems, StandardMetricConstants.DependencyDurationMetricIdValue);
Assert.NotNull(metricTelemetry);
Assert.Equal("MetricData", metricTelemetry!.Data.BaseType);
var metricData = (MetricsData)metricTelemetry.Data.BaseData;
Assert.True(metricData.Properties.TryGetValue(StandardMetricConstants.DependencySuccessKey, out var isSuccess));
Assert.Equal("True", isSuccess);
Expand Down Expand Up @@ -405,10 +400,10 @@ public void ValidateNullStatusCode(ActivityKind kind)

standardMetricCustomProcessor._meterProvider?.ForceFlush();

// Standard Metrics + Resource Metrics.
Assert.Single(metricTelemetryItems);
var metricTelemetry = metricTelemetryItems.Last()!;
Assert.Equal("MetricData", metricTelemetry.Data.BaseType);
var metricIdToFind = kind == ActivityKind.Client ? StandardMetricConstants.DependencyDurationMetricIdValue : StandardMetricConstants.RequestDurationMetricIdValue;
var metricTelemetry = GetMetricTelemetry(metricTelemetryItems, metricIdToFind);
Assert.NotNull(metricTelemetry);
Assert.Equal("MetricData", metricTelemetry!.Data.BaseType);
var metricData = (MetricsData)metricTelemetry.Data.BaseData;

if (kind == ActivityKind.Client)
Expand Down Expand Up @@ -453,10 +448,10 @@ public void ValidateNullStatusCodeNew(ActivityKind kind)

standardMetricCustomProcessor._meterProvider?.ForceFlush();

// Standard Metrics + Resource Metrics.
Assert.Single(metricTelemetryItems);
var metricTelemetry = metricTelemetryItems.Last()!;
Assert.Equal("MetricData", metricTelemetry.Data.BaseType);
var metricIdToFind = kind == ActivityKind.Client ? StandardMetricConstants.DependencyDurationMetricIdValue : StandardMetricConstants.RequestDurationMetricIdValue;
var metricTelemetry = GetMetricTelemetry(metricTelemetryItems, metricIdToFind);
Assert.NotNull(metricTelemetry);
Assert.Equal("MetricData", metricTelemetry!.Data.BaseType);
var metricData = (MetricsData)metricTelemetry.Data.BaseData;

if (kind == ActivityKind.Client)
Expand All @@ -471,6 +466,81 @@ public void ValidateNullStatusCodeNew(ActivityKind kind)
}
}

[Fact]
public void ValidatePerfCounterMetrics()
{
// This test validates the presence of perf counter based metrics emitted via _perfCounterMeter
// in StandardMetricsExtractionProcessor: Request Rate, Process Private Bytes, CPU, Normalized CPU, Exception Rate.
var activitySource = new ActivitySource(nameof(StandardMetricTests.ValidatePerfCounterMetrics));
var traceTelemetryItems = new List<TelemetryItem>();
var metricTelemetryItems = new List<TelemetryItem>();

var standardMetricCustomProcessor = new StandardMetricsExtractionProcessor(new AzureMonitorMetricExporter(new MockTransmitter(metricTelemetryItems)));

using var tracerProvider = Sdk.CreateTracerProviderBuilder()
.SetSampler(new AlwaysOnSampler())
.AddSource(nameof(StandardMetricTests.ValidatePerfCounterMetrics))
.AddProcessor(standardMetricCustomProcessor)
.AddProcessor(new BatchActivityExportProcessor(new AzureMonitorTraceExporter(new AzureMonitorExporterOptions(), new MockTransmitter(traceTelemetryItems))))
.Build();

// Generate multiple request activities to increment the RequestRate counter.
for (int i = 0; i < 5; i++)
{
using var a = activitySource.StartActivity("Req", ActivityKind.Server);
a?.SetTag(SemanticConventions.AttributeHttpStatusCode, 200);
}

// Generate a few thrown (and caught) exceptions to trigger System.Runtime "dotnet.exceptions" counter where available.
for (int i = 0; i < 3; i++)
{
try
{
throw new InvalidOperationException("Test exception for exception rate metric");
}
catch
{
// Swallow - we just need the throw to increment the counter.
}
}

tracerProvider?.ForceFlush();
WaitForActivityExport(traceTelemetryItems);

standardMetricCustomProcessor._meterProvider?.ForceFlush();

// We expect multiple metric telemetry items now (at least one per perf counter plus request duration histogram).
Assert.True(metricTelemetryItems.Count >= 2, "Expected multiple metric telemetry items including perf counters.");

// Helper local function to find metric by mapped name.
MetricsData? FindMetric(string expectedName) => metricTelemetryItems
.Select(ti => (MetricsData)ti.Data.BaseData)
.FirstOrDefault(md => md.Metrics[0].Name == expectedName);

var requestRate = FindMetric(PerfCounterConstants.RequestRateMetricIdValue);
Assert.NotNull(requestRate);
Assert.True(requestRate!.Metrics[0].Value >= 1, "Request rate should be >= 1");

var privateBytes = FindMetric(PerfCounterConstants.ProcessPrivateBytesMetricIdValue);
Assert.NotNull(privateBytes);
Assert.True(privateBytes!.Metrics[0].Value >= 0);

var cpu = FindMetric(PerfCounterConstants.ProcessCpuMetricIdValue);
Assert.NotNull(cpu);
Assert.True(cpu!.Metrics[0].Value >= 0);

var cpuNormalized = FindMetric(PerfCounterConstants.ProcessCpuNormalizedMetricIdValue);
Assert.NotNull(cpuNormalized);
Assert.True(cpuNormalized!.Metrics[0].Value >= 0);

// Exception rate metric may not be available on all target frameworks/runtimes; assert only if present.
var exceptionRate = FindMetric(PerfCounterConstants.ExceptionRateMetricIdValue);
if (exceptionRate != null)
{
Assert.True(exceptionRate.Metrics[0].Value >= 0);
}
}

private void WaitForActivityExport(List<TelemetryItem> traceTelemetryItems)
{
var result = SpinWait.SpinUntil(
Expand All @@ -483,5 +553,21 @@ private void WaitForActivityExport(List<TelemetryItem> traceTelemetryItems)

Assert.True(result, $"{nameof(WaitForActivityExport)} failed.");
}

private TelemetryItem? GetMetricTelemetry(List<TelemetryItem> metricTelemetryItems, string metricName)
{
foreach (var item in metricTelemetryItems)
{
if (item.Data.BaseType == "MetricData")
{
var data = (MetricsData)item.Data.BaseData;
if (data.Metrics.Count > 0 && data.Metrics[0].Name == metricName)
{
return item;
}
}
}
return null;
}
}
}
Loading