Applcation에서 발생한 Exception을 분석하고 처리하기 위해 Exception을 파일로 기록하려는 경우, 모든 Try, Catch에 Exception을 기록하는 로직을 두는 것은 여간 괴로운 일이 아닙니다. 이러한 코드 작성 방식은 시스템 유지보수에 있어서 더 치명적입니다. 여기에서는 WCF에서 발생하는 Exception을 OS의 EventLog에 기록하는 클래스를 작성하고 WCF Service에 부여하는 방법에 대해서 소개할 것입니다.
Exception을 기록하는 것 뿐만 아니라, Application 전역에서 발생하는 모든 Exception에 대해서 특정한 동작을 부여하고 싶을 분들에게 이 포스트가 도움이 될 수 있습니다.
이 기능의 구현은 WCF를 확장하는 몇 가지 Interface를 구현하고 Web.Config에 설정을 추가하는 것만으로 실현될 수 있습니다.
using System;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Channels;
using System.Diagnostics;
/// <summary>
/// 이벤트 처리기
/// </summary>
public class ErrorHandler : IErrorHandler
{
public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
{
//이 Method는 Exception을 Fault로 바꾸고자 할 때 사용합니다.
}
public bool HandleError(Exception error)
{
//1. EventSource 생성
if (!EventLog.SourceExists("NakedStrength"))
EventLog.CreateEventSource("NakedStrength", "Application");
//2. Exception 쓰기
EventLog.WriteEntry("NakedStrength", error.ToString());
return false;
}
}
HandleError Method는 Exception이 발생할 때마다 실행될 것입니다. 마지막에 return false;를 통해 Exception이 Handle되지 않도록 하였습니다. using System;
using System.ServiceModel.Description;
using System.ServiceModel;
using System.Collections.ObjectModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;
/// <summary>
/// ErrorHandler를 모든 Service Channel에 적용하는 ServiceBehavior
/// </summary>
public class ErrorServiceBehavior : IServiceBehavior
{
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
}
public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
{
}
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
ErrorHandler handler = new ErrorHandler();
foreach (ChannelDispatcher dispatcher in serviceHostBase.ChannelDispatchers)
dispatcher.ErrorHandlers.Add(handler);
}
}
ApplyDispatchBehavior Method에서 위에서 작성한 ErrorHandler를 생성하여 동작 중인 ServiceChannel에 추가하고 있습니다. using System;
using System.ServiceModel.Configuration;
/// <summary>
/// 생성한 ErrorServiceBehavior를 Web.Config에 추가히기 위해 확장엘리먼트로 생성
/// </summary>
public class ErrorHandlerBehavior : BehaviorExtensionElement
{
protected override object CreateBehavior()
{
return new ErrorServiceBehavior();
}
public override Type BehaviorType
{
get
{
return typeof(ErrorServiceBehavior);
}
}
}
<system.serviceModel>
<extensions>
<behaviorExtensions>
<!-- Exception Log 기능 추가 -->
<add name="ExceptionLogger" type="Dispatch.Service.ErrorHandlerBehavior, Dispatch.Service, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</behaviorExtensions>
</extensions>
.. 기타 노드
</system.serviceModel>
이로서 모든 설정은 마쳤습니다. 이제 Exception을 발생시키면 다음과 같이 Event Log에 기록으로 남을 것입니다. OS의 Event View를 통해 확인하면 다음과 같습니다.