Skip to content

Commit 15d3fce

Browse files
Add ai.location.ip and ai.user.userAgent mapping (Azure#23524)
* add ai.location.ip and ai.user.userAgent mapping * update clientIP * revert generated class change * resolve PR comments
1 parent b0403de commit 15d3fce

File tree

3 files changed

+119
-5
lines changed

3 files changed

+119
-5
lines changed

sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/src/TagEnumerationState.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ internal struct TagEnumerationState
2222
[SemanticConventions.AttributeHttpHost] = PartBType.Http,
2323
[SemanticConventions.AttributeHttpHostPort] = PartBType.Http,
2424
[SemanticConventions.AttributeHttpTarget] = PartBType.Http,
25+
[SemanticConventions.AttributeHttpUserAgent] = PartBType.Http,
26+
[SemanticConventions.AttributeHttpClientIP] = PartBType.Http,
2527

2628
[SemanticConventions.AttributePeerService] = PartBType.Common,
2729
[SemanticConventions.AttributeNetPeerName] = PartBType.Common,

sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/src/TelemetryPartA.cs

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,20 +39,24 @@ internal static TelemetryItem GetTelemetryItem(Activity activity, ref TagEnumera
3939
};
4040

4141
InitRoleInfo(resource);
42+
43+
if (activity.ParentSpanId != default)
44+
{
45+
telemetryItem.Tags[ContextTagKeys.AiOperationParentId.ToString()] = activity.ParentSpanId.ToHexString();
46+
}
47+
4248
telemetryItem.Tags[ContextTagKeys.AiCloudRole.ToString()] = RoleName;
4349
telemetryItem.Tags[ContextTagKeys.AiCloudRoleInstance.ToString()] = RoleInstance;
4450
telemetryItem.Tags[ContextTagKeys.AiOperationId.ToString()] = activity.TraceId.ToHexString();
51+
// todo: update swagger to include this key.
52+
telemetryItem.Tags["ai.user.userAgent"] = AzMonList.GetTagValue(ref monitorTags.PartBTags, SemanticConventions.AttributeHttpUserAgent)?.ToString();
4553

4654
// we only have mapping for server spans
4755
// todo: non-server spans
4856
if (activity.Kind == ActivityKind.Server)
4957
{
5058
telemetryItem.Tags[ContextTagKeys.AiOperationName.ToString()] = GetOperationName(activity, ref monitorTags.PartBTags);
51-
}
52-
53-
if (activity.ParentSpanId != default)
54-
{
55-
telemetryItem.Tags[ContextTagKeys.AiOperationParentId.ToString()] = activity.ParentSpanId.ToHexString();
59+
telemetryItem.Tags[ContextTagKeys.AiLocationIp.ToString()] = GetLocationIp(ref monitorTags.PartBTags);
5660
}
5761

5862
telemetryItem.Tags[ContextTagKeys.AiInternalSdkVersion.ToString()] = SdkVersionUtils.SdkVersion;
@@ -71,6 +75,17 @@ private static string GetOperationName(Activity activity, ref AzMonList partBTag
7175
return activity.DisplayName;
7276
}
7377

78+
private static string GetLocationIp(ref AzMonList partBTags)
79+
{
80+
var httpClientIp = AzMonList.GetTagValue(ref partBTags, SemanticConventions.AttributeHttpClientIP)?.ToString();
81+
if (!string.IsNullOrWhiteSpace(httpClientIp))
82+
{
83+
return httpClientIp;
84+
}
85+
86+
return AzMonList.GetTagValue(ref partBTags, SemanticConventions.AttributeNetPeerIp)?.ToString();
87+
}
88+
7489
internal static TelemetryItem GetTelemetryItem(LogRecord logRecord, string instrumentationKey)
7590
{
7691
var name = PartA_Name_Mapping[TelemetryType.Message];

sdk/monitor/Azure.Monitor.OpenTelemetry.Exporter/tests/Azure.Monitor.OpenTelemetry.Exporter.Tests/TelemetryPartATests.cs

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,103 @@ public void ActivityNameIsUsedByDefaultForRequestOperationName()
225225
Assert.Equal("displayname", telemetryItem.Tags[ContextTagKeys.AiOperationName.ToString()]);
226226
}
227227

228+
[Fact]
229+
public void AiLocationIpisSetAsHttpClientIpforHttpServerSpans()
230+
{
231+
using ActivitySource activitySource = new ActivitySource(ActivitySourceName);
232+
using var activity = activitySource.StartActivity(
233+
ActivityName,
234+
ActivityKind.Server,
235+
null,
236+
startTime: DateTime.UtcNow);
237+
var resource = CreateTestResource();
238+
239+
activity.SetTag(SemanticConventions.AttributeHttpClientIP, "127.0.0.1");
240+
241+
var monitorTags = AzureMonitorConverter.EnumerateActivityTags(activity);
242+
243+
var telemetryItem = TelemetryPartA.GetTelemetryItem(activity, ref monitorTags, resource, null);
244+
245+
Assert.Equal("127.0.0.1", telemetryItem.Tags[ContextTagKeys.AiLocationIp.ToString()]);
246+
}
247+
248+
[Fact]
249+
public void AiLocationIpisSetAsNetPeerIpForServerSpans()
250+
{
251+
using ActivitySource activitySource = new ActivitySource(ActivitySourceName);
252+
using var activity = activitySource.StartActivity(
253+
ActivityName,
254+
ActivityKind.Server,
255+
null,
256+
startTime: DateTime.UtcNow);
257+
var resource = CreateTestResource();
258+
259+
activity.SetTag(SemanticConventions.AttributeNetPeerIp, "127.0.0.1");
260+
261+
var monitorTags = AzureMonitorConverter.EnumerateActivityTags(activity);
262+
263+
var telemetryItem = TelemetryPartA.GetTelemetryItem(activity, ref monitorTags, resource, null);
264+
265+
Assert.Equal("127.0.0.1", telemetryItem.Tags[ContextTagKeys.AiLocationIp.ToString()]);
266+
}
267+
268+
[Fact]
269+
public void AiUserAgentisSetAsHttpUserAgent()
270+
{
271+
using ActivitySource activitySource = new ActivitySource(ActivitySourceName);
272+
using var activity = activitySource.StartActivity(
273+
ActivityName,
274+
ActivityKind.Server,
275+
null,
276+
startTime: DateTime.UtcNow);
277+
var resource = CreateTestResource();
278+
279+
var userAgent = "Mozilla / 5.0(Windows NT 10.0;WOW64) AppleWebKit / 537.36(KHTML, like Gecko) Chrome / 91.0.4472.101 Safari / 537.36";
280+
activity.SetTag(SemanticConventions.AttributeHttpUserAgent, userAgent);
281+
282+
var monitorTags = AzureMonitorConverter.EnumerateActivityTags(activity);
283+
284+
var telemetryItem = TelemetryPartA.GetTelemetryItem(activity, ref monitorTags, resource, null);
285+
286+
Assert.Equal(userAgent, telemetryItem.Tags["ai.user.userAgent"]);
287+
}
288+
289+
[Fact]
290+
public void AiLocationIpIsNullByDefault()
291+
{
292+
using ActivitySource activitySource = new ActivitySource(ActivitySourceName);
293+
using var activity = activitySource.StartActivity(
294+
ActivityName,
295+
ActivityKind.Server,
296+
null,
297+
startTime: DateTime.UtcNow);
298+
var resource = CreateTestResource();
299+
300+
var monitorTags = AzureMonitorConverter.EnumerateActivityTags(activity);
301+
302+
var telemetryItem = TelemetryPartA.GetTelemetryItem(activity, ref monitorTags, resource, null);
303+
304+
Assert.Null(telemetryItem.Tags[ContextTagKeys.AiLocationIp.ToString()]);
305+
}
306+
307+
[Fact]
308+
public void AiUserAgentIsNullByDefault()
309+
{
310+
using ActivitySource activitySource = new ActivitySource(ActivitySourceName);
311+
using var activity = activitySource.StartActivity(
312+
ActivityName,
313+
ActivityKind.Server,
314+
null,
315+
startTime: DateTime.UtcNow);
316+
var resource = CreateTestResource();
317+
318+
var monitorTags = AzureMonitorConverter.EnumerateActivityTags(activity);
319+
320+
var telemetryItem = TelemetryPartA.GetTelemetryItem(activity, ref monitorTags, resource, null);
321+
322+
Assert.Null(telemetryItem.Tags["ai.user.userAgent"]);
323+
}
324+
228325
/// <summary>
229326
/// If SERVICE.NAME is not defined, it will fall-back to "unknown_service".
230327
/// (https://github.com/open-telemetry/opentelemetry-specification/tree/main/specification/resource/semantic_conventions#semantic-attributes-with-sdk-provided-default-value).

0 commit comments

Comments
 (0)