Skip to content

Commit 80152d9

Browse files
implicitly convert regular BusLogger to SerilogLoggingAdapter when ForContext is called (#285)
* implicitly convert regular `BusLogger` to `SerilogLoggingAdapter` when `ForContext` is called close #284 * updated README
1 parent c51e306 commit 80152d9

File tree

5 files changed

+94
-34
lines changed

5 files changed

+94
-34
lines changed

Akka.Logger.Serilog.sln

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{489D8D37
1717
build.sh = build.sh
1818
src\Directory.Build.props = src\Directory.Build.props
1919
src\Directory.Packages.props = src\Directory.Packages.props
20+
NuGet.config = NuGet.config
2021
EndProjectSection
2122
EndProject
2223
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Examples", "Examples", "{28CDBE4C-053C-4CD4-B5D2-4DF529922916}"

README.md

Lines changed: 16 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,21 @@ log.Info(
5757

5858
This log entry will have "County" and "Country" properties added to it.
5959

60+
### Automatically Convert `ILoggingAdapter` into `SerilogLoggingAdapter`
61+
62+
As of Akka.Logger.Serilog v1.5.22, you can now do the following:
63+
64+
```csharp
65+
var log = Context.GetLogger()
66+
.ForContext("Address", "No. 4 Privet Drive")
67+
.ForContext("Town", "Little Whinging")
68+
.ForContext("County", "Surrey")
69+
.ForContext("Country", "England");
70+
log.Info("My boss makes me use {Semantic} logging", "semantic");
71+
```
72+
73+
And it will work without having to explicitly call `Context.GetLogger<SerilogLoggingAdapter>()` first.
74+
6075
## Building this solution
6176
To run the build script associated with this solution, execute the following:
6277

@@ -72,36 +87,4 @@ c:\> build.sh all
7287

7388
If you need any information on the supported commands, please execute the `build.[cmd|sh] help` command.
7489

75-
This build script is powered by [FAKE](https://fake.build/); please see their API documentation should you need to make any changes to the [`build.fsx`](build.fsx) file.
76-
77-
### Conventions
78-
The attached build script will automatically do the following based on the conventions of the project names added to this project:
79-
80-
* Any project name ending with `.Tests` will automatically be treated as a [XUnit2](https://xunit.github.io/) project and will be included during the test stages of this build script;
81-
* Any project name ending with `.Tests` will automatically be treated as a [NBench](https://github.com/petabridge/NBench) project and will be included during the test stages of this build script; and
82-
* Any project meeting neither of these conventions will be treated as a NuGet packaging target and its `.nupkg` file will automatically be placed in the `bin\nuget` folder upon running the `build.[cmd|sh] all` command.
83-
84-
### DocFx for Documentation
85-
This solution also supports [DocFx](http://dotnet.github.io/docfx/) for generating both API documentation and articles to describe the behavior, output, and usages of your project.
86-
87-
All of the relevant articles you wish to write should be added to the `/docs/articles/` folder and any API documentation you might need will also appear there.
88-
89-
All of the documentation will be statically generated and the output will be placed in the `/docs/_site/` folder.
90-
91-
#### Previewing Documentation
92-
To preview the documentation for this project, execute the following command at the root of this folder:
93-
94-
```
95-
C:\> serve-docs.cmd
96-
```
97-
98-
This will use the built-in `docfx.console` binary that is installed as part of the NuGet restore process from executing any of the usual `build.cmd` or `build.sh` steps to preview the fully-rendered documentation. For best results, do this immediately after calling `build.cmd buildRelease`.
99-
100-
### Release Notes, Version Numbers, Etc
101-
This project will automatically populate its release notes in all of its modules via the entries written inside [`RELEASE_NOTES.md`](RELEASE_NOTES.md) and will automatically update the versions of all assemblies and NuGet packages via the metadata included inside [`common.props`](src/common.props).
102-
103-
If you add any new projects to the solution created with this template, be sure to add the following line to each one of them in order to ensure that you can take advantage of `common.props` for standardization purposes:
104-
105-
```
106-
<Import Project="..\common.props" />
107-
```
90+
This build script is powered by [FAKE](https://fake.build/); please see their API documentation should you need to make any changes to the [`build.fsx`](build.fsx) file.

src/Akka.Logger.Serilog.Tests/ForContextSpecs.cs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@ public class ForContextSpecs : TestKit.Xunit2.TestKit
2222
public static readonly Config Config = @"akka.loglevel = DEBUG
2323
akka.loggers=[""Akka.Logger.Serilog.SerilogLogger, Akka.Logger.Serilog""]";
2424
private readonly ILoggingAdapter _loggingAdapter;
25+
26+
/// <summary>
27+
/// Used to test that https://github.com/akkadotnet/Akka.Logger.Serilog/issues/284 is fixed
28+
/// </summary>
29+
private readonly ILoggingAdapter _defaultLoggingAdapter;
2530
private readonly TestSink _sink = new TestSink();
2631

2732
public ForContextSpecs(ITestOutputHelper helper) : base(Config, output: helper)
@@ -35,6 +40,63 @@ public ForContextSpecs(ITestOutputHelper helper) : base(Config, output: helper)
3540
var logClass = typeof(ActorSystem);
3641

3742
_loggingAdapter = Sys.GetLogger<SerilogLoggingAdapter>(logSource, logClass);
43+
_defaultLoggingAdapter = Sys.Log;
44+
}
45+
46+
/// <summary>
47+
/// Used to test that https://github.com/akkadotnet/Akka.Logger.Serilog/issues/284 is fixed
48+
/// </summary>
49+
[Fact]
50+
public void ShouldLogMessageWithContextPropertyDefaultLogger()
51+
{
52+
var context = _defaultLoggingAdapter
53+
.ForContext("Address", "No. 4 Privet Drive")
54+
.ForContext("Town", "Little Whinging")
55+
.ForContext("County", "Surrey")
56+
.ForContext("Country", "England");
57+
58+
_sink.Clear();
59+
AwaitCondition(() => _sink.Writes.Count == 0);
60+
61+
context.Info("Hi {Person}", "Harry Potter");
62+
AwaitCondition(() => _sink.Writes.Count == 1);
63+
64+
_sink.Writes.TryDequeue(out var logEvent).Should().BeTrue();
65+
logEvent.Level.Should().Be(LogEventLevel.Information);
66+
logEvent.RenderMessage().Should().Contain("Hi \"Harry Potter\"");
67+
logEvent.Properties.Should().ContainKeys("Person", "Address", "Town", "County", "Country");
68+
logEvent.Properties["Person"].ToString().Should().Be("\"Harry Potter\"");
69+
logEvent.Properties["Address"].ToString().Should().Be("\"No. 4 Privet Drive\"");
70+
logEvent.Properties["Town"].ToString().Should().Be("\"Little Whinging\"");
71+
logEvent.Properties["County"].ToString().Should().Be("\"Surrey\"");
72+
logEvent.Properties["Country"].ToString().Should().Be("\"England\"");
73+
}
74+
75+
/// <summary>
76+
/// Used to test that https://github.com/akkadotnet/Akka.Logger.Serilog/issues/284 is fixed
77+
/// </summary>
78+
[Fact]
79+
public void ShouldLogMessageWithContextPropertyAndPropertyEnricherDefaultLogger()
80+
{
81+
var context = _defaultLoggingAdapter
82+
.ForContext("Address", "No. 4 Privet Drive")
83+
.ForContext("Town", "Little Whinging");
84+
85+
_sink.Clear();
86+
AwaitCondition(() => _sink.Writes.Count == 0);
87+
88+
context.Info("Hi {Person}", "Harry Potter", new PropertyEnricher("County", "Surrey"), new PropertyEnricher("Country", "England"));
89+
AwaitCondition(() => _sink.Writes.Count == 1);
90+
91+
_sink.Writes.TryDequeue(out var logEvent).Should().BeTrue();
92+
logEvent.Level.Should().Be(LogEventLevel.Information);
93+
logEvent.RenderMessage().Should().Contain("Hi \"Harry Potter\"");
94+
logEvent.Properties.Should().ContainKeys("Person", "Address", "Town", "County", "Country");
95+
logEvent.Properties["Person"].ToString().Should().Be("\"Harry Potter\"");
96+
logEvent.Properties["Address"].ToString().Should().Be("\"No. 4 Privet Drive\"");
97+
logEvent.Properties["Town"].ToString().Should().Be("\"Little Whinging\"");
98+
logEvent.Properties["County"].ToString().Should().Be("\"Surrey\"");
99+
logEvent.Properties["Country"].ToString().Should().Be("\"England\"");
38100
}
39101

40102
[Fact]

src/Akka.Logger.Serilog/SerilogLoggingAdapter.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ public override string ToString()
2525
}
2626
}
2727

28+
/// <summary>
29+
/// Serilog logging adapter.
30+
/// </summary>
2831
public class SerilogLoggingAdapter : LoggingAdapterBase
2932
{
3033
private readonly LoggingBus _bus;

src/Akka.Logger.Serilog/SerilogLoggingAdapterExtensions.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,18 @@ public static class SerilogLoggingAdapterExtensions
1515
/// <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>
1616
public static ILoggingAdapter ForContext(this ILoggingAdapter adapter, string propertyName, object value, bool destructureObjects = false)
1717
{
18-
return adapter is not SerilogLoggingAdapter customAdapter ? adapter : customAdapter.SetContextProperty(propertyName, value, destructureObjects);
18+
if(adapter is SerilogLoggingAdapter customAdapter)
19+
return customAdapter.SetContextProperty(propertyName, value, destructureObjects);
20+
21+
if (adapter is BusLogging defaultAkkaAdapter)
22+
{
23+
var enrichedAdapter = new SerilogLoggingAdapter(defaultAkkaAdapter.Bus, defaultAkkaAdapter.LogSource, defaultAkkaAdapter.LogClass);
24+
return enrichedAdapter.SetContextProperty(propertyName, value, destructureObjects);
25+
}
26+
27+
// log a warning if the adapter is not a SerilogLoggingAdapter or BusLogging
28+
adapter.Warning($"Cannot enrich log event with property {propertyName} because the adapter is not a {typeof(SerilogLoggingAdapter)} or {typeof(BusLogging)}.");
29+
return adapter;
1930
}
2031

2132
/// <summary>

0 commit comments

Comments
 (0)