|
1 | 1 | # Serilog.Extensions.Logging [](https://ci.appveyor.com/project/serilog/serilog-framework-logging/history) [](https://www.nuget.org/packages/Serilog.Extensions.Logging/)
|
2 | 2 |
|
3 |
| - |
4 | 3 | A Serilog provider for [Microsoft.Extensions.Logging](https://www.nuget.org/packages/Microsoft.Extensions.Logging), the logging subsystem used by ASP.NET Core.
|
5 | 4 |
|
6 |
| -### ASP.NET Core 2.0+ Instructions |
| 5 | +### ASP.NET Core Instructions |
| 6 | + |
| 7 | +**ASP.NET Core** applications should prefer [Serilog.AspNetCore](https://github.com/serilog/serilog-aspnetcore) and `UseSerilog()` instead. |
7 | 8 |
|
8 |
| -**ASP.NET Core 2.0** applications should prefer [Serilog.AspNetCore](https://github.com/serilog/serilog-aspnetcore) and `UseSerilog()` instead. |
| 9 | +### Non-web .NET Core Instructions |
| 10 | + |
| 11 | +**Non-web .NET Core** applications should prefer [Serilog.Extensions.Hosting](https://github.com/serilog/serilog-extensions-hosting) and `UseSerilog()` instead. |
9 | 12 |
|
10 | 13 | ### .NET Core 1.0, 1.1 and Default Provider Integration
|
11 | 14 |
|
@@ -77,6 +80,69 @@ That's it! With the level bumped up a little you should see log output like:
|
77 | 80 | [22:14:45.741 DBG] Handled. Status code: 304 File: /css/site.css
|
78 | 81 | ```
|
79 | 82 |
|
| 83 | +### Notes on Log Scopes |
| 84 | + |
| 85 | +_Microsoft.Extensions.Logging_ provides the `BeginScope` API, which can be used to add arbitrary properties to log events within a certain region of code. The API comes in two forms: |
| 86 | + |
| 87 | +1. The method: `IDisposable BeginScope<TState>(TState state)` |
| 88 | +2. The extension method: `IDisposable BeginScope(this ILogger logger, string messageFormat, params object[] args)` |
| 89 | + |
| 90 | +Using the extension method will add a `Scope` property to your log events. This is most useful for adding simple "scope strings" to your events, as in the following code: |
| 91 | + |
| 92 | +```cs |
| 93 | +using (_logger.BeginScope("Transaction")) { |
| 94 | + _logger.LogInformation("Beginning..."); |
| 95 | + _logger.LogInformation("Completed in {DurationMs}ms...", 30); |
| 96 | +} |
| 97 | +// Example JSON output: |
| 98 | +// {"@t":"2020-10-29T19:05:56.4126822Z","@m":"Beginning...","@i":"f6a328e9","SourceContext":"SomeNamespace.SomeService","Scope":["Transaction"]} |
| 99 | +// {"@t":"2020-10-29T19:05:56.4176816Z","@m":"Completed in 30ms...","@i":"51812baa","DurationMs":30,"SourceContext":"SomeNamespace.SomeService","Scope":["Transaction"]} |
| 100 | +``` |
| 101 | + |
| 102 | +If you simply want to add a "bag" of additional properties to your log events, however, this extension method approach can be overly verbose. For example, to add `TransactionId` and `ResponseJson` properties to your log events, you would have to do something like the following: |
| 103 | + |
| 104 | +```cs |
| 105 | +// WRONG! Prefer the dictionary approach below instead |
| 106 | +using (_logger.BeginScope("TransactionId: {TransactionId}, ResponseJson: {ResponseJson}", 12345, jsonString)) { |
| 107 | + _logger.LogInformation("Completed in {DurationMs}ms...", 30); |
| 108 | +} |
| 109 | +// Example JSON output: |
| 110 | +// { |
| 111 | +// "@t":"2020-10-29T19:05:56.4176816Z", |
| 112 | +// "@m":"Completed in 30ms...", |
| 113 | +// "@i":"51812baa", |
| 114 | +// "DurationMs":30, |
| 115 | +// "SourceContext":"SomeNamespace.SomeService", |
| 116 | +// "TransactionId": 12345, |
| 117 | +// "ResponseJson": "{ \"Key1\": \"Value1\", \"Key2\": \"Value2\" }", |
| 118 | +// "Scope":["TransactionId: 12345, ResponseJson: { \"Key1\": \"Value1\", \"Key2\": \"Value2\" }"] |
| 119 | +// } |
| 120 | +``` |
| 121 | + |
| 122 | +Not only does this add the unnecessary `Scope` property to your event, but it also duplicates serialized values between `Scope` and the intended properties, as you can see here with `ResponseJson`. If this were "real" JSON like an API response, then a potentially very large block of text would be duplicated within your log event! Moreover, the template string within `BeginScope` is rather arbitrary when all you want to do is add a bag of properties, and you start mixing enriching concerns with formatting concerns. |
| 123 | + |
| 124 | +A far better alternative is to use the `BeginScope<TState>(TState state)` method. If you provide any `IEnumerable<KeyValuePair<string, object>>` to this method, then Serilog will output the key/value pairs as structured properties _without_ the `Scope` property, as in this example: |
| 125 | + |
| 126 | +```cs |
| 127 | +var scopeProps = new Dictionary<string, object> { |
| 128 | + { "TransactionId", 12345 }, |
| 129 | + { "ResponseJson", jsonString }, |
| 130 | +}; |
| 131 | +using (_logger.BeginScope(scopeProps) { |
| 132 | + _logger.LogInformation("Transaction completed in {DurationMs}ms...", 30); |
| 133 | +} |
| 134 | +// Example JSON output: |
| 135 | +// { |
| 136 | +// "@t":"2020-10-29T19:05:56.4176816Z", |
| 137 | +// "@m":"Completed in 30ms...", |
| 138 | +// "@i":"51812baa", |
| 139 | +// "DurationMs":30, |
| 140 | +// "SourceContext":"SomeNamespace.SomeService", |
| 141 | +// "TransactionId": 12345, |
| 142 | +// "ResponseJson": "{ \"Key1\": \"Value1\", \"Key2\": \"Value2\" }" |
| 143 | +// } |
| 144 | +``` |
| 145 | + |
80 | 146 | ### Credits
|
81 | 147 |
|
82 | 148 | This package evolved from an earlier package _Microsoft.Framework.Logging.Serilog_ [provided by the ASP.NET team](https://github.com/aspnet/Logging/pull/182).
|
0 commit comments