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
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,8 @@ namespace Akka.Hosting
public Akka.Hosting.LoggerConfigBuilder AddLogger<T>()
where T : Akka.Dispatch.IRequiresMessageQueue<Akka.Event.ILoggerMessageQueueSemantics> { }
public Akka.Hosting.LoggerConfigBuilder ClearLoggers() { }
[System.Obsolete("SemanticLogMessageFormatter is now the default. Only use this method if you have " +
"a custom ILogMessageFormatter implementation.")]
public Akka.Hosting.LoggerConfigBuilder WithDefaultLogMessageFormatter<T>()
where T : Akka.Event.ILogMessageFormatter { }
public Akka.Hosting.LoggerConfigBuilder WithLogFilter(System.Action<Akka.Event.LogFilterBuilder> filterBuilder) { }
Expand Down Expand Up @@ -273,4 +275,4 @@ namespace Akka.Hosting.Logging
public LoggerFactorySetup(Microsoft.Extensions.Logging.ILoggerFactory loggerFactory) { }
public Microsoft.Extensions.Logging.ILoggerFactory LoggerFactory { get; }
}
}
}
40 changes: 40 additions & 0 deletions src/Akka.Hosting.Tests/Logging/LogMessageFormatterSpec.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,44 @@ await Awaiting(async () => await SetupHost<InvalidLogMessageFormatter>())
.Should().ThrowAsync<ConfigurationException>().WithMessage("*must have an empty constructor*");
}

[Fact(DisplayName = "SemanticLogMessageFormatter should be accepted (GitHub issue #703)")]
public async Task SemanticLogMessageFormatterShouldBeAcceptedTest()
{
// SemanticLogMessageFormatter has a private constructor - verify it doesn't throw
#pragma warning disable CS0618
using var host = await SetupHost<SemanticLogMessageFormatter>();
#pragma warning restore CS0618

try
{
var sys = host.Services.GetRequiredService<ActorSystem>();
sys.Settings.LogFormatter.Should().BeOfType<SemanticLogMessageFormatter>();
}
finally
{
await host.StopAsync();
}
}

[Fact(DisplayName = "DefaultLogMessageFormatter should be accepted")]
public async Task DefaultLogMessageFormatterShouldBeAcceptedTest()
{
// DefaultLogMessageFormatter has a private constructor - verify it doesn't throw
#pragma warning disable CS0618
using var host = await SetupHost<DefaultLogMessageFormatter>();
#pragma warning restore CS0618

try
{
var sys = host.Services.GetRequiredService<ActorSystem>();
sys.Settings.LogFormatter.Should().BeOfType<DefaultLogMessageFormatter>();
}
finally
{
await host.StopAsync();
}
}

private async Task<IHost> SetupHost<TFormatter>() where TFormatter : ILogMessageFormatter
{
var host = new HostBuilder()
Expand All @@ -79,7 +117,9 @@ private async Task<IHost> SetupHost<TFormatter>() where TFormatter : ILogMessage
{
setup.LogLevel = Event.LogLevel.DebugLevel;
setup.AddLoggerFactory();
#pragma warning disable CS0618
setup.WithDefaultLogMessageFormatter<TFormatter>();
#pragma warning restore CS0618
});
});
}).Build();
Expand Down
2 changes: 2 additions & 0 deletions src/Akka.Hosting.Tests/Logging/SerilogLoggerEnd2EndSpecs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,9 @@ protected override void ConfigureAkka(AkkaConfigurationBuilder builder, IService
setup.ClearLoggers();
setup.AddLogger<SerilogLogger>();
setup.LogLevel = Event.LogLevel.DebugLevel;
#pragma warning disable CS0618
setup.WithDefaultLogMessageFormatter<SerilogLogMessageFormatter>();
#pragma warning restore CS0618
});
}

Expand Down
21 changes: 16 additions & 5 deletions src/Akka.Hosting/LoggerConfigBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,15 @@ public Type LogMessageFormatter
if (!typeof(ILogMessageFormatter).IsAssignableFrom(value))
throw new ConfigurationException($"{nameof(LogMessageFormatter)} must implement {nameof(ILogMessageFormatter)}");

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

// Built-in formatters use private constructors with singleton Instance properties;
// Akka.NET's Settings.cs handles these as special cases at runtime.
if (value != typeof(SemanticLogMessageFormatter) && value != typeof(DefaultLogMessageFormatter))
{
var ctor = value.GetConstructor([]);
if (ctor is null)
throw new ConfigurationException($"{nameof(LogMessageFormatter)} Type must have an empty constructor");
}

_logMessageFormatter = value;
}
}
Expand All @@ -87,8 +92,14 @@ public LoggerConfigBuilder AddLogger<T>() where T: IRequiresMessageQueue<ILogger
}

/// <summary>
/// Sets the formatter used by the logger
/// Sets the formatter used by the logger.
/// </summary>
/// <remarks>
/// As of Akka.NET 1.5.58, <see cref="SemanticLogMessageFormatter"/> is the default formatter
/// and is configured automatically. This method is only needed if you have a custom
/// <see cref="ILogMessageFormatter"/> implementation.
/// </remarks>
[Obsolete("SemanticLogMessageFormatter is now the default. Only use this method if you have a custom ILogMessageFormatter implementation.")]
public LoggerConfigBuilder WithDefaultLogMessageFormatter<T>() where T: ILogMessageFormatter
{
#pragma warning disable CS0618 // Type or member is obsolete
Expand Down