Skip to content
Merged
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
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