diff --git a/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/src/Internals/StandardMetricsExtractionProcessor.cs b/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/src/Internals/StandardMetricsExtractionProcessor.cs index e8751b90a6db..7f8168568a81 100644 --- a/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/src/Internals/StandardMetricsExtractionProcessor.cs +++ b/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/src/Internals/StandardMetricsExtractionProcessor.cs @@ -75,7 +75,7 @@ private void ReportRequestDurationMetric(Activity activity, string statusCodeAtt } TagList tags = default; - tags.Add(new KeyValuePair(StandardMetricConstants.RequestResultCodeKey, statusCodeAttributeValue)); + tags.Add(new KeyValuePair(StandardMetricConstants.RequestResultCodeKey, statusCodeAttributeValue ?? "0")); tags.Add(new KeyValuePair(StandardMetricConstants.MetricIdKey, StandardMetricConstants.RequestDurationMetricIdValue)); tags.Add(new KeyValuePair(StandardMetricConstants.IsAutoCollectedKey, "True")); tags.Add(new KeyValuePair(StandardMetricConstants.CloudRoleInstanceKey, StandardMetricResource?.RoleInstance)); @@ -92,13 +92,13 @@ private void ReportDependencyDurationMetric(Activity activity) var dependencyTarget = activityTagsProcessor.MappedTags.GetDependencyTarget(activityTagsProcessor.activityType); - var statusCode = AzMonList.GetTagValue(ref activityTagsProcessor.MappedTags, SemanticConventions.AttributeHttpStatusCode); + var statusCode = AzMonList.GetTagValue(ref activityTagsProcessor.MappedTags, SemanticConventions.AttributeHttpStatusCode)?.ToString(); var dependencyType = activityTagsProcessor.MappedTags.GetDependencyType(activityTagsProcessor.activityType); TagList tags = default; tags.Add(new KeyValuePair(StandardMetricConstants.DependencyTargetKey, dependencyTarget)); - tags.Add(new KeyValuePair(StandardMetricConstants.DependencyResultCodeKey, statusCode)); + tags.Add(new KeyValuePair(StandardMetricConstants.DependencyResultCodeKey, statusCode ?? "0")); tags.Add(new KeyValuePair(StandardMetricConstants.MetricIdKey, StandardMetricConstants.DependencyDurationMetricIdValue)); tags.Add(new KeyValuePair(StandardMetricConstants.IsAutoCollectedKey, "True")); tags.Add(new KeyValuePair(StandardMetricConstants.CloudRoleInstanceKey, StandardMetricResource?.RoleInstance)); diff --git a/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/tests/Azure.Monitor.OpenTelemetry.Exporter.Tests/StandardMetricTests.cs b/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/tests/Azure.Monitor.OpenTelemetry.Exporter.Tests/StandardMetricTests.cs index 98ca6c2431b2..3776b0db23fe 100644 --- a/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/tests/Azure.Monitor.OpenTelemetry.Exporter.Tests/StandardMetricTests.cs +++ b/sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/tests/Azure.Monitor.OpenTelemetry.Exporter.Tests/StandardMetricTests.cs @@ -50,7 +50,6 @@ public void ValidateRequestDurationMetric() standardMetricCustomProcessor._meterProvider?.ForceFlush(); - // Standard Metrics + Resource Metrics. Assert.Single(metricTelemetryItems); var metricTelemetry = metricTelemetryItems.Last()!; @@ -102,7 +101,6 @@ public void ValidateDependencyDurationMetric() standardMetricCustomProcessor._meterProvider?.ForceFlush(); - // Standard Metrics + Resource Metrics. Assert.Single(metricTelemetryItems); var metricTelemetry = metricTelemetryItems.Last()!; @@ -125,6 +123,54 @@ public void ValidateDependencyDurationMetric() Assert.Equal("www.foo.com", dependencyTarget); } + [Theory] + [InlineData(ActivityKind.Server)] + [InlineData(ActivityKind.Client)] + public void ValidateNullStatusCode(ActivityKind kind) + { + var activitySource = new ActivitySource(nameof(StandardMetricTests.ValidateNullStatusCode)); + var traceTelemetryItems = new List(); + var metricTelemetryItems = new List(); + + var standardMetricCustomProcessor = new StandardMetricsExtractionProcessor(new AzureMonitorMetricExporter(new MockTransmitter(metricTelemetryItems))); + + using var tracerProvider = Sdk.CreateTracerProviderBuilder() + .SetSampler(new AlwaysOnSampler()) + .AddSource(nameof(StandardMetricTests.ValidateNullStatusCode)) + .AddProcessor(standardMetricCustomProcessor) + .AddProcessor(new BatchActivityExportProcessor(new AzureMonitorTraceExporter(new MockTransmitter(traceTelemetryItems)))) + .Build(); + + using (var activity = activitySource.StartActivity("Test", kind)) + { + activity?.SetTag(SemanticConventions.AttributeHttpMethod, "Get"); + activity?.SetTag(SemanticConventions.AttributeHttpUrl, "https://www.foo.com"); + } + + tracerProvider?.ForceFlush(); + + WaitForActivityExport(traceTelemetryItems); + + standardMetricCustomProcessor._meterProvider?.ForceFlush(); + + // Standard Metrics + Resource Metrics. + Assert.Single(metricTelemetryItems); + var metricTelemetry = metricTelemetryItems.Last()!; + Assert.Equal("MetricData", metricTelemetry.Data.BaseType); + var metricData = (MetricsData)metricTelemetry.Data.BaseData; + + if (kind == ActivityKind.Client) + { + Assert.True(metricData.Properties.TryGetValue(StandardMetricConstants.DependencyResultCodeKey, out var resultCode)); + Assert.Equal("0", resultCode); + } + else + { + Assert.True(metricData.Properties.TryGetValue(StandardMetricConstants.RequestResultCodeKey, out var resultCode)); + Assert.Equal("0", resultCode); + } + } + private void WaitForActivityExport(List traceTelemetryItems) { var result = SpinWait.SpinUntil(