Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public RemoteDependencyData(int version, Activity activity, ref ActivityTagsProc
}

dependencyName ??= activity.DisplayName;
Name = dependencyName.Truncate(SchemaConstants.RemoteDependencyData_Name_MaxLength);
Name = dependencyName?.Truncate(SchemaConstants.RemoteDependencyData_Name_MaxLength);
Id = activity.Context.SpanId.ToHexString();
Duration = activity.Duration < SchemaConstants.RemoteDependencyData_Duration_LessThanDays
? activity.Duration.ToString("c", CultureInfo.InvariantCulture)
Expand Down Expand Up @@ -101,8 +101,8 @@ private void SetHttpDependencyPropertiesAndDependencyName(Activity activity, ref
}

Type = "Http";
Data = httpUrl.Truncate(SchemaConstants.RemoteDependencyData_Data_MaxLength);
Target = target.Truncate(SchemaConstants.RemoteDependencyData_Target_MaxLength);
Data = httpUrl?.Truncate(SchemaConstants.RemoteDependencyData_Data_MaxLength);
Target = target?.Truncate(SchemaConstants.RemoteDependencyData_Target_MaxLength);
ResultCode = resultCode?.Truncate(SchemaConstants.RemoteDependencyData_ResultCode_MaxLength) ?? "0";
}

Expand All @@ -111,11 +111,11 @@ private void SetDbDependencyProperties(ref AzMonList dbTagObjects)
var dbAttributeTagObjects = AzMonList.GetTagValues(ref dbTagObjects, SemanticConventions.AttributeDbStatement, SemanticConventions.AttributeDbSystem);
Data = dbAttributeTagObjects[0]?.ToString().Truncate(SchemaConstants.RemoteDependencyData_Data_MaxLength);
var (DbName, DbTarget) = dbTagObjects.GetDbDependencyTargetAndName();
Target = DbTarget.Truncate(SchemaConstants.RemoteDependencyData_Target_MaxLength);
Target = DbTarget?.Truncate(SchemaConstants.RemoteDependencyData_Target_MaxLength);
Type = s_sqlDbs.Contains(dbAttributeTagObjects[1]?.ToString()) ? "SQL" : dbAttributeTagObjects[1]?.ToString().Truncate(SchemaConstants.RemoteDependencyData_Type_MaxLength);

// special case for db.name
var sanitizedDbName = DbName.Truncate(SchemaConstants.KVP_MaxValueLength);
var sanitizedDbName = DbName?.Truncate(SchemaConstants.KVP_MaxValueLength);
if (sanitizedDbName != null)
{
Properties.Add(SemanticConventions.AttributeDbName, sanitizedDbName);
Expand All @@ -132,10 +132,10 @@ private void SetRpcDependencyProperties(ref AzMonList rpcTagObjects)

private void SetMessagingDependencyProperties(Activity activity, ref AzMonList messagingTagObjects)
{
var messagingAttributeTagObjects = AzMonList.GetTagValues(ref messagingTagObjects, SemanticConventions.AttributeMessagingUrl, SemanticConventions.AttributeMessagingSystem);
var messagingUrl = messagingAttributeTagObjects[0]?.ToString();
var (messagingUrl, target) = messagingTagObjects.GetMessagingUrlAndSourceOrTarget(activity.Kind);
Data = messagingUrl?.Truncate(SchemaConstants.RemoteDependencyData_Data_MaxLength);
Type = messagingAttributeTagObjects[1]?.ToString().Truncate(SchemaConstants.RemoteDependencyData_Type_MaxLength);
Target = target?.Truncate(SchemaConstants.RemoteDependencyData_Target_MaxLength);
Type = AzMonList.GetTagValue(ref messagingTagObjects, SemanticConventions.AttributeMessagingSystem)?.ToString().Truncate(SchemaConstants.RemoteDependencyData_Type_MaxLength);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,20 @@

using System.Diagnostics;
using System.Globalization;
using System.Runtime.CompilerServices;
using Azure.Core;
using Azure.Monitor.OpenTelemetry.Exporter.Internals;

namespace Azure.Monitor.OpenTelemetry.Exporter.Models
{
internal partial class RequestData
{
public RequestData(int version, string? operationName, string? requestUrl, Activity activity, ref ActivityTagsProcessor activityTagsProcessor) : this(version, activity, ref activityTagsProcessor)
{
Name = operationName?.Truncate(SchemaConstants.RequestData_Name_MaxLength);
Url = requestUrl?.Truncate(SchemaConstants.RequestData_Url_MaxLength);
}

public RequestData(int version, Activity activity, ref ActivityTagsProcessor activityTagsProcessor) : base(version)
{
string? responseCode = null;
Expand Down Expand Up @@ -50,6 +57,7 @@ public RequestData(int version, Activity activity, ref ActivityTagsProcessor act
TraceHelper.AddPropertiesToTelemetry(Properties, ref activityTagsProcessor.UnMappedTags);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static bool IsSuccess(Activity activity, string? responseCode, OperationType operationType)
{
if (operationType.HasFlag(OperationType.Http)
Expand All @@ -67,25 +75,27 @@ internal static bool IsSuccess(Activity activity, string? responseCode, Operatio

private void SetHttpRequestPropertiesAndResponseCode(Activity activity, ref AzMonList httpTagObjects, out string responseCode)
{
Url = httpTagObjects.GetRequestUrl().Truncate(SchemaConstants.RequestData_Url_MaxLength);
Name = TraceHelper.GetOperationName(activity, ref httpTagObjects).Truncate(SchemaConstants.RequestData_Name_MaxLength);
Url ??= httpTagObjects.GetRequestUrl()?.Truncate(SchemaConstants.RequestData_Url_MaxLength);
Name ??= TraceHelper.GetOperationName(activity, ref httpTagObjects)?.Truncate(SchemaConstants.RequestData_Name_MaxLength);
responseCode = AzMonList.GetTagValue(ref httpTagObjects, SemanticConventions.AttributeHttpStatusCode)
?.ToString().Truncate(SchemaConstants.RequestData_ResponseCode_MaxLength)
?? "0";
}

private void SetHttpV2RequestPropertiesAndResponseCode(Activity activity, ref AzMonList httpTagObjects, out string responseCode)
{
Url = httpTagObjects.GetNewSchemaRequestUrl().Truncate(SchemaConstants.RequestData_Url_MaxLength);
Name = TraceHelper.GetNewSchemaOperationName(activity, Url, ref httpTagObjects).Truncate(SchemaConstants.RequestData_Name_MaxLength);
Url ??= httpTagObjects.GetNewSchemaRequestUrl()?.Truncate(SchemaConstants.RequestData_Url_MaxLength);
Name ??= TraceHelper.GetNewSchemaOperationName(activity, Url, ref httpTagObjects)?.Truncate(SchemaConstants.RequestData_Name_MaxLength);
responseCode = AzMonList.GetTagValue(ref httpTagObjects, SemanticConventions.AttributeHttpResponseStatusCode)
?.ToString().Truncate(SchemaConstants.RequestData_ResponseCode_MaxLength)
?? "0";
}

private void SetMessagingRequestProperties(Activity activity, ref AzMonList messagingTagObjects)
{
Url = AzMonList.GetTagValue(ref messagingTagObjects, SemanticConventions.AttributeMessagingUrl)?.ToString().Truncate(SchemaConstants.RequestData_Url_MaxLength);
var (messagingUrl, source) = messagingTagObjects.GetMessagingUrlAndSourceOrTarget(activity.Kind);
Url = messagingUrl?.Truncate(SchemaConstants.RequestData_Url_MaxLength);
Source = source?.Truncate(SchemaConstants.RequestData_Source_MaxLength);
Name = activity.DisplayName;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,6 @@ public TelemetryItem(Activity activity, ref ActivityTagsProcessor activityTagsPr
}

SetAuthenticatedUserId(ref activityTagsProcessor);

// we only have mapping for server spans
// todo: non-server spans
if (activity.Kind == ActivityKind.Server)
{
Tags[ContextTagKeys.AiOperationName.ToString()] = activityTagsProcessor.activityType.HasFlag(OperationType.V2)
? TraceHelper.GetNewSchemaOperationName(activity, null, ref activityTagsProcessor.MappedTags)
: TraceHelper.GetOperationName(activity, ref activityTagsProcessor.MappedTags);
Tags[ContextTagKeys.AiLocationIp.ToString()] = TraceHelper.GetLocationIp(ref activityTagsProcessor.MappedTags);
}

SetResourceSdkVersionAndIkey(resource, instrumentationKey);
if (AzMonList.GetTagValue(ref activityTagsProcessor.MappedTags, "sampleRate") is float sampleRate)
{
Expand All @@ -62,14 +51,6 @@ public TelemetryItem(string name, TelemetryItem telemetryItem, ActivitySpanId ac
Tags["ai.user.userAgent"] = userAgent;
}

// we only have mapping for server spans
// todo: non-server spans
if (kind == ActivityKind.Server)
{
Tags[ContextTagKeys.AiOperationName.ToString()] = telemetryItem.Tags[ContextTagKeys.AiOperationName.ToString()];
Tags[ContextTagKeys.AiLocationIp.ToString()] = telemetryItem.Tags[ContextTagKeys.AiLocationIp.ToString()];
}

Tags[ContextTagKeys.AiCloudRole.ToString()] = telemetryItem.Tags[ContextTagKeys.AiCloudRole.ToString()];
Tags[ContextTagKeys.AiCloudRoleInstance.ToString()] = telemetryItem.Tags[ContextTagKeys.AiCloudRoleInstance.ToString()];
Tags[ContextTagKeys.AiInternalSdkVersion.ToString()] = SdkVersionUtils.s_sdkVersion;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,8 @@ internal struct ActivityTagsProcessor
SemanticConventions.AttributeEndpointAddress,
// required - Messaging
SemanticConventions.AttributeMessagingSystem,
SemanticConventions.AttributeMessagingDestination,
SemanticConventions.AttributeMessagingDestinationKind,
SemanticConventions.AttributeMessagingTempDestination,
SemanticConventions.AttributeMessagingUrl,
SemanticConventions.AttributeMessagingDestinationName,
SemanticConventions.AttributeNetworkProtocolName,

// Others
SemanticConventions.AttributeEnduserId
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Licensed under the MIT License.

using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;

namespace Azure.Monitor.OpenTelemetry.Exporter.Internals;
Expand All @@ -15,31 +16,79 @@ internal static class AzMonNewListExtensions
{
try
{
var serverAddress = AzMonList.GetTagValue(ref tagObjects, SemanticConventions.AttributeServerAddress)?.ToString();
if (serverAddress != null)
var requestUrlTagObjects = AzMonList.GetTagValues(ref tagObjects, SemanticConventions.AttributeUrlScheme, SemanticConventions.AttributeServerAddress, SemanticConventions.AttributeServerPort, SemanticConventions.AttributeUrlPath, SemanticConventions.AttributeUrlQuery);

var scheme = requestUrlTagObjects[0]?.ToString() ?? string.Empty; // requestUrlTagObjects[0] => SemanticConventions.AttributeUrlScheme.
var host = requestUrlTagObjects[1]?.ToString() ?? string.Empty; // requestUrlTagObjects[1] => SemanticConventions.AttributeServerAddress.
var port = requestUrlTagObjects[2]?.ToString(); // requestUrlTagObjects[2] => SemanticConventions.AttributeServerPort.
port = port != null ? port = $":{port}" : string.Empty;
var path = requestUrlTagObjects[3]?.ToString() ?? string.Empty; // requestUrlTagObjects[3] => SemanticConventions.AttributeUrlPath.
var queryString = requestUrlTagObjects[4]?.ToString() ?? string.Empty; // requestUrlTagObjects[4] => SemanticConventions.AttributeUrlQuery.

var length = scheme.Length + Uri.SchemeDelimiter.Length + host.Length + port.Length + path.Length + queryString.Length;

var urlStringBuilder = new System.Text.StringBuilder(length)
.Append(scheme)
.Append(Uri.SchemeDelimiter)
.Append(host)
.Append(port)
.Append(path)
.Append(queryString);

return urlStringBuilder.ToString();
}
catch
{
// If URI building fails, there is no need to throw an exception. Instead, we can simply return null.
}

return null;
}

///<summary>
/// Gets messaging url from activity tag objects.
///</summary>
internal static (string? MessagingUrl, string? SourceOrTarget) GetMessagingUrlAndSourceOrTarget(this AzMonList tagObjects, ActivityKind activityKind)
{
string? messagingUrl = null;
string? sourceOrTarget = null;

try
{
var host = AzMonList.GetTagValue(ref tagObjects, SemanticConventions.AttributeServerAddress)?.ToString()
?? AzMonList.GetTagValue(ref tagObjects, SemanticConventions.AttributeNetPeerName)?.ToString();
if (!string.IsNullOrEmpty(host))
{
UriBuilder uriBuilder = new()
{
Scheme = AzMonList.GetTagValue(ref tagObjects, SemanticConventions.AttributeUrlScheme)?.ToString(),
Host = serverAddress,
Path = AzMonList.GetTagValue(ref tagObjects, SemanticConventions.AttributeUrlPath)?.ToString(),
Query = AzMonList.GetTagValue(ref tagObjects, SemanticConventions.AttributeUrlQuery)?.ToString()
};
object?[] messagingTagObjects;

if (int.TryParse(AzMonList.GetTagValue(ref tagObjects, SemanticConventions.AttributeServerPort)?.ToString(), out int port))
messagingTagObjects = AzMonList.GetTagValues(ref tagObjects, SemanticConventions.AttributeNetworkProtocolName, SemanticConventions.AttributeMessagingDestinationName);
var protocolName = messagingTagObjects[0]?.ToString() ?? string.Empty; // messagingTagObjects[0] => SemanticConventions.AttributeNetworkProtocolName.
var destinationName = messagingTagObjects[1]?.ToString() ?? string.Empty; // messagingTagObjects[1] => SemanticConventions.AttributeMessagingDestinationName.

if (destinationName.Length > 0)
{
uriBuilder.Port = port;
destinationName = $"/{destinationName}";
}

return uriBuilder.Uri.AbsoluteUri;
sourceOrTarget = $"{host}{destinationName}";

var length = protocolName.Length + (protocolName?.Length > 0 ? Uri.SchemeDelimiter.Length : 0) + host!.Length + destinationName.Length;

var messagingStringBuilder = new System.Text.StringBuilder(length)
.Append(protocolName)
.Append(string.IsNullOrEmpty(protocolName) ? null : Uri.SchemeDelimiter)
.Append(host)
.Append(destinationName);

messagingUrl = messagingStringBuilder.ToString();
}
}
catch
{
// If URI building fails, there is no need to throw an exception. Instead, we can simply return null.
// If Messaging Url building fails, there is no need to throw an exception. Instead, we can simply return null.
}

return null;
return (MessagingUrl: messagingUrl, SourceOrTarget: sourceOrTarget);
}

///<summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,5 +163,9 @@ internal static class SemanticConventions
public const string AttributeUrlQuery = "url.query";
public const string AttributeUserAgentOriginal = "user_agent.original"; // replaces: "http.user_agent" (AttributeHttpUserAgent)
public const string AttributeServerSocketAddress = "server.socket.address"; // replaces: "net.peer.ip" (AttributeNetPeerIp)

// Messaging v1.21.0 https://github.com/open-telemetry/opentelemetry-specification/blob/v1.21.0/specification/trace/semantic_conventions/messaging.md
public const string AttributeMessagingDestinationName = "messaging.destination.name";
public const string AttributeNetworkProtocolName = "network.protocol.name";
}
}
Loading