간접 호출 기반 로깅 시스템 설계
성능이 중요한 애플리케이션에서는 인터페이스 기반 로깅의 오버헤드를 줄이면서도 다형성을 유지하는 것이 중요합니다. 이 글에서는 Dictionary
를 활용한 간접 호출 기반 로깅 시스템을 설계하고, 이를 통해 성능과 유연성을 동시에 확보하는 방법을 설명합니다.
로깅 시스템 초기화
간접 호출 기반 로깅 시스템에서는 각 로그 레벨에 대해 Dictionary<LogLevel, Action<string>>
를 사용하여 로깅 메서드를 간접 호출하는 방식을 구현합니다. 이 방식은 인터페이스 기반 로깅 시스템과 다르게 메서드 호출을 사전 설정된 대리자를 통해 처리하여 성능을 최적화합니다.
public class Log
{
private static readonly Lazy<Log> instance = new Lazy<Log>(() => new Log());
public static Log Instance => instance.Value;
private Dictionary<LogLevel, Action<string>> _loggers = new Dictionary<LogLevel, Action<string>>();
private LogType _type = LogType.File;
private LogLevel _level = LogLevel.Debug;
private string _path = $@"C:\Logs\cLib.log";
public LogType Type
{
get => _type;
set
{
if (_type != value)
{
_type = value;
Build().Initialize();
}
}
}
public LogLevel Level
{
get => _level;
set
{
if (_level != value)
{
_level = value;
Initialize();
}
}
}
public string Path
{
get => _path;
set
{
if (_path != value)
{
_path = value;
Initialize();
}
}
}
public Log SetType(LogType type)
{
Type = type;
return this;
}
public Log SetLevel(LogLevel level)
{
Level = level;
return this;
}
public Log SetPath(string path)
{
Path = path;
return this;
}
public Log Build()
{
var loggerFactory = _type switch
{
LogType.Zero => new ZeroLoggerFactory(),
LogType.File => new SerilogLoggerFactory(),
_ => throw new ArgumentException("Invalid LogType")
};
InitializeLogger(loggerFactory.CreateLogger(_path, _level));
return this;
}
private void InitializeLogger(ILogger logger)
{
_loggers = new Dictionary<LogLevel, Action<string>>
{
{ LogLevel.Trace, logger.Trace },
{ LogLevel.Debug, logger.Debug },
{ LogLevel.Info, logger.Info },
{ LogLevel.Warn, logger.Info }, // Warn과 Info가 동일한 로그로 처리되는 경우
{ LogLevel.Error, logger.Error }
};
}
public static void LogMessage(LogLevel level, string msg)
{
if (Instance._loggers.TryGetValue(level, out var logAction))
{
logAction.Invoke(msg);
}
}
public static void Trace(string msg) => LogMessage(LogLevel.Trace, msg);
public static void Debug(string msg) => LogMessage(LogLevel.Debug, msg);
public static void Info(string msg) => LogMessage(LogLevel.Info, msg);
public static void Error(string msg) => LogMessage(LogLevel.Error, msg);
}