异常 c 中的消息模板#

Message template in exception c#

提问人:RubenHerman 提问时间:5/10/2023 最后编辑:RubenHerman 更新时间:5/10/2023 访问量:254

问:

我想创建一个例外,我可以在其中传递结构化消息模板。这可能吗?(也可以像使用 Serilog 一样立即记录它)

关于我想如何使用它的示例:

throw new NotFoundException("The book {BookId} was not found", book.Id); 

最终目标是使用 elasticsearch + kibana 来过滤掉错误消息。例如“给我所有包含'找不到书 {BookId}'的日志,其 bookid 范围在 100 到 1000 之间”

C# 异常 日志记录 kibana serilog

评论

0赞 Ralf 5/10/2023
throw new NotFoundException($"The book {book.Id} was not found")?
0赞 Ralf 5/10/2023
您的示例有点混淆 NotFoundException 与 ConflictException
0赞 RubenHerman 5/10/2023
对不起,复制粘贴...我会解决这个问题的
0赞 RubenHerman 5/10/2023
我不想使用插值字符串。我希望能够使用模板浏览我的日志。
0赞 Ralf 5/10/2023
然后为了更容易搜索。正如你提到的 serilog,你可能想看一个 inplementing a enricher。然后,扩充器可以获取您在此处拥有的 args 属性,并将其添加到您使用的任何日志接收器的输出中。throw new NotFoundException($"The book was not found. BookId = {book.Id}")

答:

0赞 RubenHerman 5/10/2023 #1

我的尝试一直都是正确的。要使用消息模板记录错误,可以传递异常、模板和参数。

例外:

public class NotFoundException : Exception
{
   public object?[] Args { get; set; }

   public NotFoundException(string message) : base(message)
   {
       Args = Array.Empty<object?>();
   }

   public NotFoundException(string message, params object?[] args) : base(message)
   {
       Args = args;
   }
}

中间件/ExceptionHandler:

    try {
        //Whatever
    }
    catch (NotFoundException e)
    {
        _logger.LogError(e, e.Message, e.Args);
    }

仅供参考,使用它的另一个优点(除了过滤掉日志)是,当您的异常消息中有动态数据时,您还可以更轻松地过滤掉异常。

try
{
    //Do some stuff
}
catch (NotFoundException e) when (e.Message == "The book {BookId} was not found"){
    //Do some more stuff
}
catch (NotFoundException e) when (Resources.BookNotFoundTemplate.Equals(e.Message)){
    //Do some more stuff
}
catch (NotFoundException e) when (e.Args[0] is 1234){
    //Do some more stuff
}

同样,对于测试异常消息时的单元测试......

await testedMethod.Should().ThrowAsync<NotFoundException>().Where(e => e.Message == "The book {BookId} was not found");
await testedMethod.Should().ThrowAsync<NotFoundException>().Where(e => e.Args[0] is 1234);