DotNET Console Generic Host - Logging With Serilog
2022. 9. 8. 00:00ㆍDOTNET/Generic Host
반응형
이번에는 Console 앱에서 Serilog 를 사용해 보겠다.
일반적인 console 앱에서 사용하는 방식이 아닌 ASPNET Core 에서 사용했던 방식을 활용하겠다.
Generic Host 를 이용하면 appsettings.json 을 통해서 값을 읽어와서 Serilog 를 설정할 수 있다.
아래 package 를 설치하자
dotnet add package Serilog.Extensions.Hosting
dotnet add package Serilog.Sinks.File
dotnet add package Serilog.Sinks.Console
dotnet add package Serilog.Settings.Configuration
Program.cs 를 다음과 같이 변경하자
using GenericHost.InjectableServices;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Serilog;
Log.Logger = CreateBootstrapLogger();
try
{
IHost host = Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
services.AddHostedService<Worker>();
//services.AddTransient<IHelloworld, Helloworld>();
services.Scan(scan => scan
.FromAssemblyOf<ITransientService>()
.AddClasses(classes => classes.AssignableTo<ITransientService>())
.AsSelfWithInterfaces()
.WithTransientLifetime()
.AddClasses(classes => classes.AssignableTo<IScopedService>())
.AsSelfWithInterfaces()
.WithScopedLifetime()
.AddClasses(classes => classes.AssignableTo<ISingletonService>())
.AsSelfWithInterfaces()
.WithSingletonLifetime()
);
})
.UseSerilog((context, configuration) => configuration.ReadFrom.Configuration(context.Configuration))
.Build();
host.Run();
}
catch(Exception ex)
{
// ef migration 시에 나타나는 오류를 log 로 보내는 코드
// https://github.com/dotnet/runtime/issues/60600
string type = ex.GetType().Name;
if (type.Equals("StopTheHostException", StringComparison.OrdinalIgnoreCase))
throw;
Log.Fatal(ex, "Host terminated unexpectedly");
}
finally
{
Log.CloseAndFlush();
}
static Serilog.ILogger CreateBootstrapLogger()
{
var configurationBuilder = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", false, true)
.AddJsonFile($"appsettings.Development.json", optional: true)
.Build();
return new LoggerConfiguration()
.ReadFrom.Configuration(configurationBuilder)
.CreateBootstrapLogger();
}
ApiLogger.cs
using GenericHost.InjectableServices;
using Microsoft.Extensions.Logging;
using System.Runtime.CompilerServices;
namespace GenericHost;
public class ApiLogger : ITransientService
{
private ILogger _logger;
public ApiLogger(ILogger<ApiLogger> logger) => _logger = logger;
public void Log(LogLevel logLevel, string message,
[CallerMemberName] string membername = "",
[CallerFilePath] string filePath = "",
[CallerLineNumber] int lineNumber = 0,
params object[] args) =>
_logger.Log(logLevel, message, membername, filePath, lineNumber, args);
public void LogDebug(string message,
[CallerMemberName] string membername = "",
[CallerFilePath] string filePath = "",
[CallerLineNumber] int lineNumber = 0,
params object[] args) =>
_logger.LogDebug(
CreateLogMessage(message, membername, filePath, lineNumber), args);
public void LogError(string message,
[CallerMemberName] string membername = "",
[CallerFilePath] string filePath = "",
[CallerLineNumber] int lineNumber = 0,
params object[] args) =>
_logger.LogError(
CreateLogMessage(message, membername, filePath, lineNumber), args);
public void LogError(Exception exception, string message,
[CallerMemberName] string membername = "",
[CallerFilePath] string filePath = "",
[CallerLineNumber] int lineNumber = 0,
params object[] args) =>
_logger.LogError(exception,
CreateLogMessage(message, membername, filePath, lineNumber), args);
public void LogInformation(string message,
[CallerMemberName] string membername = "",
[CallerFilePath] string filePath = "",
[CallerLineNumber] int lineNumber = 0,
params object[] args) =>
_logger.LogInformation(
CreateLogMessage(message, membername, filePath, lineNumber), args);
public void LogTrace(string message,
[CallerMemberName] string membername = "",
[CallerFilePath] string filePath = "",
[CallerLineNumber] int lineNumber = 0,
params object[] args) =>
_logger.LogTrace(
CreateLogMessage(message, membername, filePath, lineNumber), args);
public void LogWarning(string message,
[CallerMemberName] string membername = "",
[CallerFilePath] string filePath = "",
[CallerLineNumber] int lineNumber = 0,
params object[] args) =>
_logger.LogWarning(
CreateLogMessage(message, membername, filePath, lineNumber), args);
private string CreateLogMessage(string message,
string memberName, string filePath, int lineNumber) =>
$"[{memberName}] {message}. \nfilePath = {filePath} : line = {lineNumber}";
}
Worker.cs 에서 사용
using GenericHost;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
public sealed class Worker : IHostedService
{
private readonly ApiLogger _logger;
private readonly IHelloworld _helloworld;
private readonly IConfiguration _configuration;
public Worker(
ApiLogger logger,
IHostApplicationLifetime appLifetime,
IHelloworld helloworld,
IConfiguration configuration)
{
_logger = logger;
_helloworld = helloworld;
_configuration = configuration;
appLifetime.ApplicationStarted.Register(OnStarted);
appLifetime.ApplicationStopping.Register(OnStopping);
appLifetime.ApplicationStopped.Register(OnStopped);
}
public Task StartAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("1. StartAsync has been called.");
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("4. StopAsync has been called.");
return Task.CompletedTask;
}
private void OnStarted()
{
_logger.LogInformation("2. OnStarted has been called.");
_logger.LogInformation($"2.1. {_helloworld.Execute()} ");
var name = _configuration.GetSection("User").GetValue<string>("Name");
var age = _configuration.GetSection("User").GetValue<int>("Age");
_logger.LogInformation($"2.2. Name = {name} , Age = {age} ");
}
private void OnStopping()
{
_logger.LogInformation("3. OnStopping has been called.");
}
private void OnStopped()
{
_logger.LogInformation("5. OnStopped has been called.");
var name = _configuration.GetSection("User").GetValue<string>("Name");
var age = _configuration.GetSection("User").GetValue<int>("Age");
_logger.LogInformation($"5.1. Name = {name} , Age = {age} ");
}
}
appsettings.json
{
"Serilog": {
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information",
"System": "Warning"
}
},
"WriteTo": [
{ "Name": "Console" },
{
"Name": "File",
"Args": {
"path": "./logs/GenericHost.log",
"rollingInterval": "Day"
}
}
]
},
"User": {
"Name": "Yogingang",
"Age": 18
}
}
실행 후 bin/Debug/net6.0 폴더로 이동하면 logs 폴더가 있다. 들어가 보자
GenericHost.log 라는 이름으로 파일이 존재한다.
해당 파일을 영어보면 log 가 보일 것이다.
관련영상
반응형
'DOTNET > Generic Host' 카테고리의 다른 글
DotNET Console Generic Host - Event Driven With MediatR (0) | 2022.09.09 |
---|---|
DotNET Console Generic Host - Configuration (appsetting.json) (0) | 2022.09.07 |
DotNET Console Generic Host - Dependency Injection with Scrutor (0) | 2022.09.06 |
DotNET Console Generic Host - Create Project (0) | 2022.09.05 |