Skip to content

Commit

Permalink
Adapt code to conform to v1.5.0 logging changes (#213)
Browse files Browse the repository at this point in the history
* Adapt code to conform to v1.5.0 logging changes

* upgraded to Akka.NET v1.5.0-beta5

---------

Co-authored-by: Aaron Stannard <[email protected]>
  • Loading branch information
Arkatufus and Aaronontheweb authored Mar 1, 2023
1 parent a4267e7 commit 183c35e
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 127 deletions.
8 changes: 8 additions & 0 deletions NuGet.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<!--To inherit the global NuGet package sources remove the <clear/> line below -->
<clear />
<add key="nuget" value="https://api.nuget.org/v3/index.json" />
</packageSources>
</configuration>
15 changes: 2 additions & 13 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,2 @@
#### 1.4.42 September 23 2022 ####
* Updated to [Akka.NET v1.4.42](https://github.com/akkadotnet/akka.net/releases/tag/1.4.42)
* [Bump Serilog from 2.10.0 to 2.12.0](https://github.com/akkadotnet/Akka.Logger.Serilog/pull/191)

#### 1.4.26 October 7 2021 ####
* Updated to [Akka.NET v1.4.26](https://github.com/akkadotnet/akka.net/releases/tag/1.4.26)

#### 1.4.25 September 9 2021 ####
* Updated to [Akka.NET v1.4.25](https://github.com/akkadotnet/akka.net/releases/tag/1.4.25)

#### 1.4.17 March 17 2021 ####
* Updated to [Akka.NET v1.4.17](https://github.com/akkadotnet/akka.net/releases/tag/1.4.17)
* Resolved a Akka.Remote LogSource race condition
#### 1.5.0-beta5 February 28 2023 ####
* Updated to [Akka.NET v1.5.0-beta5](https://github.com/akkadotnet/akka.net/releases/tag/1.5.0-beta5)
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public class SerilogLogMessageFormatter : ILogMessageFormatter
{
private readonly MessageTemplateCache _templateCache;

public static readonly SerilogLogMessageFormatter Instance = new SerilogLogMessageFormatter();
public static readonly SerilogLogMessageFormatter Instance = new();

/// <summary>
/// Initializes a new instance of the <see cref="SerilogLogMessageFormatter"/> class.
Expand Down Expand Up @@ -52,5 +52,18 @@ public string Format(string format, params object[] args)

return template.Render(properties);
}

/// <summary>
/// Converts the specified template string to a text string using the specified
/// token array to match replacements.
/// </summary>
/// <param name="format">The template string used in the conversion.</param>
/// <param name="args">The <see cref="IEnumerable{T}"/> that contains values to replace in the template.</param>
/// <returns>
/// A text string where the template placeholders have been replaced with
/// their corresponding values.
/// </returns>
public string Format(string format, IEnumerable<object> args)
=> Format(format, args.ToArray());
}
}
28 changes: 14 additions & 14 deletions src/Akka.Logger.Serilog/SerilogLogger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
//-----------------------------------------------------------------------

using System.Linq;
using System.Runtime.CompilerServices;
using Akka.Actor;
using Akka.Dispatch;
using Akka.Event;
Expand All @@ -25,6 +26,7 @@ public class SerilogLogger : ReceiveActor, IRequiresMessageQueue<ILoggerMessageQ
{
private readonly ILoggingAdapter _log = Logging.GetLogger(Context.System.EventStream, "SerilogLogger");

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static string GetFormat(object message)
{
return message is LogMessage logMessage ? logMessage.Format : "{Message:l}";
Expand All @@ -33,7 +35,7 @@ private static string GetFormat(object message)
private static object[] GetArgs(object message)
{
var logMessage = message as LogMessage;
return logMessage?.Args.Where(a => !(a is PropertyEnricher)).ToArray() ?? new[] { message };
return logMessage?.Parameters().Where(a => a is not PropertyEnricher).ToArray() ?? new[] { message };
}

private static ILogger GetLogger(LogEvent logEvent) {
Expand All @@ -42,46 +44,44 @@ private static ILogger GetLogger(LogEvent logEvent) {
.ForContext("ActorPath", Context.Sender.Path)
.ForContext("Timestamp", logEvent.Timestamp)
.ForContext("LogSource", logEvent.LogSource)
.ForContext("Thread", logEvent.Thread.ManagedThreadId.ToString().PadLeft( 4, '0' ));
.ForContext("Thread", logEvent.Thread.ManagedThreadId.ToString("0000"));

var logMessage = logEvent.Message as LogMessage;
if (logMessage != null)
if (logEvent.Message is SerilogPayload logMessage)
{
logger = logMessage.Args.OfType<PropertyEnricher>().Aggregate(logger, (current, enricher) => current.ForContext(enricher));
logger = logMessage.Enrichers.OfType<PropertyEnricher>().Aggregate(logger, (current, enricher) => current.ForContext(enricher));
}

return logger;
}

private static void Handle(Error logEvent) {

GetLogger(logEvent).Error(logEvent.Cause, GetFormat(logEvent.Message), GetArgs(logEvent.Message));
}

private static void Handle(Warning logEvent) {
GetLogger(logEvent).Warning(logEvent.Cause, GetFormat(logEvent.Message), GetArgs(logEvent.Message));
GetLogger(logEvent).Warning(logEvent.Cause, GetFormat(logEvent.Message), GetArgs(logEvent.Message));
}

private static void Handle(Info logEvent)
{
GetLogger(logEvent).Information(logEvent.Cause, GetFormat(logEvent.Message), GetArgs(logEvent.Message));
GetLogger(logEvent).Information(logEvent.Cause, GetFormat(logEvent.Message), GetArgs(logEvent.Message));
}

private static void Handle(Debug logEvent)
{
GetLogger(logEvent).Debug(logEvent.Cause, GetFormat(logEvent.Message), GetArgs(logEvent.Message));
GetLogger(logEvent).Debug(logEvent.Cause, GetFormat(logEvent.Message), GetArgs(logEvent.Message));
}

/// <summary>
/// Initializes a new instance of the <see cref="SerilogLogger"/> class.
/// </summary>
public SerilogLogger()
{
Receive<Error>(m => Handle(m));
Receive<Warning>(m => Handle(m));
Receive<Info>(m => Handle(m));
Receive<Debug>(m => Handle(m));
Receive<InitializeLogger>(m =>
Receive<Error>(Handle);
Receive<Warning>(Handle);
Receive<Info>(Handle);
Receive<Debug>(Handle);
Receive<InitializeLogger>(_ =>
{
_log.Info("SerilogLogger started");
Sender.Tell(new LoggerInitialized());
Expand Down
152 changes: 57 additions & 95 deletions src/Akka.Logger.Serilog/SerilogLoggingAdapter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,25 @@

namespace Akka.Logger.Serilog
{
public class SerilogLoggingAdapter : BusLogging
internal readonly struct SerilogPayload
{
public SerilogPayload(object message, IReadOnlyList<ILogEventEnricher> enrichers)
{
Message = message;
Enrichers = enrichers;
}

public IReadOnlyList<ILogEventEnricher> Enrichers { get; }

public object Message { get; }

public override string ToString()
{
return Message.ToString();
}
}

public class SerilogLoggingAdapter : LoggingAdapterBase
{
private readonly LoggingBus _bus;
private readonly Type _logClass;
Expand All @@ -29,98 +47,36 @@ public SerilogLoggingAdapter(LoggingBus bus, string logSource, Type logClass) :
{
}

private SerilogLoggingAdapter(LoggingBus bus, string logSource, Type logClass, ContextNode enricher) : base(bus, logSource, logClass, SerilogLogMessageFormatter.Instance)
private SerilogLoggingAdapter(LoggingBus bus, string logSource, Type logClass, ContextNode enricher) : base(SerilogLogMessageFormatter.Instance)
{
_bus = bus;
_logSource = logSource;
_logClass = logClass;
_enricherNode = enricher;

IsErrorEnabled = bus.LogLevel <= LogLevel.ErrorLevel;
IsWarningEnabled = bus.LogLevel <= LogLevel.WarningLevel;
IsInfoEnabled = bus.LogLevel <= LogLevel.InfoLevel;
IsDebugEnabled = bus.LogLevel <= LogLevel.DebugLevel;
}

private LogEvent CreateLogEvent(LogLevel logLevel, object message, Exception cause = null)
=> logLevel switch
{
LogLevel.DebugLevel => new Debug(cause, _logSource, _logClass, BuildMessage(message)),
LogLevel.InfoLevel => new Info(cause, _logSource, _logClass, BuildMessage(message)),
LogLevel.WarningLevel => new Warning(cause, _logSource, _logClass, BuildMessage(message)),
LogLevel.ErrorLevel => new Error(cause, _logSource, _logClass, BuildMessage(message)),
_ => throw new ArgumentOutOfRangeException(nameof(logLevel), logLevel, null)
};

/// <summary>
/// Logs a <see cref="F:Akka.Event.LogLevel.DebugLevel" /> message.
/// </summary>
/// <param name="format">The message that is being logged.</param>
/// <param name="args">An optional list of items used to format the message.</param>
public override void Debug(string format, params object[] args)
{
base.Debug(format, BuildArgs(args));
}

/// <summary>
/// Logs a <see cref="F:Akka.Event.LogLevel.InfoLevel" /> message.
/// </summary>
/// <param name="format">The message that is being logged.</param>
/// <param name="args">An optional list of items used to format the message.</param>
public override void Info(string format, params object[] args)
{
base.Info(format, BuildArgs(args));
}

public override void Info(Exception cause, string format, params object[] args)
{
base.Info(cause, format, BuildArgs(args));
}

public override void Debug(Exception cause, string format, params object[] args)
{
base.Debug(cause, format, BuildArgs(args));
}

/// <summary>
/// Obsolete. Use <see cref="M:Akka.Event.ILoggingAdapter.Warning(System.String,System.Object[])" /> instead!
/// </summary>
/// <param name="format">The message that is being logged.</param>
/// <param name="args">An optional list of items used to format the message.</param>
public override void Warn(string format, params object[] args)
{
base.Warning(format, BuildArgs(args));
}

public override void Warning(Exception cause, string format, params object[] args)
{
base.Warning(cause, format, BuildArgs(args));
}

/// <summary>
/// Logs a <see cref="F:Akka.Event.LogLevel.WarningLevel" /> message.
/// </summary>
/// <param name="format">The message that is being logged.</param>
/// <param name="args">An optional list of items used to format the message.</param>
public override void Warning(string format, params object[] args)
{
base.Warning(format, BuildArgs(args));
}

/// <summary>
/// Logs a <see cref="F:Akka.Event.LogLevel.ErrorLevel" /> message.
/// </summary>
/// <param name="format">The message that is being logged.</param>
/// <param name="args">An optional list of items used to format the message.</param>
public override void Error(string format, params object[] args)
{
base.Error(format, BuildArgs(args));
}

/// <summary>
/// Logs a <see cref="F:Akka.Event.LogLevel.ErrorLevel" /> message and associated exception.
/// </summary>
/// <param name="cause">The exception associated with this message.</param>
/// <param name="format">The message that is being logged.</param>
/// <param name="args">An optional list of items used to format the message.</param>
public override void Error(Exception cause, string format, params object[] args)
{
base.Error(cause, format, BuildArgs(args));
}
protected override void NotifyLog(LogLevel logLevel, object message, Exception cause = null)
=> _bus.Publish(CreateLogEvent(logLevel, message, cause));

/// <summary>Logs a message with a specified level.</summary>
/// <param name="logLevel">The level used to log the message.</param>
/// <param name="format">The message that is being logged.</param>
/// <param name="args">An optional list of items used to format the message.</param>
public override void Log(LogLevel logLevel, string format, params object[] args)
{
base.Log(logLevel, format, BuildArgs(args));
}
public override bool IsDebugEnabled { get; }
public override bool IsInfoEnabled { get; }
public override bool IsWarningEnabled { get; }
public override bool IsErrorEnabled { get; }

public ILoggingAdapter SetContextProperty(string name, object value, bool destructureObjects = false)
{
Expand All @@ -134,20 +90,26 @@ public ILoggingAdapter SetContextProperty(string name, object value, bool destru

return new SerilogLoggingAdapter(_bus, _logSource, _logClass, contextNode);
}

private object BuildMessage(object message)
{
return new SerilogPayload(message, BuildArgs());
}

private object[] BuildArgs(IEnumerable<object> args)
private IReadOnlyList<ILogEventEnricher> BuildArgs()
{
var newArgs = args.ToList();
if (_enricherNode != null)
if (_enricherNode == null)
return Array.Empty<ILogEventEnricher>();

var newArgs = new List<ILogEventEnricher>();
var currentNode = _enricherNode;
while (currentNode != null)
{
var currentNode = _enricherNode;
while (currentNode != null)
{
newArgs.Add(currentNode.Enricher);
currentNode = currentNode.Next;
}
newArgs.Add(currentNode.Enricher);
currentNode = currentNode.Next;
}
return newArgs.ToArray();

return newArgs;
}
}
}
2 changes: 1 addition & 1 deletion src/Akka.Logger.Serilog/SerilogLoggingAdapterExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public static class SerilogLoggingAdapterExtensions
/// <param name="destructureObjects">If true, the value will be serialized as a structured object if possible; if false, the object will be recorded as a scalar or simple array.</param>
public static ILoggingAdapter ForContext(this ILoggingAdapter adapter, string propertyName, object value, bool destructureObjects = false)
{
return !(adapter is SerilogLoggingAdapter customAdapter) ? adapter : customAdapter.SetContextProperty(propertyName, value, destructureObjects);
return adapter is not SerilogLoggingAdapter customAdapter ? adapter : customAdapter.SetContextProperty(propertyName, value, destructureObjects);
}

/// <summary>
Expand Down
7 changes: 4 additions & 3 deletions src/common.props
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,20 @@
<PackageTags>akka;actors;actor model;Akka;concurrency;serilog</PackageTags>
<Copyright>Copyright © 2013-2021 Akka.NET Team</Copyright>
<Authors>Akka.NET Team</Authors>
<PackageReleaseNotes>Updated Akka.Logger.Serilog to [Akka.NET v1.4.3](https://getakka.net/community/whats-new/akkadotnet-v1.4.html)</PackageReleaseNotes>
<VersionPrefix>1.4.3</VersionPrefix>
<PackageReleaseNotes>Updated to [Akka.NET v1.5.0-beta5](https://github.com/akkadotnet/akka.net/releases/tag/1.5.0-beta5)</PackageReleaseNotes>
<VersionPrefix>1.5.0</VersionPrefix>
<PackageIconUrl>http://getakka.net/images/akkalogo.png</PackageIconUrl>
<PackageProjectUrl>https://github.com/akkadotnet/Akka.Logger.Serilog</PackageProjectUrl>
<PackageLicenseUrl>https://github.com/akkadotnet/Akka.Logger.Serilog/blob/master/LICENSE</PackageLicenseUrl>
<NoWarn>$(NoWarn);CS1591</NoWarn>
<LangVersion>10</LangVersion>
</PropertyGroup>
<PropertyGroup>
<XunitVersion>2.4.2</XunitVersion>
<XunitRunnerVersion>2.4.5</XunitRunnerVersion>
<TestSdkVersion>17.4.1</TestSdkVersion>
<NBenchVersion>2.0.1</NBenchVersion>
<AkkaVersion>1.4.49</AkkaVersion>
<AkkaVersion>1.5.0-beta5</AkkaVersion>
<NetCoreTestVersion>netcoreapp3.1</NetCoreTestVersion>
<NetFrameworkTestVersion>net471</NetFrameworkTestVersion>
<NetStandardLibVersion>netstandard2.0</NetStandardLibVersion>
Expand Down

0 comments on commit 183c35e

Please sign in to comment.