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를 통해 확인하면 다음과 같습니다.