[WCF] Global Level에서 Exception 처리 또는 기록

2009. 11. 22. 15:46WEB/WebService

서문

Applcation에서 발생한 Exception을 분석하고 처리하기 위해 Exception을 파일로 기록하려는 경우, 모든 Try, Catch에 Exception을 기록하는 로직을 두는 것은 여간 괴로운 일이 아닙니다. 이러한 코드 작성 방식은 시스템 유지보수에 있어서 더 치명적입니다. 여기에서는 WCF에서 발생하는 Exception을 OS의 EventLog에 기록하는 클래스를 작성하고 WCF Service에 부여하는 방법에 대해서 소개할 것입니다.

Exception을 기록하는 것 뿐만 아니라, Application 전역에서 발생하는 모든 Exception에 대해서 특정한 동작을 부여하고 싶을 분들에게 이 포스트가 도움이 될 수 있습니다.

구현

이 기능의 구현은 WCF를 확장하는 몇 가지 Interface를 구현하고 Web.Config에 설정을 추가하는 것만으로 실현될 수 있습니다.

  1. IErrorHandler Interface를 구현하여 에러 처리기를 작성합니다.
    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되지 않도록 하였습니다.
  2. 동작중인 각 Service에 위에서 작성한 ErrorHandler를 추가하는 Service Behavior의 작성이 필요합니다. 이 것은 IServiceBehavior Interface를 상속함으로서 구현가능합니다.
    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에 추가하고 있습니다.
  3. 이제 위에서 생성한 Service Behavior를 Web.Config에 추가하기 위해 Extension Element을 생성해야 합니다.
    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);
            }
        }
    }
  4. 마지막으로 WCF의 Web.Config의 <system.serviceModel> Element를 다음과 같이 구성합니다.
    <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를 통해 확인하면 다음과 같습니다.

 

Event Logging에 대한 더 자세한 정보

http://msdn.microsoft.com/ko-kr/library/k00ce235.aspx