Skip to content

Commit

Permalink
Merge pull request #234 from serilog/hosting-bootstrap-logger
Browse files Browse the repository at this point in the history
Update to include CreateBootstrapLogger()
  • Loading branch information
nblumhardt committed Feb 17, 2021
2 parents 2857be8 + 2f449dd commit 29378ba
Show file tree
Hide file tree
Showing 121 changed files with 1,475 additions and 40,578 deletions.
85 changes: 49 additions & 36 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ public class Program
public static int Main(string[] args)
{
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.MinimumLevel.Override("Microsoft", LogEventLevel.Information)
.Enrich.FromLogContext()
.WriteTo.Console()
Expand Down Expand Up @@ -61,7 +60,7 @@ public class Program

**Finally**, clean up by removing the remaining configuration for the default logger:

* Remove the `"Logging"` section from _appsettings.json_ files (this can be replaced with [Serilog configuration](https://github.com/serilog/serilog-settings-configuration) as shown in [the _EarlyInitializationSample_ project](https://github.com/serilog/serilog-aspnetcore/blob/dev/samples/EarlyInitializationSample/Program.cs), if required)
* Remove the `"Logging"` section from _appsettings.*.json_ files (this can be replaced with [Serilog configuration](https://github.com/serilog/serilog-settings-configuration) as shown in [the _Sample_ project](https://github.com/serilog/serilog-aspnetcore/blob/dev/samples/Sample/Program.cs), if required)
* Remove `UseApplicationInsights()` (this can be replaced with the [Serilog AI sink](https://github.com/serilog/serilog-sinks-applicationinsights), if required)

That's it! With the level bumped up a little you will see log output resembling:
Expand All @@ -81,7 +80,7 @@ That's it! With the level bumped up a little you will see log output resembling:

**Tip:** to see Serilog output in the Visual Studio output window when running under IIS, either select _ASP.NET Core Web Server_ from the _Show output from_ drop-down list, or replace `WriteTo.Console()` in the logger configuration with `WriteTo.Debug()`.

A more complete example, showing `appsettings.json` configuration, can be found in [the sample project here](https://github.com/serilog/serilog-aspnetcore/tree/dev/samples/EarlyInitializationSample).
A more complete example, including `appsettings.json` configuration, can be found in [the sample project here](https://github.com/serilog/serilog-aspnetcore/tree/dev/samples/Sample).

### Request logging

Expand Down Expand Up @@ -188,59 +187,73 @@ app.UseSerilogRequestLogging(options =>
});
```

### Inline initialization
### Two-stage initialization

You can alternatively configure Serilog inline, in `BuildWebHost()`, using a delegate as shown below:
The example at the top of this page shows how to configure Serilog immediately when the application starts. This has the benefit of catching and reporting exceptions thrown during set-up of the ASP.NET Core host.

```csharp
.UseSerilog((hostingContext, services, loggerConfiguration) => loggerConfiguration
.ReadFrom.Configuration(hostingContext.Configuration)
.Enrich.FromLogContext()
.WriteTo.Console())
```
The downside of initializing Serilog first is that services from the ASP.NET Core host, including the `appsettings.json` configuration and dependency injection, aren't available yet.

This has the advantage of making a service provider and the `hostingContext`'s `Configuration` object available for [configuration of the logger](https://github.com/serilog/serilog-settings-configuration), but at the expense of losing `Exception`s raised earlier in program startup.
To address this, Serilog supports two-stage initialization. An initial "bootstrap" logger is configured immediately when the program starts, and this is replaced by the fully-configured logger once the host has loaded.

If this method is used, `Log.Logger` is assigned implicitly, and closed when the app is shut down.
To use this technique, first replace the initial `CreateLogger()` call with `CreateBoostrapLogger()`:

A complete example, showing this approach, can be found in [the _InlineIntializationSample_ project](https://github.com/serilog/serilog-aspnetcore/tree/dev/samples/InlineInitializationSample).
```csharp
using Serilog;

### Enabling `Microsoft.Extensions.Logging.ILoggerProvider`s
public class Program
{
public static int Main(string[] args)
{
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Override("Microsoft", LogEventLevel.Information)
.Enrich.FromLogContext()
.WriteTo.Console()
.CreateBootstrapLogger(); <-- this line!
```

Serilog sends events to outputs called _sinks_, that implement Serilog's `ILogEventSink` interface, and are added to the logging pipeline using `WriteTo`. _Microsoft.Extensions.Logging_ has a similar concept called _providers_, and these implement `ILoggerProvider`. Providers are what the default logging configuration creates under the hood through methods like `AddConsole()`.
Then, pass a callback to `UseSerilog()` that creates the final logger:

By default, Serilog ignores providers, since there are usually equivalent Serilog sinks available, and these work more efficiently with Serilog's pipeline. If provider support is needed, it can be optionally enabled.
```csharp
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseSerilog((context, services, configuration) => configuration
.ReadFrom.Configuration(context.Configuration)
.ReadFrom.Services(services)
.Enrich.FromLogContext()
.WriteTo.Console())
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
```

**Using the recommended configuration:**
It's important to note that the final logger **completely replaces** the bootstrap logger: if you want both to log to the console, for instance, you'll need to specify `WriteTo.Console()` in both places, as the example shows.

In the recommended configuration (in which startup exceptions are caught and logged), first create a `LoggerProviderCollection` in a static field in _Program.cs_:
#### Consuming `appsettings.json` configuration

```csharp
// using Serilog.Extensions.Logging;
static readonly LoggerProviderCollection Providers = new LoggerProviderCollection();
```
**Using two-stage initialization**, insert the `ReadFrom.Configuration(context.Configuration)` call shown in the example above. The JSON configuration syntax is documented in [the _Serilog.Settings.Configuration_ README](https://github.com/serilog/serilog-settings-configuration).
Next, add `WriteTo.Providers()` to the logger configuration:
#### Injecting services into enrichers and sinks

```csharp
.WriteTo.Providers(Providers)
```
**Using two-stage initialization**, insert the `ReadFrom.Services(services)` call shown in the example above. The `ReadFrom.Services()` call will configure the logging pipeline with any registered implementations of the following services:

Finally, pass the provider collection into `UseSerilog()`:
* `IDestructuringPolicy`
* `ILogEventEnricher`
* `ILogEventFilter`
* `ILogEventSink`
* `LoggingLevelSwitch`

```csharp
.UseSerilog(providers: Providers)
```
#### Enabling `Microsoft.Extensions.Logging.ILoggerProvider`s

Providers registered in _Startup.cs_ with `AddLogging()` will then receive events from Serilog.
Serilog sends events to outputs called _sinks_, that implement Serilog's `ILogEventSink` interface, and are added to the logging pipeline using `WriteTo`. _Microsoft.Extensions.Logging_ has a similar concept called _providers_, and these implement `ILoggerProvider`. Providers are what the default logging configuration creates under the hood through methods like `AddConsole()`.

**Using inline initialization:**
By default, Serilog ignores providers, since there are usually equivalent Serilog sinks available, and these work more efficiently with Serilog's pipeline. If provider support is needed, it can be optionally enabled.

If [inline initialization](#inline-initialization) is used, providers can be enabled by adding `writeToProviders: true` to the `UseSerilog()` method call:
To have Serilog pass events to providers, **using two-stage initialization** as above, pass `writeToProviders: true` in the call to `UseSerilog()`:

```csharp
.UseSerilog(
(hostingContext, loggerConfiguration) => /* snip! */,
(hostingContext, services, loggerConfiguration) => /* snip! */,
writeToProviders: true)
```

Expand Down Expand Up @@ -278,7 +291,7 @@ The Azure Diagnostic Log Stream ships events from any files in the `D:\home\LogF

### Pushing properties to the `ILogger<T>`

If you want to add extra properties to all logevents in a specific part of your code, you can add them to the **`ILogger<T>`** in **Microsoft.Extensions.Logging** with the following code. For this code to work, make sure you have added the `.Enrich.FromLogContext()` to the `.UseSerilog(...)` statement, as specified in the samples above.
If you want to add extra properties to all log events in a specific part of your code, you can add them to the **`ILogger<T>`** in **Microsoft.Extensions.Logging** with the following code. For this code to work, make sure you have added the `.Enrich.FromLogContext()` to the `.UseSerilog(...)` statement, as specified in the samples above.

```csharp
// Microsoft.Extensions.Logging ILogger<T>
Expand Down
Binary file added assets/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion global.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"sdk": {
"allowPrerelease": false,
"version": "3.1.201",
"version": "5.0.102",
"rollForward": "latestFeature"
}
}
11 changes: 0 additions & 11 deletions samples/EarlyInitializationSample/EarlyInitializationSample.csproj

This file was deleted.

56 changes: 0 additions & 56 deletions samples/EarlyInitializationSample/Program.cs

This file was deleted.

45 changes: 0 additions & 45 deletions samples/EarlyInitializationSample/Startup.cs

This file was deleted.

6 changes: 0 additions & 6 deletions samples/EarlyInitializationSample/Views/Home/Privacy.cshtml

This file was deleted.

25 changes: 0 additions & 25 deletions samples/EarlyInitializationSample/Views/Shared/Error.cshtml

This file was deleted.

This file was deleted.

Loading

0 comments on commit 29378ba

Please sign in to comment.