Skip to content

Commit

Permalink
Export span event as trace telemetry (Azure#32980)
Browse files Browse the repository at this point in the history
* export span event as trace telemetry

* revert demo

* mark method private

* assert

* rename method

* refactor

* resolve pr comments
  • Loading branch information
vishweshbankwar authored Jan 17, 2023
1 parent 89e96a5 commit e215b40
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ public TelemetryItem(Activity activity, ref TagEnumerationState monitorTags, str
}
}

public TelemetryItem(TelemetryItem telemetryItem, ActivitySpanId activitySpanId, ActivityKind kind, DateTimeOffset activityEventTimeStamp) :
this("Exception", FormatUtcTimestamp(activityEventTimeStamp.DateTime))
public TelemetryItem(string name, TelemetryItem telemetryItem, ActivitySpanId activitySpanId, ActivityKind kind, DateTimeOffset activityEventTimeStamp) :
this(name, FormatUtcTimestamp(activityEventTimeStamp.DateTime))
{
Tags[ContextTagKeys.AiOperationParentId.ToString()] = activitySpanId.ToHexString();
Tags[ContextTagKeys.AiOperationId.ToString()] = telemetryItem.Tags[ContextTagKeys.AiOperationId.ToString()];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ internal static List<TelemetryItem> OtelToAzureMonitorTrace(Batch<Activity> batc
// Check for Exceptions events
if (activity.Events.Any())
{
AddExceptionTelemetryFromActivityExceptionEvents(activity, telemetryItem, telemetryItems);
AddTelemetryFromActivityEvents(activity, telemetryItem, telemetryItems);
}

switch (activity.GetTelemetryType())
Expand Down Expand Up @@ -177,31 +177,62 @@ internal static string GetOperationName(Activity activity, ref AzMonList MappedT
return activity.DisplayName;
}

private static void AddExceptionTelemetryFromActivityExceptionEvents(Activity activity, TelemetryItem telemetryItem, List<TelemetryItem> telemetryItems)
private static void AddTelemetryFromActivityEvents(Activity activity, TelemetryItem telemetryItem, List<TelemetryItem> telemetryItems)
{
foreach (var evnt in activity.Events)
{
if (evnt.Name == SemanticConventions.AttributeExceptionEventName)
try
{
try
if (evnt.Name == SemanticConventions.AttributeExceptionEventName)
{
var exceptionData = GetExceptionDataDetailsOnTelemetryItem(evnt.Tags);
if (exceptionData != null)
{
var exceptionTelemetryItem = new TelemetryItem(telemetryItem, activity.SpanId, activity.Kind, evnt.Timestamp);
var exceptionTelemetryItem = new TelemetryItem("Exception", telemetryItem, activity.SpanId, activity.Kind, evnt.Timestamp);
exceptionTelemetryItem.Data = exceptionData;
telemetryItems.Add(exceptionTelemetryItem);
}
}
catch (Exception ex)
else
{
AzureMonitorExporterEventSource.Log.WriteWarning("FailedToExtractExceptionFromActivityEvent", ex);
var messageData = GetTraceTelemetryData(evnt);
if (messageData != null)
{
var traceTelemetryItem = new TelemetryItem("Message", telemetryItem, activity.SpanId, activity.Kind, evnt.Timestamp);
traceTelemetryItem.Data = messageData;
telemetryItems.Add(traceTelemetryItem);
}
}
}
catch (Exception ex)
{
AzureMonitorExporterEventSource.Log.WriteError("FailedToExtractActivityEvent", ex);
}
}
}

private static MonitorBase GetTraceTelemetryData(ActivityEvent activityEvent)
{
if (activityEvent.Name == null)
{
return null;
}

var messageData = new MessageData(Version, activityEvent.Name);

foreach (var tag in activityEvent.Tags)
{
messageData.Properties.Add(tag.Key, tag.Value.ToString());
}

return new MonitorBase
{
BaseType = "MessageData",
BaseData = messageData,
};
}

internal static MonitorBase GetExceptionDataDetailsOnTelemetryItem(IEnumerable<KeyValuePair<string, object>> activityEventTags)
private static MonitorBase GetExceptionDataDetailsOnTelemetryItem(IEnumerable<KeyValuePair<string, object>> activityEventTags)
{
string exceptionType = null;
string exceptionStackTrace = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public void ValidateSampleRateForEventException(object SampleRate)

var monitorTags = TraceHelper.EnumerateActivityTags(activity);
var telemetryItem = new TelemetryItem(activity, ref monitorTags, "RoleName", "RoleInstance", "00000000-0000-0000-0000-000000000000");
var expTelemetryItem = new TelemetryItem(telemetryItem, default, default, default);
var expTelemetryItem = new TelemetryItem("Exception", telemetryItem, default, default, default);

if (SampleRate is float)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -238,11 +238,44 @@ public void ActivityWithExceptionEventCreatesExceptionTelemetry()
var telemetryItems = TraceHelper.OtelToAzureMonitorTrace(batch, "roleName", "roleInstance", "00000000-0000-0000-0000-000000000000");

Assert.Equal(2, telemetryItems.Count());
Assert.Equal("Exception", (IEnumerable<char>)telemetryItems[0].Name);
Assert.Equal("Request", (IEnumerable<char>)telemetryItems[1].Name);
Assert.Equal(exceptionMessage, (IEnumerable<char>)(telemetryItems[0].Data.BaseData as TelemetryExceptionData).Exceptions.First().Message);
Assert.Equal("System.Exception", (IEnumerable<char>)(telemetryItems[0].Data.BaseData as TelemetryExceptionData).Exceptions.First().TypeName);
Assert.Equal("System.Exception: Exception Message", (IEnumerable<char>)(telemetryItems[0].Data.BaseData as TelemetryExceptionData).Exceptions.First().Stack);
Assert.Equal("Exception", telemetryItems[0].Name);
Assert.Equal("Request", telemetryItems[1].Name);
Assert.Equal(exceptionMessage, (telemetryItems[0].Data.BaseData as TelemetryExceptionData).Exceptions.First().Message);
Assert.Equal("System.Exception", (telemetryItems[0].Data.BaseData as TelemetryExceptionData).Exceptions.First().TypeName);
Assert.Equal("System.Exception: Exception Message", (telemetryItems[0].Data.BaseData as TelemetryExceptionData).Exceptions.First().Stack);
}

[Fact]
public void ActivityWithEventCreatesTraceTelemetry()
{
var eventName = "Custom Event";
using ActivitySource activitySource = new ActivitySource(ActivitySourceName);
using var activity = activitySource.StartActivity(
ActivityName,
ActivityKind.Server);

var tagsCollection = new ActivityTagsCollection
{
{ "key1", "value1" },
};

var activityEvent = new ActivityEvent(eventName, default, tagsCollection);

activity.AddEvent(activityEvent);

Activity[] activityList = new Activity[1];
activityList[0] = activity;
Batch<Activity> batch = new Batch<Activity>(activityList, 1);

var telemetryItems = TraceHelper.OtelToAzureMonitorTrace(batch, "roleName", "roleInstance", "00000000-0000-0000-0000-000000000000");

Assert.Equal(2, telemetryItems.Count());
Assert.Equal("Message", telemetryItems[0].Name);
Assert.Equal("Request", telemetryItems[1].Name);
Assert.Equal(eventName, (telemetryItems[0].Data.BaseData as MessageData).Message);
Assert.True((telemetryItems[0].Data.BaseData as MessageData).Properties.TryGetValue("key1", out var value));
Assert.Equal("value1", value);
Assert.Null((telemetryItems[0].Data.BaseData as MessageData).SeverityLevel);
}

[Fact]
Expand Down Expand Up @@ -295,7 +328,7 @@ public void ActivityWithExceptionEventDoesNotCreateExceptionTelemetryWhenTypeNam
var telemetryItems = TraceHelper.OtelToAzureMonitorTrace(batch, "roleName", "roleInstance", "00000000 - 0000 - 0000 - 0000 - 000000000000");

Assert.Single(telemetryItems);
Assert.Equal("Request", (IEnumerable<char>)telemetryItems[0].Name);
Assert.Equal("Request", telemetryItems[0].Name);
}

private string GetExpectedMSlinks(IEnumerable<ActivityLink> links)
Expand Down

0 comments on commit e215b40

Please sign in to comment.