Skip to content

Commit 91dc3f1

Browse files
author
Timothy Mothra
authored
[AzureMonitorDistro] fix for LiveMetrics Dependencies (#45103)
* fix for LiveMetrics and manual Dependencies * changelog * update all dependency mappings * fix * update tests * cleanup * cleanup * drop ActivityType * changelog * update changelog * update mappings * fix tests
1 parent cf86036 commit 91dc3f1

File tree

5 files changed

+101
-24
lines changed

5 files changed

+101
-24
lines changed

sdk/monitor/Azure.Monitor.OpenTelemetry.AspNetCore/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,14 @@
1818
* Fixed a bug where LiveMetrics displays "UNKNOWN_INSTANCE" and "UNKNOWN_NAME" for "server name" and "role name" respectively.
1919
([#45433](https://github.com/Azure/azure-sdk-for-net/pull/45433))
2020

21+
* Fixed a bug in LiveMetrics that counted all manually created Dependencies as failures.
22+
([#45103](https://github.com/Azure/azure-sdk-for-net/pull/45103))
23+
2124
### Other Changes
2225

26+
* Updated field mappings for telemetry sent to LiveMetrics.
27+
([#45103](https://github.com/Azure/azure-sdk-for-net/pull/45103))
28+
2329
* Updated log collection to default to Warning level and above for Azure SDKs
2430
via `Microsoft.Extensions.Logging`. For more information, refer to [Logging
2531
with the Azure SDK for

sdk/monitor/Azure.Monitor.OpenTelemetry.AspNetCore/src/LiveMetrics/DataCollection/DocumentHelper.cs

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,13 @@ internal static RemoteDependency ConvertToDependencyDocument(Activity activity)
108108
RemoteDependency remoteDependencyDocument = new()
109109
{
110110
DocumentType = DocumentType.RemoteDependency,
111+
Duration = activity.Duration < SchemaConstants.RemoteDependencyData_Duration_LessThanDays
112+
? activity.Duration.ToString("c", CultureInfo.InvariantCulture)
113+
: SchemaConstants.Duration_MaxValue,
114+
111115
// The following "EXTENSION" properties are used to calculate metrics. These are not serialized.
112116
Extension_Duration = activity.Duration.TotalMilliseconds,
117+
Extension_IsSuccess = activity.Status != ActivityStatusCode.Error,
113118
};
114119

115120
var liveMetricsTagsProcessor = new LiveMetricsTagsProcessor();
@@ -119,41 +124,41 @@ internal static RemoteDependency ConvertToDependencyDocument(Activity activity)
119124
{
120125
case OperationType.Http:
121126
remoteDependencyDocument.Name = activity.DisplayName;
122-
remoteDependencyDocument.CommandName = AzMonList.GetTagValue(ref liveMetricsTagsProcessor.Tags, SemanticConventions.AttributeUrlFull)?.ToString();
127+
128+
var httpUrl = AzMonList.GetTagValue(ref liveMetricsTagsProcessor.Tags, SemanticConventions.AttributeUrlFull)?.ToString();
129+
remoteDependencyDocument.CommandName = httpUrl;
130+
123131
var httpResponseStatusCode = AzMonList.GetTagValue(ref liveMetricsTagsProcessor.Tags, SemanticConventions.AttributeHttpResponseStatusCode)?.ToString();
124-
remoteDependencyDocument.ResultCode = httpResponseStatusCode;
125-
remoteDependencyDocument.Duration = activity.Duration < SchemaConstants.RequestData_Duration_LessThanDays
126-
? activity.Duration.ToString("c", CultureInfo.InvariantCulture)
127-
: SchemaConstants.Duration_MaxValue;
132+
remoteDependencyDocument.ResultCode = httpResponseStatusCode ?? "0";
128133

129134
// The following "EXTENSION" properties are used to calculate metrics. These are not serialized.
130135
remoteDependencyDocument.Extension_IsSuccess = IsHttpSuccess(activity, httpResponseStatusCode);
131136
break;
132137
case OperationType.Db:
133-
// Note: The Exception details are recorded in Activity.Events only if the configuration has opt-ed into this (SqlClientInstrumentationOptions.RecordException).
134-
135-
var (_, dbTarget) = liveMetricsTagsProcessor.Tags.GetDbDependencyTargetAndName();
138+
remoteDependencyDocument.Name = activity.DisplayName;
136139

137-
remoteDependencyDocument.Name = dbTarget;
138140
remoteDependencyDocument.CommandName = AzMonList.GetTagValue(ref liveMetricsTagsProcessor.Tags, SemanticConventions.AttributeDbStatement)?.ToString();
139-
remoteDependencyDocument.Duration = activity.Duration.ToString("c", CultureInfo.InvariantCulture);
140141

141142
// TODO: remoteDependencyDocumentIngress.ResultCode = "";
142143
// AI SDK reads a Number property from Connection or Command objects.
143144
// As of Feb 2024, OpenTelemetry doesn't record this. This may change in the future when the semantic convention stabalizes.
144145

145-
// The following "EXTENSION" properties are used to calculate metrics. These are not serialized.
146-
remoteDependencyDocument.Extension_IsSuccess = activity.Status != ActivityStatusCode.Error;
147-
break;
148-
case OperationType.Rpc:
149-
// TODO RPC
150146
break;
151147
case OperationType.Messaging:
152-
// TODO MESSAGING
148+
remoteDependencyDocument.Name = activity.DisplayName;
149+
150+
var (messagingUrl, _) = liveMetricsTagsProcessor.Tags.GetMessagingUrlAndSourceOrTarget(activity.Kind);
151+
remoteDependencyDocument.CommandName = messagingUrl;
152+
153153
break;
154+
case OperationType.Rpc:
155+
// remoteDependencyDocument.Name = activity.DisplayName;
156+
// remoteDependencyDocument.CommandName = AzMonList.GetTagValue(ref liveMetricsTagsProcessor.Tags, SemanticConventions.AttributeRpcService)?.ToString();
157+
// remoteDependencyDocument.ResultCode = AzMonList.GetTagValue(ref liveMetricsTagsProcessor.Tags, SemanticConventions.AttributeRpcStatus)?.ToString();
154158
default:
155-
// Unknown or Unexpected Dependency Type
156-
remoteDependencyDocument.Name = liveMetricsTagsProcessor.ActivityType.ToString();
159+
// Unknown or Manual or Unexpected Dependency Type
160+
remoteDependencyDocument.Name = activity.DisplayName;
161+
remoteDependencyDocument.Properties.Add(new KeyValuePairString("ActivitySource", activity.Source.Name));
157162
break;
158163
}
159164

sdk/monitor/Azure.Monitor.OpenTelemetry.AspNetCore/tests/Azure.Monitor.OpenTelemetry.AspNetCore.Tests/LiveMetrics/DocumentTests/HttpClientDependecyTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public void VerifyHttpClientAttributes()
4343
ActivitySource.AddActivityListener(listener);
4444

4545
// ACT
46-
using var dependencyActivity = activitySource.StartActivity(name: "HelloWorld", kind: ActivityKind.Client);
46+
using var dependencyActivity = activitySource.StartActivity(name: "TestActivityName", kind: ActivityKind.Client);
4747
Assert.NotNull(dependencyActivity);
4848
dependencyActivity.SetTag("http.request.method", "GET");
4949
dependencyActivity.SetTag("url.full", "http://bing.com");
@@ -67,7 +67,7 @@ public void VerifyHttpClientAttributes()
6767
// ASSERT
6868
Assert.Equal("http://bing.com", dependencyDocument.CommandName);
6969
Assert.Equal(DocumentType.RemoteDependency, dependencyDocument.DocumentType);
70-
Assert.Equal("HelloWorld", dependencyDocument.Name);
70+
Assert.Equal("TestActivityName", dependencyDocument.Name);
7171
Assert.Equal("200", dependencyDocument.ResultCode);
7272

7373
VerifyCustomProperties(dependencyDocument);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
using System;
5+
using System.Collections.Generic;
6+
using System.Diagnostics;
7+
using System.Linq;
8+
using System.Net.Http;
9+
using System.Threading.Tasks;
10+
using Azure.Monitor.OpenTelemetry.AspNetCore.LiveMetrics.DataCollection;
11+
using Azure.Monitor.OpenTelemetry.AspNetCore.Models;
12+
using Microsoft.AspNetCore.Builder;
13+
using OpenTelemetry;
14+
using OpenTelemetry.Trace;
15+
using Xunit;
16+
using Xunit.Abstractions;
17+
18+
namespace Azure.Monitor.OpenTelemetry.AspNetCore.Tests.LiveMetrics.DocumentTests
19+
{
20+
public class ManualDependencyTests : DocumentTestBase
21+
{
22+
public ManualDependencyTests(ITestOutputHelper output) : base(output)
23+
{
24+
}
25+
26+
[Theory]
27+
[InlineData(ActivityStatusCode.Ok, true)]
28+
[InlineData(ActivityStatusCode.Error, false)]
29+
[InlineData(ActivityStatusCode.Unset, true)]
30+
public void VerifyManualDependency(ActivityStatusCode activityStatusCode, bool expectedIsSuccess)
31+
{
32+
var exportedActivities = new List<Activity>();
33+
34+
var testActivitySource = new ActivitySource("TestActivitySource");
35+
36+
// SETUP
37+
using var tracerProvider = Sdk.CreateTracerProviderBuilder()
38+
.AddSource("TestActivitySource")
39+
.AddInMemoryExporter(exportedActivities)
40+
.Build();
41+
42+
// ACT
43+
using (var activity = testActivitySource.StartActivity("TestActivityName", ActivityKind.Internal))
44+
{
45+
activity?.SetStatus(activityStatusCode);
46+
}
47+
48+
tracerProvider.ForceFlush();
49+
WaitForActivityExport(exportedActivities);
50+
51+
// Assert
52+
var dependencyActivity = exportedActivities.Last();
53+
PrintActivity(dependencyActivity);
54+
var dependencyDocument = DocumentHelper.ConvertToDependencyDocument(dependencyActivity);
55+
56+
Assert.Null(dependencyDocument.CommandName);
57+
Assert.Equal(DocumentType.RemoteDependency, dependencyDocument.DocumentType);
58+
Assert.Equal("TestActivityName", dependencyDocument.Name);
59+
Assert.Equal("TestActivitySource", dependencyDocument.Properties.Single(x => x.Key == "ActivitySource").Value);
60+
61+
//// The following "EXTENSION" properties are used to calculate metrics. These are not serialized.
62+
Assert.Equal(dependencyActivity.Duration.TotalMilliseconds, dependencyDocument.Extension_Duration);
63+
Assert.Equal(expectedIsSuccess, dependencyDocument.Extension_IsSuccess);
64+
}
65+
}
66+
}

sdk/monitor/Azure.Monitor.OpenTelemetry.AspNetCore/tests/Azure.Monitor.OpenTelemetry.AspNetCore.Tests/LiveMetrics/DocumentTests/SqlClientDependencyTests.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public void VerifySqlClientAttributes()
4646
ActivitySource.AddActivityListener(listener);
4747

4848
// ACT
49-
using var dependencyActivity = activitySource.StartActivity(name: "HelloWorld", kind: ActivityKind.Client);
49+
using var dependencyActivity = activitySource.StartActivity(name: "TestActivityName", kind: ActivityKind.Client);
5050
Assert.NotNull(dependencyActivity);
5151
dependencyActivity.SetTag("db.system", "mssql");
5252
dependencyActivity.SetTag("db.name", "MyDatabase");
@@ -71,7 +71,7 @@ public void VerifySqlClientAttributes()
7171
Assert.Equal("select * from sys.databases", dependencyDocument.CommandName);
7272
Assert.Equal(DocumentType.RemoteDependency, dependencyDocument.DocumentType);
7373
Assert.Equal(dependencyActivity.Duration.ToString("c"), dependencyDocument.Duration);
74-
Assert.Equal("(localdb)\\MSSQLLocalDB | MyDatabase", dependencyDocument.Name);
74+
Assert.Equal("TestActivityName", dependencyDocument.Name);
7575

7676
VerifyCustomProperties(dependencyDocument);
7777

@@ -141,7 +141,7 @@ public void VerifySqlClientDependency(
141141
Assert.Equal(commandText, dependencyDocument.CommandName);
142142
Assert.Equal(DocumentType.RemoteDependency, dependencyDocument.DocumentType);
143143
Assert.Equal(dependencyActivity.Duration.ToString("c"), dependencyDocument.Duration);
144-
Assert.Equal("(localdb)\\MSSQLLocalDB | MyDatabase", dependencyDocument.Name);
144+
Assert.Equal("MyDatabase", dependencyDocument.Name);
145145

146146
// The following "EXTENSION" properties are used to calculate metrics. These are not serialized.
147147
Assert.Equal(dependencyActivity.Duration.TotalMilliseconds, dependencyDocument.Extension_Duration);
@@ -214,7 +214,7 @@ public void VerifySqlClientDependencyWithException(
214214
Assert.Equal(commandText, dependencyDocument.CommandName);
215215
Assert.Equal(DocumentType.RemoteDependency, dependencyDocument.DocumentType);
216216
Assert.Equal(dependencyActivity.Duration.ToString("c"), dependencyDocument.Duration);
217-
Assert.Equal("(localdb)\\MSSQLLocalDB | MyDatabase", dependencyDocument.Name);
217+
Assert.Equal("MyDatabase", dependencyDocument.Name);
218218

219219
// The following "EXTENSION" properties are used to calculate metrics. These are not serialized.
220220
Assert.Equal(dependencyActivity.Duration.TotalMilliseconds, dependencyDocument.Extension_Duration);

0 commit comments

Comments
 (0)