in src/Elastic.OpenTelemetry.Core/Diagnostics/LogFormatter.cs [13:58]
public static string Format<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter)
{
var managedThreadId = Environment.CurrentManagedThreadId;
var dateTime = DateTime.UtcNow;
string? spanId = null;
var activity = Activity.Current;
switch (state)
{
case LogState s:
managedThreadId = s.ManagedThreadId;
dateTime = s.DateTime;
activity = s.Activity;
spanId = s.SpanId;
break;
}
var builder = StringBuilderCache.Acquire();
// Force exceptions to be written as errors
if (exception is not null)
logLevel = LogLevel.Error;
WriteLogPrefix(managedThreadId, dateTime, logLevel, builder, spanId ?? activity?.SpanId.ToHexString() ?? string.Empty);
var message = formatter(state, exception);
builder.Append(message);
if (eventId != default)
if (!string.IsNullOrEmpty(eventId.Name))
builder.Append(" {{EventId: " + eventId.Id + ", EventName: " + eventId.Name + "}}");
else
builder.Append(" {{EventId: " + eventId.Id + "}}");
if (activity is not null)
{
// Accessing activity.Id here will cause the Id to be initialized
// before the sampler runs in case where the activity is created using legacy way
// i.e. new Activity("Operation name"). This will result in Id not reflecting the
// correct sampling flags
// https://github.com/dotnet/runtime/issues/61857
var activityId = $"00-{activity.TraceId.ToHexString()}-{activity.SpanId.ToHexString()}-{(activity.ActivityTraceFlags.HasFlag(ActivityTraceFlags.Recorded) ? "01" : "00")}";
builder.Append($" <{activityId}>");
}
var fullLogLine = StringBuilderCache.GetStringAndRelease(builder);
return fullLogLine;
}