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
14 changes: 14 additions & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
#### 1.5.57-beta2 December 3rd 2025 ####

* [Update Akka.NET to 1.5.57-beta2](https://github.com/akkadotnet/akka.net/releases/tag/1.5.57-beta2)
* [Add semantic logging support for Akka.NET 1.5.56+](https://github.com/akkadotnet/Akka.Logger.Serilog/pull/294)

This release adds full semantic logging support, enabling Serilog to receive properly structured message templates and parameters instead of pre-formatted strings. This enhancement leverages Akka.NET's semantic logging APIs introduced in version 1.5.56, enabling richer structured logging capabilities.

**New Features:**
- **Semantic Logging**: Serilog now receives message templates with named and positional parameters for true structured logging
- **Enhanced Template Support**: Full support for Serilog destructuring (`@`), stringification (`$`), and format specifiers (e.g., `:N2`)
- **ForContext Integration**: Semantic logging works seamlessly with `ForContext()` for enriched log contexts
- **Akka Metadata Preservation**: All Akka.NET metadata (timestamp, log level, thread, logger name) is preserved in structured logs
- **Backwards Compatible**: Fully compatible with older Akka.NET versions through `LogMessage` type checking

#### 1.5.25 June 17 2024 ####

* [Update Akka.Hosting to 1.5.25](https://github.com/akkadotnet/akka.net/releases/tag/1.5.25)
Expand Down
43 changes: 32 additions & 11 deletions src/Akka.Logger.Serilog.Tests/SerilogFormattingSpecs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
using Serilog;
using Xunit;
using Xunit.Abstractions;
using LogEvent = Serilog.Events.LogEvent;
using SerilogLog = Serilog.Log;

namespace Akka.Logger.Serilog.Tests
Expand Down Expand Up @@ -53,10 +54,11 @@ public async Task RawLogOutputRegressionTest(string version, string expected, st
await AwaitConditionAsync(() => _sink.Writes.Count == 0);

_serilogLogger.Information(messageFormat, args);
await AwaitConditionAsync(() => _sink.Writes.Count == 1);

_sink.Writes.TryDequeue(out var logEvent).Should().BeTrue();
logEvent!.RenderMessage().Should().Be(expected);
await AwaitConditionAsync(() => AssertCondition(logEvent =>
{
logEvent.RenderMessage().Should().Be(expected);
}));
}

[Theory(DisplayName = "SerilogLoggingAdapter output must be compatible with previous version")]
Expand All @@ -67,10 +69,11 @@ public async Task AdapterLogOutputRegressionTest(string version, string expected
await AwaitConditionAsync(() => _sink.Writes.Count == 0);

_loggingAdapter.Info(messageFormat, args);
await AwaitConditionAsync(() => _sink.Writes.Count == 1);

_sink.Writes.TryDequeue(out var logEvent).Should().BeTrue();
logEvent!.RenderMessage().Should().Contain(expected);
await AwaitConditionAsync(() => AssertCondition(logEvent =>
{
logEvent.RenderMessage().Should().Contain(expected);
}));
}

[Theory(DisplayName = "Default ILoggingAdapter output must be compatible with previous version")]
Expand All @@ -81,10 +84,28 @@ public async Task LogOutputRegressionTest(string version, string expected, strin
await AwaitConditionAsync(() => _sink.Writes.Count == 0);

Sys.Log.Info(messageFormat, args);
await AwaitConditionAsync(() => _sink.Writes.Count == 1);

_sink.Writes.TryDequeue(out var logEvent).Should().BeTrue();
logEvent!.RenderMessage().Should().Contain(expected);
await AwaitConditionAsync(() => AssertCondition(logEvent =>
{
logEvent.RenderMessage().Should().Contain(expected);
}));
}

private bool AssertCondition(Action<LogEvent> assertion)
{
while (_sink.Writes.TryDequeue(out var logEvent))
{
try
{
assertion(logEvent);
return true;
}
catch
{
// no-op
}
}
return false;
}

[Theory]
Expand All @@ -93,13 +114,13 @@ public async Task LogOutputRegressionTest(string version, string expected, strin
[InlineData(LogLevel.DebugLevel, "test case {myNum} {myStr}", new object[] { 1, "foo" })]
public void ShouldHandleSerilogFormats(LogLevel level, string formatStr, object[] args)
{
Sys.EventStream.Subscribe(TestActor, typeof(LogEvent));
Sys.EventStream.Subscribe(TestActor, typeof(Akka.Event.LogEvent));

Action logWrite = () =>
{
_loggingAdapter.Log(level, formatStr, args);

var logEvent = ExpectMsg<LogEvent>();
var logEvent = ExpectMsg<Akka.Event.LogEvent>();
logEvent.LogLevel().Should().Be(level);
logEvent.ToString().Should().NotBeEmpty();
};
Expand Down