Implement the External Logging Source to Logging Information of API and Windows Service - Serilog.
Packages need Serilog.AspNetCore.
<PackageReference Include="Serilog.AspNetCore" Version="8.0.0" />
<PackageReference Include="Serilog.Extensions.Hosting" Version="8.0.0" />
<PackageReference Include="Serilog.Settings.AppSettings" Version="2.2.2" />
<PackageReference Include="Serilog.Settings.Configuration" Version="8.0.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="5.0.1" />
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
Confiuration of Serilog in API
Settings File
"LogBaseDirectory": "C:\\WindowsServiceLogs\\",
"Serilog": {
"Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File" ],
"MinimumLevel": "Debug",
"WriteTo": [
{
"Name": "Console"
},
{
"Name": "File",
"Args": {
"path": "%APP_BASE_DIRECTORY%/Logs/log-.txt",
"rollingInterval": "Day"
}
}
]
}
/*
%APP_BASE_DIRECTORY% - Will be read from App Settings and update in Startup of Service.
*/
Application / Worker Startup
using Serilog;
var host = Host.CreateDefaultBuilder(args)
.UseWindowsService()
.UseSerilog((context, services, configuration) => configuration
.ReadFrom.Configuration(context.Configuration)
.ReadFrom.Services(services))
.ConfigureServices(services =>
{
IConfigurationRoot configuration = new ConfigurationBuilder()
.SetBasePath(AppDomain.CurrentDomain.BaseDirectory)
.AddJsonFile("appsettings.json")
.Build();
if (!Directory.Exists(configuration["LogBaseDirectory"]))
{
Directory.CreateDirectory(configuration["LogBaseDirectory"]);
}
Environment.SetEnvironmentVariable("APP_BASE_DIRECTORY", configuration["LogBaseDirectory"]);
services.AddHostedService<SimpleWorker>();
})
.Build();
await host.RunAsync();
A Worker Class
public class SimpleWorker : BackgroundService
{
private readonly ILogger<SimpleWorker> _logger;
public SimpleWorker(ILogger<SimpleWorker> logger)
{
_logger = logger;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
_logger.LogInformation("Execute SimpleWorker -> [ExecuteAsync]");
await Task.Delay(1000, stoppingToken);
}
}
public override Task StartAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("Starting service [StartAsync]");
return base.StartAsync(cancellationToken);
}
/// <summary>
/// Executes when the service is performing a graceful shutdown.
/// </summary>
/// <param name="cancellationToken"><see cref="CancellationToken"/></param>
/// <returns><see cref="Task"/></returns>
public override Task StopAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("Stopping service [StopAsync]");
return base.StopAsync(cancellationToken);
}
}
That's all, We configured all things. Just run the application, See the configured folder check for the log file and console too.
Output
I will share the reference code in the comments section.