C# 斯蒂芬·克利里';s关于异步的新日志记录模式问题

C# 斯蒂芬·克利里';s关于异步的新日志记录模式问题,c#,C#,一旦我测试过斯蒂芬·克利里的新手机,我就喜欢它了。然而,有一点我不明白: 不幸的是,这里的解决方案不能很好地处理异步代码。这是因为异步将导致捕获异常,然后在等待时重新抛出。因此,异常过滤器在等待点运行,而不是在异常最初抛出的位置 我想举一个这样的例子,因为我的代码在Handle(…)/hisTrue(…)和nothrow中似乎运行良好 我故意让SubscribeAsync抛出一个异常 公共异步任务StartAsync(CancellationToken CancellationToken) {

一旦我测试过斯蒂芬·克利里的新手机,我就喜欢它了。然而,有一点我不明白:

不幸的是,这里的解决方案不能很好地处理异步代码。这是因为异步将导致捕获异常,然后在等待时重新抛出。因此,异常过滤器在等待点运行,而不是在异常最初抛出的位置

我想举一个这样的例子,因为我的代码在
Handle(…)
/his
True(…)
和no
throw中似乎运行良好

我故意让SubscribeAsync抛出一个异常

公共异步任务StartAsync(CancellationToken CancellationToken)
{
尝试
{
wait SubscribeAsync().configurewait(false);
}
当(句柄(()=>_logger.LogError(例如,“意外错误”)时捕获(异常)
{
}
}
公共静态类ExceptionFilterUtility
{
公共静态布尔句柄(操作)
{
动作();
返回true;
}
公共静态布尔传播(操作)
{
动作();
返回false;
}
}
我的目标是:

[2021-03-13 20:16:32 Error] ElonMuskBot.Core.TradeManagers.LiveTradeManager
Unexpected error.
ElonMuskBot.Core.Exceptions.RequestFailedException: Error while subscribing to the Spot candlestick update stream
   at ElonMuskBot.Core.Clients.SpotBotClient.SubscribeToCandleUpdatesAsync(String symbol, KlineInterval timeInterval, Action`1 onMessage) in E:\GitHub\elonmuskbot\src\ElonMuskBot.Core\Clients\SpotBotClient.cs:line 88
   at ElonMuskBot.Core.TradeManagers.LiveTradeManager.SubscribeAsync() in E:\GitHub\elonmuskbot\src\ElonMuskBot.Core\TradeManagers\LiveTradeManager.cs:line 54
   at ElonMuskBot.Core.TradeManagers.LiveTradeManager.StartAsync(CancellationToken cancellationToken) in E:\GitHub\elonmuskbot\src\ElonMuskBot.Core\TradeManagers\LiveTradeManager.cs:line 38
我想举一个这样的例子,因为我的代码在Handle(…)/histtrue(…)和no-throw;方面似乎运行良好

该模式的要点是在
抛出点捕获日志范围。无论哪种方式,异常处理本身都可以正常工作,但捕获的作用域是不同的

同步代码的日志范围被正确捕获,因为异常过滤器实际上是在
抛出点执行的。因此,异常记录在
抛出
,包括存在的所有日志作用域

但是,对于异步代码,它不能正常工作。异常将被很好地记录,但记录范围将不存在。这是因为异常过滤器在
等待
点执行,而不是在
抛出
点执行

下面是一个无法正确捕获异常日志记录范围的示例:

public async Task SubscribeAsync()
{
  using var _ = _logger.BeginScope("This will not be logged");
  await Task.Yield();
  throw new InvalidOperationException("This will be logged");
}
自从写了那篇博文之后,我已经开发出了一个更好的解决方案,它可以同时处理同步和异步异常以及异常。我还没来得及写一篇新的博文(对不起!),但一旦我写了,我会把旧的解决方案指向新的解决方案

较新的解决方案仅为.NET Core,因为它与
ILogger
相关联。用法示例:

// Don't forget to call IServiceCollection.AddExceptionLoggingScopes() in your startup.
public async Task StartAsync(CancellationToken cancellationToken)
{
  try
  {
    await SubscribeAsync().ConfigureAwait(false);
  }
  catch (Exception ex)
  {
    using (_logger.BeginCapturedExceptionLoggingScopes(ex))
      _logger.LogError(ex, "Unexpected error.");
  }
}

你声称“没问题”的结果是…@CaiusJard,我不明白你的意思。你的异常的堆栈跟踪是什么?@CaiusJard,这是正确的。就在那里。我从来没有见过这么严格的字符限制,但考虑到你在截图中只显示了大约6行,你显然掌握了“什么是证明这一点所需的合理数据量”,所以在将文本编辑到问题中时,请随意使用相同的判断谢谢你的回答!我看到了其他选择:。我实际上在用Serilog。哪一个更好?我肯定会用Serilog的。因为您可以在启动时设置它,然后不必麻烦使用
BeginCaptureXceptionLoggingScopes
BeginCaptureXceptionLoggingScopes
之所以存在,是因为Microsoft依赖项注入库的功能不够强大,无法扩展记录器以自动执行此操作。Serilog库直接扩展Serilog记录器,因此它没有相同的限制,因此其API更易于使用(无需
BeginCaptureDeceptionLoggingScopes
必要)。非常感谢您的解释!