개요
안녕하세요 피터입니다.
오늘은 C# 프로젝트에 log4net 라이브러리를 통해 로그 시스템(log system)을 적용하는 방법을 알려드리겠습니다.
프로젝트를 진행하다 보면 로그 시스템이 절실할 때가 있습니다.
특정 상황에서 에러가 발생하는데 어떤 절차에 의해 실행하면 에러가 발생하는지 추적이 어려울 때가 바로 그런 경우입니다.
또한 개발을 진행할 때에는 세부적이고 자세한 로그를 기록하는 것이 도움이 되지만 실제로 사용자가 프로그램을 쓸 때에는 중요한 내용만 기록하는 것이 더 도움이 됩니다.
이런 이유로 상황에 따라 어떤 수준의 로그를 기록할지 손쉽게 설정할 수 있는 로그 시스템이 필요합니다.
C# 프로젝트에서는 log4net 라이브러리를 통해 이러한 기능을 쉽게 구현 할 수 있습니다.
로그시스템 적용
log4net 라이브러리 설치
Visual studio 에서는 nuget을 통해 손쉽게 라이브러리를 설치 할 수 있습니다.
먼저 로그시스템을 적용하고자 하는 프로젝트를 열고 nuget에서 log4net을 검색합니다.
nuget 에서 log4net (Apach Software Foundation)을 검색하여 적용하고자 하는 프로젝트에 설치합니다.
log4net 환경설정 파일 추가
로그 시스템을 프로젝트에 원하는대로 적용하기 위해서는 환경설정 파일이 필요합니다.
[프로젝트] - [추가] - [새 항목] 클릭
"구성" 을 키워드로 검색하여 "응용 프로그램 구성 파일" (확장자가 config)을 선택합니다.
파일명을 log4net.config 로 변경한 다음 추가를 클릭합니다.
(파일명은 원하는대로 변경이 가능합니다. 설정파일을 읽어오는 부분도 동일하게 변경해주시면 됩니다.)
예제) log4net.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<log4net>
<root>
<level value="ALL"/>
<appender-ref ref="console"/>
<appender-ref ref="file"/>
<appender-ref ref="fatal_file"/>
</root>
<appender name="console" type="log4net.Appender.ConsoleAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date %level %logger - %message%newline" />
</layout>
</appender>
<appender name="file" type="log4net.Appender.RollingFileAppender">
<file value="log\app.log" />
<appendToFile value="true" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="5" />
<maximumFileSize value="100MB" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %level %logger - %message%newline" />
</layout>
</appender>
<appender name="fatal_file" type="log4net.Appender.RollingFileAppender">
<file value="log\fatal.log" />
<appendToFile value="true" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="5" />
<maximumFileSize value="100MB" />
<staticLogFileName value="true" />
<filter type="log4net.Filter.LevelRangeFilter">
<param name="LevelMin" value="FATAL" />
<param name="LevelMax" value="FATAL" />
</filter>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %level %logger - %message%newline" />
</layout>
</appender>
</log4net>
</configuration>
log4net의 설정에서는 appender가 핵심적인 역할을 수행합니다.
appender의 종류에 따라 화면에 출력하거나 파일에 기록할 수 있으며, 이메일로도 로그를 전송할 수 있습니다.
위에서 사용한 appender는 아래 2가지 입니다.
log4net.Appender.ConsoleAppender (화면에 출력하는 appender)
log4net.Appender.RollingFileAppender (파일에 기록하는 appender)
RollingFileAppender에 대한 위 설정은 설치파일경로\log\app.log 파일로 로그를 기록하며, 100MB 초과 시 5개까지 파일을 분기하는 설정입니다.
<root>
<level value="ALL"/>
<appender-ref ref="console"/>
<appender-ref ref="file"/>
<appender-ref ref="fatal_file"/>
</root>
appender 들을 설정했으면 root 태그에 appender-ref 를 추가해줍니다.
log4net 라이브러리에서 발생한 로그들을 appender-ref 목록에 있는 appender 들에게 전달해주는데 만일 level을 지정하면 지정된 레벨 이상의 로그만 appender 로 전달할 수 있습니다.
레벨에 설정 가능한 값
- ALL
- DEBUG
- INFO
- WARN
- ERROR
- FATAL
appender 별로 로그 레벨을 지정하고자 할 때는 아래와 같이 appender 내부에 filter를 사용하면 됩니다.
<filter type="log4net.Filter.LevelRangeFilter">
<param name="LevelMin" value="FATAL" />
<param name="LevelMax" value="FATAL" />
</filter>
환경설정을 다 작성하였으면 log4net.config 파일 속성의 고급에서 아래 내용을 변경해줍니다.
아래 속성을 지정해주지 않으면 빌드 시 환경설정 파일이 출력디렉토리에 복사되지 않기 때문에 실행했을 때 환경설정을 읽어오지 못하게 되니 반드시 적용해주세요.
빌드작업 - 내용
출력 디렉터리에 복사 - 항상 복사 ("새버전이면 복사"로 해도 무방합니다)
환경설정 파일 로드
프로젝트에서 환경설정 파일을 읽어올 수 있도록 AssemblyInfo.cs 파일 하단에 코드를 추가해줍니다.
위에서 파일 이름을 변경했다면 변경한 파일 이름으로 작성해주셔야 합니다.
[assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4net.config", Watch = true)]
Watch = true 라는 옵션을 주면 프로그램 실행 중에 config 파일을 수정해도 바로 반영됩니다.
이 옵션은 상당히 유용한 옵션으로 프로그램을 재실행하지 않고도 로그 시스템의 설정을 바꿀 수 있기 때문에 사용을 권장드립니다.
로그 인터페이스 생성 및 로그 기록
using log4net;
public partial class App : Application
{
private static readonly ILog log = LogManager.GetLogger(typeof(App));
protected override void OnStartup(StartupEventArgs e)
{
log.Info("============= Started application =============");
base.OnStartup(e);
}
}
App.xaml.cs 에 log4net 라이브러리를 추가하고 프로그램이 시작 할 때 로그를 기록해봤습니다.
LogManager의 GetLogger 메소드를 통해 ILog 인터페이스를 얻어올 수 있습니다.
GetLogger에 파라미터로 넘겨주는 이름이 나중에 로그에 기록될 때 식별자로 기록됩니다.
이렇게 얻은 ILog 인터페이스를 통해 로그를 기록 할 수 있습니다.
private static readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
log.Debug("Debug");
log.Info("Info");
log.Warn("Warn");
log.Error("Error");
log.Fatal("Fatal");
}
ILog 인터페이스는 위와같이 레벨별 메소드들을 제공합니다.
작은 팁을 드리면 Error 로그는 아래와 같이 Exception 객체를 파라미터로 넘겨서 출력할 수 있습니다.
try
{
;
}
catch (Exception ex)
{
log.Error($"An exception occurred from {MethodBase.GetCurrentMethod().Name}", ex);
}
비즈니스 로직이 들어가는 코드를 위와 같이 작성해두면 나중에 에러가 발생했을 때 추적이 쉬워집니다.
로그 기록 확인
위에서 설정한 대로 실행파일이 위치한 디렉토리 하위에 log 라는 디렉토리와 로그파일이 생성된 것을 확인 할 수 있습니다.
로그 파일을 열어보면 레벨별로 잘 기록된 것을 볼 수 있습니다.
-Peter의 우아한 프로그래밍
여러분의 공감과 댓글은 저에게 크나큰 힘이 됩니다. 오류 및 의견 주시면 감사하겠습니다.