-
Notifications
You must be signed in to change notification settings - Fork 207
/
SerilogWebHostBuilderExtensions.cs
159 lines (138 loc) · 6.89 KB
/
SerilogWebHostBuilderExtensions.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
// Copyright 2017-2019 Serilog Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using System;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Logging;
using Serilog.Extensions.Logging;
using Microsoft.Extensions.DependencyInjection;
using Serilog.Extensions.Hosting;
namespace Serilog
{
/// <summary>
/// Extends <see cref="IWebHostBuilder"/> with Serilog configuration methods.
/// </summary>
public static class SerilogWebHostBuilderExtensions
{
/// <summary>
/// Sets Serilog as the logging provider.
/// </summary>
/// <param name="builder">The web host builder to configure.</param>
/// <param name="logger">The Serilog logger; if not supplied, the static <see cref="Serilog.Log"/> will be used.</param>
/// <param name="dispose">When true, dispose <paramref name="logger"/> when the framework disposes the provider. If the
/// logger is not specified but <paramref name="dispose"/> is true, the <see cref="Log.CloseAndFlush()"/> method will be
/// called on the static <see cref="Log"/> class instead.</param>
/// <param name="providers">A <see cref="LoggerProviderCollection"/> registered in the Serilog pipeline using the
/// <c>WriteTo.Providers()</c> configuration method, enabling other <see cref="ILoggerProvider"/>s to receive events. By
/// default, only Serilog sinks will receive events.</param>
/// <returns>The web host builder.</returns>
public static IWebHostBuilder UseSerilog(
this IWebHostBuilder builder,
ILogger logger = null,
bool dispose = false,
LoggerProviderCollection providers = null)
{
if (builder == null) throw new ArgumentNullException(nameof(builder));
builder.ConfigureServices(collection =>
{
if (providers != null)
{
collection.AddSingleton<ILoggerFactory>(services =>
{
var factory = new SerilogLoggerFactory(logger, dispose, providers);
foreach (var provider in services.GetServices<ILoggerProvider>())
factory.AddProvider(provider);
return factory;
});
}
else
{
collection.AddSingleton<ILoggerFactory>(services => new SerilogLoggerFactory(logger, dispose));
}
ConfigureServices(collection, logger);
});
return builder;
}
/// <summary>Sets Serilog as the logging provider.</summary>
/// <remarks>
/// A <see cref="WebHostBuilderContext"/> is supplied so that configuration and hosting information can be used.
/// The logger will be shut down when application services are disposed.
/// </remarks>
/// <param name="builder">The web host builder to configure.</param>
/// <param name="configureLogger">The delegate for configuring the <see cref="LoggerConfiguration" /> that will be used to construct a <see cref="Logger" />.</param>
/// <param name="preserveStaticLogger">Indicates whether to preserve the value of <see cref="Log.Logger"/>.</param>
/// <param name="writeToProviders">By default, Serilog does not write events to <see cref="ILoggerProvider"/>s registered through
/// the Microsoft.Extensions.Logging API. Normally, equivalent Serilog sinks are used in place of providers. Specify
/// <c>true</c> to write events to all providers.</param>
/// <returns>The web host builder.</returns>
public static IWebHostBuilder UseSerilog(
this IWebHostBuilder builder,
Action<WebHostBuilderContext, LoggerConfiguration> configureLogger,
bool preserveStaticLogger = false,
bool writeToProviders = false)
{
if (builder == null) throw new ArgumentNullException(nameof(builder));
if (configureLogger == null) throw new ArgumentNullException(nameof(configureLogger));
builder.ConfigureServices((context, collection) =>
{
var loggerConfiguration = new LoggerConfiguration();
LoggerProviderCollection loggerProviders = null;
if (writeToProviders)
{
loggerProviders = new LoggerProviderCollection();
loggerConfiguration.WriteTo.Providers(loggerProviders);
}
configureLogger(context, loggerConfiguration);
var logger = loggerConfiguration.CreateLogger();
ILogger registeredLogger = null;
if (preserveStaticLogger)
{
registeredLogger = logger;
}
else
{
// Passing a `null` logger to `SerilogLoggerFactory` results in disposal via
// `Log.CloseAndFlush()`, which additionally replaces the static logger with a no-op.
Log.Logger = logger;
}
collection.AddSingleton<ILoggerFactory>(services =>
{
var factory = new SerilogLoggerFactory(registeredLogger, true, loggerProviders);
if (writeToProviders)
{
foreach (var provider in services.GetServices<ILoggerProvider>())
factory.AddProvider(provider);
}
return factory;
});
ConfigureServices(collection, logger);
});
return builder;
}
static void ConfigureServices(IServiceCollection collection, ILogger logger)
{
if (collection == null) throw new ArgumentNullException(nameof(collection));
if (logger != null)
{
// This won't (and shouldn't) take ownership of the logger.
collection.AddSingleton(logger);
}
// Registered to provide two services...
var diagnosticContext = new DiagnosticContext(logger);
// Consumed by e.g. middleware
collection.AddSingleton(diagnosticContext);
// Consumed by user code
collection.AddSingleton<IDiagnosticContext>(diagnosticContext);
}
}
}