ELMAH를 사용한 WCF 서비스에 대한 예외 로깅
우리는 ASP.NET 3.5 웹 애플리케이션에서 처리되지 않은 예외를 처리하기 위해 우수한 ELMAH를 사용하고 있습니다.이것은 REST 기능을 사용하여 소비되는 WCF 서비스를 제외한 모든 사이트에서 매우 잘 작동합니다.응용 프로그램 코드로 처리되지 않는 작업 방법 내에서 예외가 발생하면 WCF는 서비스 계약 및 구성 설정에 따라 다양한 방법으로 이를 처리합니다.이는 예외가 ASP.NET HttpApplication을 실행하는 것으로 끝나지 않습니다.ELMAH가 사용하는 오류 이벤트입니다.이 문제를 해결하기 위해 알고 있는 두 가지 솔루션은 다음과 같습니다.
- 모든 메서드 호출을 try { } catch(Exception ex) {Elmah}(으)로 래핑합니다.오류 신호입니다.FromCurrentContext().캐치 블록 내에서 엘마를 명시적으로 호출하려면 (ex); 던지기; }을(를) 올립니다.
- Will Hughes의 블로그 게시물 Making WCF와 ELMAH의 설명에 따라 IErrorHandler를 사용하여 ELMAH에 대한 호출을 별도의 ErrorHandler로 분해합니다.
첫 번째 옵션은 매우 간단하지만 완전히 건조하지는 않습니다.두 번째 옵션은 속성 및 ErrorHandler를 구현한 후 각 서비스를 사용자 지정 속성으로 장식하기만 하면 됩니다.저는 윌의 작업을 바탕으로 이 작업을 수행했지만 코드를 게시하기 전에 이 방법이 올바른지 확인하고 싶습니다.
제가 놓친 더 좋은 방법이 있을까요?
IErrorHandler에 대한 MSDN 문서에는 HandleError 메서드가 로깅을 수행하는 위치이지만 ELMAH는 HttpContext에 액세스한다고 나와 있습니다.현재의.응용 프로그램인스턴스. HttpContext에도 불구하고 이 메서드 내에서 null입니다.전류를 사용할 수 있습니다.ProvideFault 메서드 내에서 Elmah에 전화를 거는 것은 Application과 같은 해결 방법입니다.인스턴스가 설정되었지만 API 설명서에 설명된 의도와 일치하지 않습니다.제가 여기서 뭘 빠뜨린 건가요?설명서에는 작업 스레드에서 호출되는 HandleError 메서드에 의존해서는 안 된다고 명시되어 있습니다. 이는 응용 프로그램의 이유일 수 있습니다.인스턴스가 이 범위에서 null입니다.
제 블로그 게시물(OP에서 참조)의 솔루션은 오류 상태에서 HTTP 응답 코드를 변경하기 위해 사용 중이거나 사용 중인 기존 솔루션을 기반으로 했습니다.
그래서, 우리에게는 ELMAH에 대한 예외를 통과시키는 것이 한 줄 변경이었습니다.더 좋은 해결책이 있다면 저도 알고 싶습니다.
사후/참조 및 잠재적 개선을 위해 현재 솔루션의 코드가 여기 있습니다.
HttpErrorHandler 및 ServiceErrorBehavior 특성 클래스
using System;
using System.ServiceModel;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.Collections.ObjectModel;
using System.Net;
using System.Web;
using Elmah;
namespace YourApplication
{
/// <summary>
/// Your handler to actually tell ELMAH about the problem.
/// </summary>
public class HttpErrorHandler : IErrorHandler
{
public bool HandleError(Exception error)
{
return false;
}
public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
{
if (error != null ) // Notify ELMAH of the exception.
{
if (System.Web.HttpContext.Current == null)
return;
Elmah.ErrorSignal.FromCurrentContext().Raise(error);
}
}
}
/// <summary>
/// So we can decorate Services with the [ServiceErrorBehaviour(typeof(HttpErrorHandler))]
/// ...and errors reported to ELMAH
/// </summary>
public class ServiceErrorBehaviourAttribute : Attribute, IServiceBehavior
{
Type errorHandlerType;
public ServiceErrorBehaviourAttribute(Type errorHandlerType)
{
this.errorHandlerType = errorHandlerType;
}
public void Validate(ServiceDescription description, ServiceHostBase serviceHostBase)
{
}
public void AddBindingParameters(ServiceDescription description, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection parameters)
{
}
public void ApplyDispatchBehavior(ServiceDescription description, ServiceHostBase serviceHostBase)
{
IErrorHandler errorHandler;
errorHandler = (IErrorHandler)Activator.CreateInstance(errorHandlerType);
foreach (ChannelDispatcherBase channelDispatcherBase in serviceHostBase.ChannelDispatchers)
{
ChannelDispatcher channelDispatcher = channelDispatcherBase as ChannelDispatcher;
channelDispatcher.ErrorHandlers.Add(errorHandler);
}
}
}
}
사용 예
ServiceErrorBehavior 특성을 사용하여 WCF 서비스를 장식합니다.
[ServiceContract(Namespace = "http://example.com/api/v1.0/")]
[ServiceErrorBehaviour(typeof(HttpErrorHandler))]
public class MyServiceService
{
// ...
}
동작을 생성할 때ExtensionElement 구성을 사용하여 동작을 활성화할 수도 있습니다.
public class ErrorBehaviorExtensionElement : BehaviorExtensionElement
{
public override Type BehaviorType
{
get { return typeof(ServiceErrorBehaviourAttribute); }
}
protected override object CreateBehavior()
{
return new ServiceErrorBehaviourAttribute(typeof(HttpErrorHandler));
}
}
구성:
<system.serviceModel>
<extensions>
<behaviorExtensions>
<add name="elmah" type="Namespace.ErrorBehaviorExtensionElement, YourAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
</behaviorExtensions>
</extensions>
<behaviors>
<serviceBehaviors>
<behavior>
<elmah />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
그렇게 하면 ELMAH를 RIA 서비스와 함께 사용할 수도 있습니다!
이것은 일부 사람들에게는 명백할 수 있지만, 저는 단지 제 HttpContext의 이유를 알아내기 위해 꽤 오랜 시간을 보냈습니다.윌 휴즈의 훌륭한 답변을 모두 따랐음에도 불구하고 전류는 무효였습니다.당황스럽게도, 저는 이것이 제 WCF 서비스가 MSMQ 메시지에 의해 활성화되었기 때문이라는 것을 깨달았습니다.
나는 결국 그것을 다시 썼습니다.ProvideFault()
방법:
if (HttpContext.Current == null)
{
ErrorLog.GetDefault(null).Log(new Error(error));
}
else
{
ErrorSignal.FromCurrentContext().Raise(error);
}
저는 윌의 작업을 바탕으로 이 작업을 수행했지만 코드를 게시하기 전에 이 방법이 올바른지 확인하고 싶습니다.
저는 이것이 훌륭한 접근법이라고 생각합니다(이 게시물에 대한 윌의 칭찬!).윌이나 당신은 여기서 놓친 것이 없다고 생각합니다.IErrorHandler를 구현하는 것은 통신 채널에 장애가 발생할 수 있는 모든 가능한 서버 측 예외를 캡처하는 선호되는 방법이므로 ELMAH와 같은 일부 로깅에서 후크를 거는 것이 당연합니다.
마르크
WCF 데이터 서비스를 사용하여 제안된 답변을 얻을 수 없습니다.동작 속성 등을 연결했지만 오류가 기록되지 않았습니다.대신 서비스 구현에 다음 사항을 추가했습니다.
protected override void HandleException(HandleExceptionArgs args)
{
Elmah.ErrorSignal.FromCurrentContext().Raise(args.Exception);
base.HandleException(args);
}
나는 REST 물건으로 이것을 명시적으로 시도하지 않았고, ELMAH를 직접 사용하지도 않았지만, 조사할 가치가 있는 다른 옵션은 ID 디스패치 메시지를 사용하여 WCF에 연결하는 것일 수 있습니다.IErrorHandler 대신 Inspector.
언급URL : https://stackoverflow.com/questions/895901/exception-logging-for-wcf-services-using-elmah
'programing' 카테고리의 다른 글
Node.js - Mongoose - 컬렉션이 있는지 확인합니다. (0) | 2023.07.06 |
---|---|
여러 안드로이드 애플리케이션이 동일한 파이어베이스 데이터베이스에 액세스할 수 있습니까? (0) | 2023.07.06 |
Postgresql: 암호를 사용하여 psql 실행 스크립팅 (0) | 2023.07.06 |
TSQL DATTIME ISO 8601 (0) | 2023.07.06 |
삭제된 파일을 복원할 수 있습니까('git clean -fdx'를 해제합니다)? (0) | 2023.07.06 |