简体   繁体   English

Serilog 中环境 LogContext 的线程安全

[英]Thread safety of the ambient LogContext in Serilog

According to this article, you can attach a request ID to an ambient context (the LogContext ) in Serilog like this:根据这篇文章,您可以将请求 ID 附加到 Serilog 中的环境上下文( LogContext ),如下所示:

using (LogContext.PushProperty("RequestId", Request.Id))
{
    // Process request; all logged events will carry `RequestId`
    Log.Information("Adding {Item} to cart {CartId}", item, cart.Id);
}

And that is fine, and seems to be working.这很好,而且似乎正在工作。 I have two scenarios where I need this:我有两个需要这个的场景:

  • Add a correlation ID to logs per request to an API.将相关 ID 添加到对 API 的每个请求的日志中。
  • Add a correlation ID per message read of a queue.为队列的每条消息读取添加一个相关 ID。

What has me confused is what happens if multiple requests hits the API at once, or we process multiple messages concurrently.让我感到困惑的是,如果多个请求同时命中 API,或者我们同时处理多个消息,会发生什么。 Since LogContext is a static class, can I accidentally overwrite the RequestId property in the LogContext with values from another thread than the one who originally set the property?由于LogContext是 static class,我是否可以不小心用来自另一个线程的值而不是最初设置该属性的值覆盖LogContext中的RequestId属性?

Lets say thread 1 sets the RequestId to 1 .假设线程 1 将RequestId设置为1 Before it is finished, thread 2 sets the RequestId to 2 because we received another request.在完成之前,线程 2 将RequestId设置为2 ,因为我们收到了另一个请求。 Will thread 1 now use 2 as the value for RequestId when logging?线程 1 现在是否会在记录时使用2作为RequestId的值? I'm guessing it wont, but can someone explain why?我猜它不会,但有人可以解释为什么吗? According this this , pushing a property with the same name as an existing property onto the stack overwrites it:根据this ,将与现有属性同名的属性推送到堆栈上会覆盖它:

Pushing property onto the context will override any existing properties with the same name, until the object returned from PushProperty() is disposed, as the property A in the example demonstrates.将属性推送到上下文将覆盖任何具有相同名称的现有属性,直到从 PushProperty() 返回的 object 被释放,如示例中的属性 A 所示。

Does Serilog have one stack per handle returned from the LogContext.PushProperty(...) method, or something? Serilog 是否每个从LogContext.PushProperty(...)方法返回的句柄都有一个堆栈,还是什么? Is there any way I can override RequestId , perhaps short of calling LogContext.PushProperty("RequestId", Request.Id) again?有什么办法可以覆盖RequestId ,也许没有再次调用LogContext.PushProperty("RequestId", Request.Id)

LogContext is thread-safe via AsyncLocal/ThreadStatic . LogContext 通过 AsyncLocal/ThreadStatic 是线程安全的 Each thread has their own LogContext despite it being accessed through a static class.尽管通过 static class 访问每个线程都有自己的 LogContext。 Requests don't share the same LogContext.请求不共享相同的 LogContext。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM