3

[IExceptionLogger][1]を実装している例外ログは、コントローラアクションから例外がスローされたときに2回呼び出されます。ASP.NET Web API 2回呼び出されたIExceptionLogger

context.RequestContext.Configuration.Services.GetServices(typeof(IExceptionLogger)) 

これは単一のエントリを返すので、私はロガーのインスタンスが1つしか登録されていないと確信しています。未処理の例外を2回ログに記録することは望ましくありません。それを引き起こす原因をトラブルシューティングするにはどうすればよいですか?

LogAsync()メソッドにブレークポイントを設定した場合、呼び出しスタックは両方の呼び出しで[External Code]と表示されます。

[RoutePrefix("test")] 
public class MyController : ApiController 
{ 
    [HttpGet, AllowAnonymous] 
    [Route("test")] 
    public string GetTest() 
    { 
     throw new InvalidOperationException("Shit happens"); 
    } 
} 

ロガーは、このように注入された:それは代わりにExceptionLoggerから継承されるように

config.Services.Add(typeof(IExceptionLogger), new WebApiExceptionLogger()); 

public class WebApiExceptionLogger : IExceptionLogger 
{ 
    private readonly ILoggingService loggingService; 

    public WebApiExceptionLogger() 
    { 
     this.loggingService = ServiceContainer.Factory.Resolve<ILoggingService>(); 
    } 

    public Task LogAsync(ExceptionLoggerContext context, CancellationToken cancellationToken) 
    { 
     this.loggingService.Log(LogLevel.Error, this.GetType().Name, context.Exception, "Ship has just happened"); 
     return Task.FromResult(true); 
    } 
} 
+0

ロガーコードを表示しますか?ただ2つの例外がスローされるのは可能でしょうか? – MartinM

答えて

4

は、変更WebApiExceptionLoggerをお試しください。 ExceptionLoggerは重複呼び出しを抑制する "ShouldLog"というカスタムメソッドを実装しています。 (同様のロジックを提供できない限り、このメソッドをオーバーライドしないでください)。これは私の問題を解決しました。

この動作は、WebApi2が、パイプライン内の別の場所から例外が発生したときに、要求ごとにLog/LogAsyncを2回呼び出すためです。これを処理するロジックがない限り、重複したログ呼び出しで終了します。

0

あなたがここにautofacを使用してグローバルな例外ハンドラを解決したいときについての注意点は、あなたが何ができるかです:

1)autofacタイプの登録方法が最初に呼び出されていることを確認します。そこには、一般的にこのような何か:

 builder.RegisterType<AppExceptionLogger>().AsSelf().AsImplementedInterfaces(); 
     builder.RegisterType<AppExceptionHandler>().AsSelf().AsImplementedInterfaces(); 

2)あなたのWebApiConfig.Register(HttpConfiguration設定)、またはあなたが持っている同様の呼び出しに以下を追加します。これはOWINせずに動作しますが、それが必要

 // Inject our exception logger and handler (get one from DR/Autofac) 
     config.Services.Replace(typeof(IExceptionHandler), config.DependencyResolver.GetService(typeof(AppExceptionHandler))); 
     config.Services.Replace(typeof(IExceptionLogger), config.DependencyResolver.GetService(typeof(AppExceptionLogger))); 

そこにも大丈夫です。

関連する問題