Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 63 additions & 8 deletions src/core/Akka.API.Tests/LogFormatSpec.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
Expand All @@ -32,9 +33,9 @@ public DefaultLogFormatSpec() : base(CustomLoggerSetup())
{
_logger = (CustomLogger)Sys.Settings.StdoutLogger;
}

private readonly CustomLogger _logger;

public class CustomLogger : StandardOutLogger
{
protected override void Log(object message)
Expand All @@ -44,13 +45,13 @@ protected override void Log(object message)
{
_events.Add(e);
}

}

private readonly ConcurrentBag<LogEvent> _events = new();
public IReadOnlyCollection<LogEvent> Events => _events;
}

public static ActorSystemSetup CustomLoggerSetup()
{
var hocon = @$"
Expand Down Expand Up @@ -109,10 +110,51 @@ await AwaitConditionAsync(() =>
text = SanitizeThreadNumber(text);
// to resolve https://github.com/akkadotnet/akka.net/issues/7421
text = SanitizeTestEventListener(text);

await Verifier.Verify(text);
}


/// <summary>
/// Validation spec for https://github.com/akkadotnet/akka.net/issues/6855
/// </summary>
[Fact]
public async Task ShouldUseDefaultLogFormatWithTraceCorrelation()
{
// arrange
var filePath = Path.GetTempFileName();

// act
using (new OutputRedirector(filePath))
{
using var activity = new Activity("test").Start();
Activity.Current = activity;

Sys.Log.Debug("This is a test {0} {1}", 1, "cheese");
Sys.Log.Info("This is a test {0}", 1);
Sys.Log.Warning("This is a test {0}", 1);
Sys.Log.Error("This is a test {0}", 1);

// force all logs to be received
await AwaitConditionAsync(() =>
{
return _logger.Events.Count(c => c.Message.ToString()!.Contains("This is a test")) == 4;
});
}

// ReSharper disable once MethodHasAsyncOverload
var text = File.ReadAllText(filePath);

// need to sanitize the thread id
text = SanitizeDateTime(text);
text = SanitizeThreadNumber(text);
// to resolve https://github.com/akkadotnet/akka.net/issues/7421
text = SanitizeTestEventListener(text);
text = SanitizeTraceId(text);

await Verifier.Verify(text);

}

private static string SanitizeTestEventListener(string logs)
{
var pattern = @"^.*Akka\.TestKit\.TestEventListener.*$";
Expand All @@ -138,4 +180,17 @@ private static string SanitizeDateTime(string logs, string replacement = "DateTi

return result;
}
}

// Matches TraceId=<hex>, SpanId=<hex>
private const string PATTERN =
@"TraceId=([0-9a-f]{32}), SpanId=([0-9a-f]{16})";

private const string REPLACEMENT =
"TraceId=00000000000000000000000000000000, SpanId=0000000000000000";

private static string SanitizeTraceId(string logs)
{
var result = Regex.Replace(logs, PATTERN, REPLACEMENT);
return result;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3320,6 +3320,7 @@ namespace Akka.Event
public Akka.Actor.IActorRef Sender { get; }
public override string ToString() { }
}
[System.Runtime.CompilerServices.NullableAttribute(0)]
public sealed class BusLogging : Akka.Event.LoggingAdapterBase
{
public BusLogging(Akka.Event.LoggingBus bus, string logSource, System.Type logClass, Akka.Event.ILogMessageFormatter logMessageFormatter) { }
Expand Down Expand Up @@ -3349,6 +3350,7 @@ namespace Akka.Event
{
public Debug(string logSource, System.Type logClass, object message) { }
public Debug(System.Exception cause, string logSource, System.Type logClass, object message) { }
public Debug(System.Exception cause, string logSource, System.Type logClass, object message, [System.Runtime.CompilerServices.IsReadOnlyAttribute()] ref System.Diagnostics.ActivityContext context) { }
public override Akka.Event.LogLevel LogLevel() { }
}
public class DefaultLogMessageFormatter : Akka.Event.ILogMessageFormatter
Expand Down Expand Up @@ -3376,6 +3378,7 @@ namespace Akka.Event
public class Error : Akka.Event.LogEvent
{
public Error(System.Exception cause, string logSource, System.Type logClass, object message) { }
public Error(System.Exception cause, string logSource, System.Type logClass, object message, [System.Runtime.CompilerServices.IsReadOnlyAttribute()] ref System.Diagnostics.ActivityContext context) { }
public override Akka.Event.LogLevel LogLevel() { }
}
public abstract class EventBus<TEvent, TClassifier, TSubscriber>
Expand Down Expand Up @@ -3434,16 +3437,20 @@ namespace Akka.Event
{
public Info(string logSource, System.Type logClass, object message) { }
public Info(System.Exception cause, string logSource, System.Type logClass, object message) { }
public Info(System.Exception cause, string logSource, System.Type logClass, object message, [System.Runtime.CompilerServices.IsReadOnlyAttribute()] ref System.Diagnostics.ActivityContext context) { }
public override Akka.Event.LogLevel LogLevel() { }
}
public class InitializeLogger : Akka.Actor.INoSerializationVerificationNeeded
{
public InitializeLogger(Akka.Event.LoggingBus loggingBus) { }
public Akka.Event.LoggingBus LoggingBus { get; }
}
[System.Runtime.CompilerServices.NullableAttribute(0)]
public abstract class LogEvent : Akka.Actor.INoSerializationVerificationNeeded
{
protected LogEvent() { }
public System.Diagnostics.ActivityContext ActivityContext { get; set; }
[System.Runtime.CompilerServices.NullableAttribute(2)]
public System.Exception Cause { get; set; }
public System.Type LogClass { get; set; }
public string LogSource { get; set; }
Expand Down Expand Up @@ -3723,6 +3730,7 @@ namespace Akka.Event
{
public Warning(string logSource, System.Type logClass, object message) { }
public Warning(System.Exception cause, string logSource, System.Type logClass, object message) { }
public Warning(System.Exception cause, string logSource, System.Type logClass, object message, [System.Runtime.CompilerServices.IsReadOnlyAttribute()] ref System.Diagnostics.ActivityContext context) { }
public override Akka.Event.LogLevel LogLevel() { }
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3312,6 +3312,7 @@ namespace Akka.Event
public Akka.Actor.IActorRef Sender { get; }
public override string ToString() { }
}
[System.Runtime.CompilerServices.NullableAttribute(0)]
public sealed class BusLogging : Akka.Event.LoggingAdapterBase
{
public BusLogging(Akka.Event.LoggingBus bus, string logSource, System.Type logClass, Akka.Event.ILogMessageFormatter logMessageFormatter) { }
Expand Down Expand Up @@ -3341,6 +3342,7 @@ namespace Akka.Event
{
public Debug(string logSource, System.Type logClass, object message) { }
public Debug(System.Exception cause, string logSource, System.Type logClass, object message) { }
public Debug(System.Exception cause, string logSource, System.Type logClass, object message, ref System.Diagnostics.ActivityContext context) { }
public override Akka.Event.LogLevel LogLevel() { }
}
public class DefaultLogMessageFormatter : Akka.Event.ILogMessageFormatter
Expand Down Expand Up @@ -3368,6 +3370,7 @@ namespace Akka.Event
public class Error : Akka.Event.LogEvent
{
public Error(System.Exception cause, string logSource, System.Type logClass, object message) { }
public Error(System.Exception cause, string logSource, System.Type logClass, object message, ref System.Diagnostics.ActivityContext context) { }
public override Akka.Event.LogLevel LogLevel() { }
}
public abstract class EventBus<TEvent, TClassifier, TSubscriber>
Expand Down Expand Up @@ -3426,16 +3429,20 @@ namespace Akka.Event
{
public Info(string logSource, System.Type logClass, object message) { }
public Info(System.Exception cause, string logSource, System.Type logClass, object message) { }
public Info(System.Exception cause, string logSource, System.Type logClass, object message, ref System.Diagnostics.ActivityContext context) { }
public override Akka.Event.LogLevel LogLevel() { }
}
public class InitializeLogger : Akka.Actor.INoSerializationVerificationNeeded
{
public InitializeLogger(Akka.Event.LoggingBus loggingBus) { }
public Akka.Event.LoggingBus LoggingBus { get; }
}
[System.Runtime.CompilerServices.NullableAttribute(0)]
public abstract class LogEvent : Akka.Actor.INoSerializationVerificationNeeded
{
protected LogEvent() { }
public System.Diagnostics.ActivityContext ActivityContext { get; set; }
[System.Runtime.CompilerServices.NullableAttribute(2)]
public System.Exception Cause { get; set; }
public System.Type LogClass { get; set; }
public string LogSource { get; set; }
Expand Down Expand Up @@ -3713,6 +3720,7 @@ namespace Akka.Event
{
public Warning(string logSource, System.Type logClass, object message) { }
public Warning(System.Exception cause, string logSource, System.Type logClass, object message) { }
public Warning(System.Exception cause, string logSource, System.Type logClass, object message, ref System.Diagnostics.ActivityContext context) { }
public override Akka.Event.LogLevel LogLevel() { }
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[DEBUG][DateTime][Thread 0001][ActorSystem(test)][TraceId=00000000000000000000000000000000, SpanId=0000000000000000, TraceFlags=None] This is a test 1 cheese
[INFO][DateTime][Thread 0001][ActorSystem(test)][TraceId=00000000000000000000000000000000, SpanId=0000000000000000, TraceFlags=None] This is a test 1
[WARNING][DateTime][Thread 0001][ActorSystem(test)][TraceId=00000000000000000000000000000000, SpanId=0000000000000000, TraceFlags=None] This is a test 1
[ERROR][DateTime][Thread 0001][ActorSystem(test)][TraceId=00000000000000000000000000000000, SpanId=0000000000000000, TraceFlags=None] This is a test 1
1 change: 1 addition & 0 deletions src/core/Akka/Akka.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
<PackageReference Include="Polyfill" Version="1.28.0" PrivateAssets="all" />
<PackageReference Include="System.Reflection.Emit" Version="4.7.0" />
<PackageReference Include="System.Threading.Channels" Version="$(MicrosoftLibVersion)" />
<PackageReference Include="System.Diagnostics.DiagnosticSource" Version="$(MicrosoftLibVersion)" />
</ItemGroup>

<ItemGroup Label="PublicAnalyzers">
Expand Down
14 changes: 8 additions & 6 deletions src/core/Akka/Event/BusLogging.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
// Copyright (C) 2013-2025 .NET Foundation <https://github.com/akkadotnet/akka.net>
// </copyright>
//-----------------------------------------------------------------------

#nullable enable
using System;
using Akka.Actor;

Expand Down Expand Up @@ -72,14 +72,16 @@ public BusLogging(LoggingBus bus, string logSource, Type logClass, ILogMessageFo
/// </summary>
public override bool IsWarningEnabled { get; }

private LogEvent CreateLogEvent(LogLevel logLevel, object message, Exception cause = null)
private LogEvent CreateLogEvent(LogLevel logLevel, object message, Exception? cause = null)
{
var currentContext = (System.Diagnostics.Activity.Current?.Context ?? default);

return logLevel switch
{
LogLevel.DebugLevel => new Debug(cause, LogSource, LogClass, message),
LogLevel.InfoLevel => new Info(cause, LogSource, LogClass, message),
LogLevel.WarningLevel => new Warning(cause, LogSource, LogClass, message),
LogLevel.ErrorLevel => new Error(cause, LogSource, LogClass, message),
LogLevel.DebugLevel => new Debug(cause, LogSource, LogClass, message, currentContext),
LogLevel.InfoLevel => new Info(cause, LogSource, LogClass, message, currentContext),
LogLevel.WarningLevel => new Warning(cause, LogSource, LogClass, message, currentContext),
LogLevel.ErrorLevel => new Error(cause, LogSource, LogClass, message, currentContext),
_ => throw new ArgumentOutOfRangeException(nameof(logLevel), logLevel, null)
};
}
Expand Down
17 changes: 16 additions & 1 deletion src/core/Akka/Event/Debug.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
//-----------------------------------------------------------------------

using System;
using System.Diagnostics;

namespace Akka.Event
{
Expand All @@ -32,12 +33,26 @@ public Debug(string logSource, Type logClass, object message)
/// <param name="logSource">The source that generated the log event.</param>
/// <param name="logClass">The type of logger used to log the event.</param>
/// <param name="message">The message that is being logged.</param>
public Debug(Exception cause, string logSource, Type logClass, object message)
public Debug(Exception cause, string logSource, Type logClass, object message)
: this(cause, logSource, logClass, message, default)
{
}

/// <summary>
/// Initializes a new instance of the <see cref="Debug" /> class.
/// </summary>
/// <param name="cause">The exception that generated the log event.</param>
/// <param name="logSource">The source that generated the log event.</param>
/// <param name="logClass">The type of logger used to log the event.</param>
/// <param name="message">The message that is being logged.</param>
/// <param name="context">The current <see cref="Activity"/>'s context, if one is present.</param>>
public Debug(Exception cause, string logSource, Type logClass, object message, in ActivityContext context)
{
LogSource = logSource;
LogClass = logClass;
Message = message;
Cause = cause;
ActivityContext = context;
}

/// <summary>
Expand Down
15 changes: 15 additions & 0 deletions src/core/Akka/Event/Error.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
//-----------------------------------------------------------------------

using System;
using System.Diagnostics;

namespace Akka.Event
{
Expand All @@ -22,11 +23,25 @@ public class Error : LogEvent
/// <param name="logClass">The type of logger used to log the event.</param>
/// <param name="message">The message that is being logged.</param>
public Error(Exception cause, string logSource, Type logClass, object message)
: this(cause, logSource, logClass, message, default)
{
}

/// <summary>
/// Initializes a new instance of the <see cref="Error" /> class.
/// </summary>
/// <param name="cause">The exception that caused the log event.</param>
/// <param name="logSource">The source that generated the log event.</param>
/// <param name="logClass">The type of logger used to log the event.</param>
/// <param name="message">The message that is being logged.</param>
/// <param name="context">The current <see cref="Activity"/>'s context, if one is present.</param>
public Error(Exception cause, string logSource, Type logClass, object message, in ActivityContext context)
{
Cause = cause;
LogSource = logSource;
LogClass = logClass;
Message = message;
ActivityContext = context;
}

/// <summary>
Expand Down
18 changes: 17 additions & 1 deletion src/core/Akka/Event/Info.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
//-----------------------------------------------------------------------

using System;
using System.Diagnostics;

namespace Akka.Event
{
Expand All @@ -32,12 +33,27 @@ public Info(string logSource, Type logClass, object message)
/// <param name="logSource">The source that generated the log event.</param>
/// <param name="logClass">The type of logger used to log the event.</param>
/// <param name="message">The message that is being logged.</param>
public Info(Exception cause, string logSource, Type logClass, object message)
public Info(Exception cause, string logSource, Type logClass, object message)
: this(cause, logSource, logClass, message, default)
{

}

/// <summary>
/// Initializes a new instance of the <see cref="Info" /> class.
/// </summary>
/// <param name="cause">The exception that generated the log event.</param>
/// <param name="logSource">The source that generated the log event.</param>
/// <param name="logClass">The type of logger used to log the event.</param>
/// <param name="message">The message that is being logged.</param>
/// <param name="context">The current <see cref="Activity"/>'s context, if one is present.</param>
public Info(Exception cause, string logSource, Type logClass, object message, in ActivityContext context)
{
Cause = cause;
LogSource = logSource;
LogClass = logClass;
Message = message;
ActivityContext = context;
}

/// <summary>
Expand Down
Loading
Loading