Skip to content

Commit

Permalink
[AzureMonitorExporter] fix more nullables (#34092)
Browse files Browse the repository at this point in the history
* fix more nullables

* update to match spec

* cleanup
  • Loading branch information
TimothyMothra authored Feb 11, 2023
1 parent 2606ffd commit d294e07
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace Azure.Monitor.OpenTelemetry.Exporter.Models
{
internal partial class TelemetryItem
{
public TelemetryItem(Activity activity, ref TagEnumerationState monitorTags, AzureMonitorResource resource, string instrumentationKey) :
public TelemetryItem(Activity activity, ref TagEnumerationState monitorTags, AzureMonitorResource? resource, string instrumentationKey) :
this(activity.GetTelemetryType() == TelemetryType.Request ? "Request" : "RemoteDependency", FormatUtcTimestamp(activity.StartTimeUtc))
{
if (activity.ParentSpanId != default)
Expand Down Expand Up @@ -73,7 +73,7 @@ public TelemetryItem(string name, TelemetryItem telemetryItem, ActivitySpanId ac
SampleRate = telemetryItem.SampleRate;
}

public TelemetryItem (LogRecord logRecord, AzureMonitorResource resource, string instrumentationKey) :
public TelemetryItem (LogRecord logRecord, AzureMonitorResource? resource, string instrumentationKey) :
this(logRecord.Exception != null ? "Exception" : "Message", FormatUtcTimestamp(logRecord.Timestamp))
{
if (logRecord.TraceId != default)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

#nullable disable // TODO: remove and fix errors

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
Expand All @@ -26,7 +24,7 @@ internal class LogsHelper
private static readonly ConcurrentDictionary<int, string> s_depthCache = new ConcurrentDictionary<int, string>();
private static readonly Func<int, string> s_convertDepthToStringRef = ConvertDepthToString;

internal static List<TelemetryItem> OtelToAzureMonitorLogs(Batch<LogRecord> batchLogRecord, AzureMonitorResource resource, string instrumentationKey)
internal static List<TelemetryItem> OtelToAzureMonitorLogs(Batch<LogRecord> batchLogRecord, AzureMonitorResource? resource, string instrumentationKey)
{
List<TelemetryItem> telemetryItems = new List<TelemetryItem>();
TelemetryItem telemetryItem;
Expand Down Expand Up @@ -57,15 +55,15 @@ internal static List<TelemetryItem> OtelToAzureMonitorLogs(Batch<LogRecord> batc
return telemetryItems;
}

internal static string GetMessageAndSetProperties(LogRecord logRecord, IDictionary<string, string> properties)
internal static string? GetMessageAndSetProperties(LogRecord logRecord, IDictionary<string, string> properties)
{
string message = logRecord.FormattedMessage;
string? message = logRecord.FormattedMessage;

// Both logRecord.State and logRecord.StateValues will not be set at the same time for LogRecord.
// Either logRecord.State != null or logRecord.StateValues will be called.
if (logRecord.State != null)
{
if (logRecord.State is IReadOnlyCollection<KeyValuePair<string, object>> stateDictionary)
if (logRecord.State is IReadOnlyCollection<KeyValuePair<string, object?>> stateDictionary)
{
ExtractProperties(ref message, properties, stateDictionary);
}
Expand Down Expand Up @@ -93,14 +91,14 @@ internal static string GetMessageAndSetProperties(LogRecord logRecord, IDictiona

internal static void WriteScopeInformation(LogRecord logRecord, IDictionary<string, string> properties)
{
StringBuilder builder = null;
StringBuilder? builder = null;
int originalScopeDepth = 1;
logRecord.ForEachScope(ProcessScope, properties);

void ProcessScope(LogRecordScope scope, IDictionary<string, string> properties)
{
int valueDepth = 1;
foreach (KeyValuePair<string, object> scopeItem in scope)
foreach (KeyValuePair<string, object?> scopeItem in scope)
{
if (string.IsNullOrEmpty(scopeItem.Key))
{
Expand All @@ -109,7 +107,7 @@ void ProcessScope(LogRecordScope scope, IDictionary<string, string> properties)
}
else if (scopeItem.Key == "{OriginalFormat}")
{
properties.Add($"OriginalFormatScope_{s_depthCache.GetOrAdd(originalScopeDepth, s_convertDepthToStringRef)}", Convert.ToString(scope.Scope.ToString(), CultureInfo.InvariantCulture));
properties.Add($"OriginalFormatScope_{s_depthCache.GetOrAdd(originalScopeDepth, s_convertDepthToStringRef)}", Convert.ToString(scope.Scope?.ToString(), CultureInfo.InvariantCulture));
}
else if (!properties.TryGetValue(scopeItem.Key, out _))
{
Expand Down Expand Up @@ -138,8 +136,8 @@ internal static string GetProblemId(Exception exception)
int methodOffset = System.Diagnostics.StackFrame.OFFSET_UNKNOWN;

var exceptionType = exception.GetType().FullName;
var strackTrace = new StackTrace(exception);
var exceptionStackFrame = strackTrace.GetFrame(0);
var stackTrace = new StackTrace(exception);
var exceptionStackFrame = stackTrace.GetFrame(0);

if (exceptionStackFrame != null)
{
Expand Down Expand Up @@ -187,27 +185,30 @@ internal static SeverityLevel GetSeverityLevel(LogLevel logLevel)
}
}

private static void ExtractProperties(ref string message, IDictionary<string, string> properties, IReadOnlyCollection<KeyValuePair<string, object>> stateDictionary)
private static void ExtractProperties(ref string? message, IDictionary<string, string> properties, IReadOnlyCollection<KeyValuePair<string, object?>> stateDictionary)
{
foreach (KeyValuePair<string, object> item in stateDictionary)
foreach (KeyValuePair<string, object?> item in stateDictionary)
{
if (item.Key == "{OriginalFormat}")
if (item.Key.Length <= SchemaConstants.KVP_MaxKeyLength && item.Value != null)
{
if (message == null)
// Note: if Key exceeds MaxLength, the entire KVP will be dropped.

if (item.Key == "{OriginalFormat}")
{
message = item.Value.ToString();
if (message == null)
{
message = item.Value.ToString();
}
else
{
properties.Add("OriginalFormat", item.Value.ToString().Truncate(SchemaConstants.KVP_MaxValueLength));
}
}
else
{
properties.Add("OriginalFormat", item.Value.ToString().Truncate(SchemaConstants.KVP_MaxValueLength));
properties.Add(item.Key, item.Value.ToString().Truncate(SchemaConstants.KVP_MaxValueLength));
}
}
else if (item.Key.Length <= SchemaConstants.KVP_MaxKeyLength)
{
// Note: if Key exceeds MaxLength, the entire KVP will be dropped.

properties.Add(item.Key, item.Value.ToString().Truncate(SchemaConstants.KVP_MaxValueLength));
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,9 @@ internal struct TagEnumerationState
private OperationType _tempActivityType;
public OperationType activityType;

public void ForEach(IEnumerable<KeyValuePair<string, object>> activityTags)
public void ForEach(IEnumerable<KeyValuePair<string, object?>> activityTags)
{
foreach (KeyValuePair<string, object> activityTag in activityTags)
foreach (KeyValuePair<string, object?> activityTag in activityTags)
{
if (activityTag.Value == null)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

#nullable disable // TODO: remove and fix errors

using System;
using System.Collections.Generic;
using System.Diagnostics;
Expand All @@ -21,7 +19,7 @@ internal static class TraceHelper
private const int Version = 2;
private const int MaxlinksAllowed = 100;

internal static List<TelemetryItem> OtelToAzureMonitorTrace(Batch<Activity> batchActivity, AzureMonitorResource resource, string instrumentationKey)
internal static List<TelemetryItem> OtelToAzureMonitorTrace(Batch<Activity> batchActivity, AzureMonitorResource? resource, string instrumentationKey)
{
List<TelemetryItem> telemetryItems = new List<TelemetryItem>();
TelemetryItem telemetryItem;
Expand Down Expand Up @@ -144,7 +142,7 @@ internal static TagEnumerationState EnumerateActivityTags(Activity activity)
return monitorTags;
}

internal static string GetLocationIp(ref AzMonList MappedTags)
internal static string? GetLocationIp(ref AzMonList MappedTags)
{
var httpClientIp = AzMonList.GetTagValue(ref MappedTags, SemanticConventions.AttributeHttpClientIP)?.ToString();
if (!string.IsNullOrWhiteSpace(httpClientIp))
Expand All @@ -161,14 +159,16 @@ internal static string GetOperationName(Activity activity, ref AzMonList MappedT
if (!string.IsNullOrWhiteSpace(httpMethod))
{
var httpRoute = AzMonList.GetTagValue(ref MappedTags, SemanticConventions.AttributeHttpRoute)?.ToString();

// ASP.NET instrumentation assigns route as {controller}/{action}/{id} which would result in the same name for different operations.
// To work around that we will use path from httpUrl.
if (!string.IsNullOrWhiteSpace(httpRoute) && !httpRoute.Contains("{controller}"))
if (!string.IsNullOrWhiteSpace(httpRoute) && !httpRoute!.Contains("{controller}"))
{
return $"{httpMethod} {httpRoute}";
}

var httpUrl = AzMonList.GetTagValue(ref MappedTags, SemanticConventions.AttributeHttpUrl)?.ToString();
if (!string.IsNullOrWhiteSpace(httpUrl) && Uri.TryCreate(httpUrl.ToString(), UriKind.RelativeOrAbsolute, out var uri) && uri.IsAbsoluteUri)
if (!string.IsNullOrWhiteSpace(httpUrl) && Uri.TryCreate(httpUrl!.ToString(), UriKind.RelativeOrAbsolute, out var uri) && uri.IsAbsoluteUri)
{
return $"{httpMethod} {uri.AbsolutePath}";
}
Expand Down Expand Up @@ -211,7 +211,7 @@ private static void AddTelemetryFromActivityEvents(Activity activity, TelemetryI
}
}

private static MonitorBase GetTraceTelemetryData(ActivityEvent activityEvent)
private static MonitorBase? GetTraceTelemetryData(ActivityEvent activityEvent)
{
if (activityEvent.Name == null)
{
Expand All @@ -228,7 +228,7 @@ private static MonitorBase GetTraceTelemetryData(ActivityEvent activityEvent)
}
else
{
messageData.Properties.Add(tag.Key, tag.Value.ToString());
messageData.Properties.Add(tag.Key, tag.Value?.ToString());
}
}

Expand All @@ -239,29 +239,29 @@ private static MonitorBase GetTraceTelemetryData(ActivityEvent activityEvent)
};
}

private static MonitorBase GetExceptionDataDetailsOnTelemetryItem(IEnumerable<KeyValuePair<string, object>> activityEventTags)
private static MonitorBase? GetExceptionDataDetailsOnTelemetryItem(IEnumerable<KeyValuePair<string, object?>> activityEventTags)
{
string exceptionType = null;
string exceptionStackTrace = null;
string exceptionMessage = null;
string? exceptionType = null;
string? exceptionStackTrace = null;
string? exceptionMessage = null;

// TODO: update to use perf improvements in .NET7.0
foreach (var tag in activityEventTags)
{
// TODO: see if these can be cached
if (tag.Key == SemanticConventions.AttributeExceptionType)
{
exceptionType = tag.Value.ToString();
exceptionType = tag.Value?.ToString();
continue;
}
if (tag.Key == SemanticConventions.AttributeExceptionMessage)
{
exceptionMessage = tag.Value.ToString();
exceptionMessage = tag.Value?.ToString();
continue;
}
if (tag.Key == SemanticConventions.AttributeExceptionStacktrace)
{
exceptionStackTrace = tag.Value.ToString();
exceptionStackTrace = tag.Value?.ToString();
continue;
}
}
Expand All @@ -275,7 +275,7 @@ private static MonitorBase GetExceptionDataDetailsOnTelemetryItem(IEnumerable<Ke
{
Stack = exceptionStackTrace.Truncate(SchemaConstants.ExceptionDetails_Stack_MaxLength),

HasFullStack = exceptionStackTrace.Length <= SchemaConstants.ExceptionDetails_Stack_MaxLength,
HasFullStack = exceptionStackTrace != null && (exceptionStackTrace.Length <= SchemaConstants.ExceptionDetails_Stack_MaxLength),

// TODO: Update swagger schema to mandate typename.
TypeName = exceptionType.Truncate(SchemaConstants.ExceptionDetails_TypeName_MaxLength),
Expand Down

0 comments on commit d294e07

Please sign in to comment.