2012-04-25 2 views
2

multicastOnExceptionAspectPostsharp에서 어셈블리 수준으로 적용됩니다. 이것은 자연스럽게 예외를 던지면 모든 메소드가 Aspect를 호출한다는 것을 의미합니다.멀티 캐스트 OnExceptionAspect가 버블 링 예외를 로깅합니다.

Aspect 내 예외가 발생했을 때 매개 변수의 값을 포함하는 예외 세부 정보 이 기록됩니다. 정상적으로 작동합니다.

그러나 어셈블리의 모든 메소드에 적용되기 때문에 예외가 스택을 통해 위로 향하기 때문에 스택의 각 메소드에 대해 로그 항목이 작성됩니다.

이 문제를 방지하는 방법에 대한 아이디어가 없습니다. 처음에는 예외를 비교하려고했으나 (이 것이 동일한 지 알아보기 위해) 그러나 이것은 지저분 해 보입니다. 누군가 전에이 문제가 있었음에 틀림 없다.

+0

의도 한 행동은 무엇입니까? 그 점에 대해 당신은 분명하지 않습니다. –

+0

사과. 예외 지점에서 메서드의 스택 추적 및 매개 변수를 기록 할 수 있어야합니다. 그러나 나는 또한 예외적으로 다시 로깅하지 않고 정상적인 스택처럼 전파하기를 원한다. –

답변

0

나는이 일을 볼 수있는 한 가지 방법은 사용자 지정 예외를 정의하고 그냥 귀하의 측면에서 그 하나를 던질 것입니다. 또한 사용자 측면에서 loggin 전에 예외를 확인하십시오. 사용자 정의 예외 로그가 아니라면 로그를 남기지 말고 (다시 던지기)? 당신은 여전히 ​​예외 다 정의해야 할 것 물론

[Serializable] 
public class DatabaseExceptionWrapper : OnExceptionAspect 
{ 
    public override void OnException(MethodExecutionArgs args) 
    { 
     if(!(args.Exception is CustomException)) 
     { 
     string msg = string.Format("{0} had an error @ {1}: {2}\n{3}", 
      args.Method.Name, DateTime.Now, 
      args.Exception.Message, args.Exception.StackTrace); 

     Trace.WriteLine(msg); 
     } 

     throw new CustomException("There was a problem"); 
    } 
} 

: 같은 예제 코드가 보일 것 무엇

. :)

+0

좋은 생각인데, 예외가 그 메소드에서 발생했는지 또는 아래에서 위로 올라가고 있는지 알 수있는 방법은 무엇입니까? –

+0

@ m.edmondson : 중요할까요?당신은 aspect에 의해 커스텀 예외가 던져졌고 당신이 이미 그것을 기록했다는 것을 알았지 만 그것이 던져진 깊이가 정말로 중요하지는 않습니까? – shriek

+1

나는 그렇지 않다고 생각하지만 도움이되지 않는 정보로 내 기록을 채우고 싶지 않습니다. 방해가됩니다. –

4

이 문제를 해결할 수있는 방법은 두 가지가 있습니다.

A. 이미 기록 된 예외를 저장하려면 스레드 정적 필드를 사용하십시오.

[Serializable] 
public class MyAspect : OnExceptionAspect 
{ 
    [ThreadStatic] 
    private static Exception lastException; 

    public override void OnException(MethodExecutionArgs args) 
    { 
     if(args.Exception != lastException) 
     { 
     string msg = string.Format("{0} had an error @ {1}: {2}\n{3}", 
      args.Method.Name, DateTime.Now, 
      args.Exception.Message, args.Exception.StackTrace); 

     Trace.WriteLine(msg); 
     lastException = args.Exception; 
     } 

    } 
} 

B. 예외 객체에 태그를 추가하십시오.

[Serializable] 
public class MyAspect : OnExceptionAspect 
{ 
    private static object marker = new object(); 

    public override void OnException(MethodExecutionArgs args) 
    { 
     if(!args.Exception.Data.Contains(marker)) 
     { 
     string msg = string.Format("{0} had an error @ {1}: {2}\n{3}", 
      args.Method.Name, DateTime.Now, 
      args.Exception.Message, args.Exception.StackTrace); 

     Trace.WriteLine(msg); 
     args.Exception.Data.Add(marker, marker); 
     } 

    } 
} 
2

FYI - Gael은 PostSharp 전문가입니다. 왜냐하면 그가 고용되어 있기 때문입니다.

StackTrace를 검사하여 어디에서 예외가 발생했는지 항상 알 수 있습니다. StackTrace는 args.Exception.StackTrace를 통해 사용할 수 있습니다. 당신은 더스틴 데이비스 (다른 PostSharp 직원이) 여기 권장 무엇을 시도 할 수 있습니다 : 다음 구문 분석 결과와 args.Method.Name 비교 :

PostSharp - OnExceptionAspect - Get line number of exception이 (How to split a stacktrace line into namespace, class, method file and line number? 여기에 설명 된 방법을 통해) 스택 트레이스를 구문 분석합니다. args.Method.Name이 (StackTrace 구문 분석을 통해 찾은) 원래 메서드와 동일하면 무시해야한다는 것을 알고 있으면 무시합니다. 여기

는 (이전이 개 인용 솔루션에 대한 건물) 내 솔루션은보다 구체적인하기 위해 몇 가지 코드입니다 (. 또는, 정직하게, 당신은 단지 가엘의 추천 솔루션 중 하나를 사용할 수 있습니다)

[Serializable] 
public class ExceptionWrapper : OnExceptionAspect 
{ 
    public override void OnException(MethodExecutionArgs args) 
    { 
     var st = new StackTrace(args.Exception, true); 
     var frame = st.GetFrame(0) 
     var lineNumber = frame.GetFileLineNumber(); 
     var methodName = frame.GetMethod(); 
     if(methodName.Equals(args.Method.Name)) 
     { 
      string msg = string.Format("{0} had an error @ {1}: {2}\n{3}", 
       args.Method.Name, DateTime.Now, 
       args.Exception.Message, args.Exception.StackTrace); 

      Trace.WriteLine(msg); 
     } 
    } 
}