| 
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