Reputation: 5162
I was initially using one log file for Serilog, which I accomplished by doing this
var slc = new SerilogSubLoggerConfiguration();
configuration.GetSection("Serilog:SubLogger").Bind(slc);
and then configuring the SubLogger in the Main method of Program.cs
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(configuration)
.WriteTo.Logger(logger => logger.Filter.
ByIncludingOnly(lvl => lvl.Level == slc.Level).WriteTo.RollingFile(slc..PathFormat))
.CreateLogger();
I have moved to using three separate logs now defined in the appsettings file. This creates the class, with one property, a list of Serilog configurations
public class SerilogSubLoggerConfigurations
{
public List<SerilogSubLoggerConfiguration> SubLoggers { get; set; }
}
var slcs = configuration.GetSection("Serilog").Get<SerilogSubLoggerConfigurations>();
Now that I have my list of SubLogger configs, I need to create the logger, and add all these sub loggers. Each SubLogger will need its own
.WriteTo.Logger(logger => logger.Filter.
ByIncludingOnly(lvl => lvl.Level == slc.Level).WriteTo.RollingFile(slc..PathFormat))
line in the Log.Logger call, therefore I need to iterate over the SubLoggers. My intention was to write a method to do so.
public static LoggerConfiguration GetLoggerConfiguration(IConfiguration config, SerilogSubLoggerConfigurations slcs)
{
var lc = new LoggerConfiguration();
lc.ReadFrom.Configuration(config);
foreach (var cfg in slcs.SubLoggers)
{
lc.WriteTo.Logger(logger => logger.Filter
.ByIncludingOnly(lvl => lvl.Level == cfg.Level).WriteTo
.RollingFile(cfg.PathFormat));
}
lc.CreateLogger();
return lc;
}
and then just use this in the Main method
Log.Logger = GetLoggerConfiguration(configuration, slcs);
But this errs,
Cannot implicitly convert type 'Serilog.LoggerConfiguration' to 'Serilog.ILogger'
I tried changing the method to an ILogger and returning an ILogger, but ILogger doesn't contain the WriteTo and ReadFrom methods, so that was a no go. I tried casting the returned LoggerConfiguration to an ILogger, but that didn't work either and a number of other iterations that also failed.
There must be a way to accomplish this. Any help appreciated.
Update:
public static int Main(string[] args)
{
var currentEnv = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
var configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.AddJsonFile($"appsettings.{currentEnv}.json", optional: true)
.AddEnvironmentVariables()
.Build();
var slcs = configuration.GetSection("Serilog").Get<SerilogSubLoggerConfigurations>();
Log.Logger = BuildLogger(configuration, slcs);
Log.Information(Appname != null ? $"{Appname}{LogDelimeter}Logger created." : "Logger created.");
try
{
Log.Information(Appname != null ? $"{Appname}{LogDelimeter}Starting web host" : "Starting web host.");
BuildWebHost(args).Run();
return 0;
}
catch (Exception ex)
{
Log.Fatal(ex,
Appname != null
? $"{Appname}{LogDelimeter}Web Host terminated unexpectedly"
: "Web Host terminated unexpectedly");
return 1;
}
finally
{
Log.Information(Appname != null ? $"{Appname}{LogDelimeter}Flushing log and closing it." : "Flushing log and closing it.");
Log.CloseAndFlush();
}
}
Upvotes: 4
Views: 15669
Reputation: 31312
I tried changing the method to an ILogger and returning an ILogger, but ILogger doesn't contain the WriteTo and ReadFrom methods, so that was a no go.
The sequence of Serilog bootstraping is following:
Serilog.LoggerConfiguration
object and setup it with either code calls (WriteTo.RollingFile()
) or from config files (ReadFrom.Configuration()
).LoggerConfiguration.CreateLogger()
call.So before you finished loading configuration you can't log any messages (you don't have Logger
instance yet). But after you built a logger there is no point to call WriteTo
or ReadFrom
methods since logger is already built and changes to source configuration will not affect anything.
So you could change your GetLoggerConfiguration()
method as:
public static Serilog.ILogger BuildLogger(IConfiguration config, SerilogSubLoggerConfigurations slcs)
{
var lc = new LoggerConfiguration();
lc.ReadFrom.Configuration(config);
foreach (var cfg in slcs.SubLoggers)
{
lc.WriteTo.Logger(logger => logger.Filter
.ByIncludingOnly(lvl => lvl.Level == cfg.Level).WriteTo
.RollingFile(cfg.PathFormat));
}
// Apply any additional changes to lc configuration here
// Finally build a logger
return lc.CreateLogger();
}
static void Main(string[] args)
{
// ...
var logger = BuildLogger(configuration, subLoggerConfigurations);
// No any changes could be made to logging configuration at this point.
// Just log what you need.
logger.Information("Test info message");
}
Upvotes: 5