Skip to content

Commit

Permalink
Add logging LogMessageFormatter support (#248)
Browse files Browse the repository at this point in the history
* Add logging LogMessageFormatter support

* Update API Verify list
  • Loading branch information
Arkatufus authored Mar 1, 2023
1 parent a78d024 commit c7d6074
Show file tree
Hide file tree
Showing 3 changed files with 139 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ namespace Akka.Hosting
public Akka.Hosting.DebugOptions? DebugOptions { get; set; }
public bool LogConfigOnStart { get; set; }
public Akka.Event.LogLevel LogLevel { get; set; }
public System.Type LogMessageFormatter { get; set; }
public Akka.Hosting.LoggerConfigBuilder AddLogger<T>()
where T : Akka.Dispatch.IRequiresMessageQueue<Akka.Event.ILoggerMessageQueueSemantics> { }
public Akka.Hosting.LoggerConfigBuilder ClearLoggers() { }
Expand Down
117 changes: 117 additions & 0 deletions src/Akka.Hosting.Tests/Logging/LogMessageFormatterSpec.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
// -----------------------------------------------------------------------
// <copyright file="LogMessageFormatterSpec.cs" company="Akka.NET Project">
// Copyright (C) 2009-2023 Lightbend Inc. <http://www.lightbend.com>
// Copyright (C) 2013-2023 .NET Foundation <https://github.com/akkadotnet/akka.net>
// </copyright>
// -----------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Akka.Actor;
using Akka.Configuration;
using Akka.Event;
using FluentAssertions;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Xunit;
using Xunit.Abstractions;
using LogLevel = Microsoft.Extensions.Logging.LogLevel;
using static FluentAssertions.FluentActions;

namespace Akka.Hosting.Tests.Logging;

public class LogMessageFormatterSpec
{
private ITestOutputHelper _helper;

public LogMessageFormatterSpec(ITestOutputHelper helper)
{
_helper = helper;
}

[Fact(DisplayName = "ILogMessageFormatter should transform log messages")]
public async Task TransformMessagesTest()
{
using var host = await SetupHost(typeof(TestLogMessageFormatter));

try
{
var sys = host.Services.GetRequiredService<ActorSystem>();
var testKit = new TestKit.Xunit2.TestKit(sys);

var probe = testKit.CreateTestProbe();
sys.EventStream.Subscribe(probe, typeof(Error));
sys.Log.Error("This is a test {0}", 1);

var msg = probe.ExpectMsg<Error>();
msg.Message.Should().BeAssignableTo<LogMessage>();
msg.ToString().Should().Contain("++TestLogMessageFormatter++");
}
finally
{
await host.StopAsync();
}
}

[Fact(DisplayName = "Invalid LogMessageFormatter property should throw")]
public async Task InvalidLogMessageFormatterThrowsTest()
{
await Awaiting(async () => await SetupHost(typeof(InvalidLogMessageFormatter)))
.Should().ThrowAsync<ConfigurationException>().WithMessage("*must have an empty constructor*");
}

private async Task<IHost> SetupHost(Type formatter)
{
var host = new HostBuilder()
.ConfigureLogging(builder =>
{
builder.AddProvider(new XUnitLoggerProvider(_helper, LogLevel.Information));
})
.ConfigureServices(collection =>
{
collection.AddAkka("TestSys", configurationBuilder =>
{
configurationBuilder
.ConfigureLoggers(setup =>
{
setup.LogLevel = Event.LogLevel.DebugLevel;
setup.AddLoggerFactory();
setup.LogMessageFormatter = formatter;
});
});
}).Build();
await host.StartAsync();
return host;
}
}

public class TestLogMessageFormatter : ILogMessageFormatter
{
public string Format(string format, params object[] args)
{
return string.Format($"++TestLogMessageFormatter++{format}", args);
}

public string Format(string format, IEnumerable<object> args)
=> Format(format, args.ToArray());
}

public class InvalidLogMessageFormatter : ILogMessageFormatter
{
public InvalidLogMessageFormatter(string doesNotMatter)
{
}

public string Format(string format, params object[] args)
{
throw new NotImplementedException();
}

public string Format(string format, IEnumerable<object> args)
{
throw new NotImplementedException();
}
}
22 changes: 21 additions & 1 deletion src/Akka.Hosting/LoggerConfigBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using Akka.Configuration;
using Akka.Dispatch;
Expand All @@ -17,6 +18,7 @@ namespace Akka.Hosting
public sealed class LoggerConfigBuilder
{
private readonly List<Type> _loggers = new List<Type> { typeof(DefaultLogger) };
private Type _logMessageFormatter = typeof(DefaultLogMessageFormatter);
internal AkkaConfigurationBuilder Builder { get; }

internal LoggerConfigBuilder(AkkaConfigurationBuilder builder)
Expand Down Expand Up @@ -45,6 +47,22 @@ internal LoggerConfigBuilder(AkkaConfigurationBuilder builder)

public DebugOptions? DebugOptions { get; set; }

public Type LogMessageFormatter
{
get => _logMessageFormatter;
set
{
if (!typeof(ILogMessageFormatter).IsAssignableFrom(value))
throw new ConfigurationException($"{nameof(LogMessageFormatter)} must implement {nameof(ILogMessageFormatter)}");

var ctor = value.GetConstructor(new Type[]{});
if (ctor is null)
throw new ConfigurationException($"{nameof(LogMessageFormatter)} Type must have an empty constructor");

_logMessageFormatter = value;
}
}

/// <summary>
/// Clear all loggers currently registered.
/// </summary>
Expand Down Expand Up @@ -83,7 +101,9 @@ internal Config ToConfig()
var sb = new StringBuilder()
.Append("akka.loglevel=").AppendLine(ParseLogLevel(LogLevel))
.Append("akka.loggers=[").Append(string.Join(",", _loggers.Select(t => $"\"{t.AssemblyQualifiedName}\""))).AppendLine("]")
.Append("akka.log-config-on-start=").AppendLine(LogConfigOnStart ? "true" : "false");
.Append("akka.log-config-on-start=").AppendLine(LogConfigOnStart ? "true" : "false")
.Append("akka.logger-formatter=").AppendLine(_logMessageFormatter.AssemblyQualifiedName.ToHocon());

if (DebugOptions is { })
sb.AppendLine(DebugOptions.ToString());
if (DeadLetterOptions is { })
Expand Down

0 comments on commit c7d6074

Please sign in to comment.