I wrote an extension method over IHostBuilder
named ConfigureLog
to configure Serilog
. Serilog must be log on Kibana
and this config is in appsettings.json
file
public static IHostBuilder ConfigureLog(this IHostBuilder builder)
{
builder.UseSerilog((hostContext, loggerConfiguration) =>
{
var options = hostContext.Configuration.GetSection("LoggingConfiguration")
.Get<LoggingConfigurationOption>();
loggerConfiguration = options.GetLoggerConfiguration();
loggerConfiguration.CreateLogger();
});
builder.ConfigureServices((hostContext, services) =>
{
services.AddLogging(b =>
{
b.AddSerilog();
});
});
return builder;
}
My LoggingConfigurationOption
class is:
internal class LoggingConfigurationOption
{
public string ElkUrl { get; set; }
public string ElkUsername { get; set; }
public string ElkPassword { get; set; }
public string ServiceName { get; set; }
public LogEventLevel? ConsoleLogLevel { get; set; }
internal LoggerConfiguration GetLoggerConfiguration()
{
return new LoggerConfiguration()
.MinimumLevel.Verbose()
.MinimumLevel.Override("System", LogEventLevel.Fatal)
.MinimumLevel.Override("Microsoft", LogEventLevel.Fatal)
.Enrich.FromLogContext()
.WriteTo.Console(ConsoleLogLevel??LogEventLevel.Warning)
.WriteTo.Elasticsearch(
new ElasticsearchSinkOptions(new Uri(ElkUrl)) {
ModifyConnectionSettings = c=>c.BasicAuthentication(ElkUsername,ElkPassword),
AutoRegisterTemplateVersion = AutoRegisterTemplateVersion.ESv8,
DetectElasticsearchVersion = true,
BatchPostingLimit = 1,
CustomFormatter = new ExceptionAsObjectJsonFormatter(renderMessage: true),
AutoRegisterTemplate = true,
MinimumLogEventLevel = LogEventLevel.Information,
IndexDecider = IndexDeciderFunc,
FailureCallback = e => System.Console.WriteLine("Unable to submit event " + e.MessageTemplate),
});
}
private string IndexDeciderFunc(LogEvent logEvent, DateTimeOffset offset)
{
var now = DateTimeOffset.UtcNow;
var year = now.Year;
var month = now.Month;
var day = now.Day;
if (logEvent.MessageTemplate.Text.Equals(HttpRequestTemplate) ||
logEvent.MessageTemplate.Text.Equals(HttpResponseTemplate))
return $"http-logs-{year}-{month}-{day}";
return $"{ServiceName}-logs-{year}-{month}-{day}";
}
}
This class LoggingConfigurationOption
get ELK
configuration correctly from appsettings.json
file but when I using logger on code, it doesn't work
You seem to have a fundamental misunderstanding of how UseSerilog
works and is supposed to be used. loggerConfiguration
isn't passed by reference. This:
loggerConfiguration = options.GetLoggerConfiguration();
only modifies the local variable, so this does effectively nothing. You also don't need to call CreateLogger()
here.
Instead, you're meant to modify the logger configuration you're given, not create a new one. Serilog will then create a logger from that configuration.
So, your GetLoggerConfiguration()
should be rewritten to be something like:
internal void ConfigureLogger(LoggerConfiguration configuration)
{
// modify the configuation
configuration
.MinimumLevel.Verbose()
.MinimumLevel.Override("System", LogEventLevel.Fatal)
.MinimumLevel.Override("Microsoft", LogEventLevel.Fatal)
.Enrich.FromLogContext()
.WriteTo.Console(ConsoleLogLevel??LogEventLevel.Warning)
.WriteTo.Elasticsearch(/* omitted for conciseness */);
}
And then, pass along your provided configuration object:
builder.UseSerilog((hostContext, loggerConfiguration) =>
{
var options = hostContext.Configuration.GetSection("LoggingConfiguration")
.Get<LoggingConfigurationOption>();
options.ConfigureLogger(loggerConfiguration);
});