Serilog 中环境 LogContext 的线程安全
Thread safety of the ambient LogContext in Serilog
根据 this 文章,您可以像这样在 Serilog 中将请求 ID 附加到环境上下文(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);
}
这很好,而且似乎有效。我有两种情况需要这个:
- 将关联 ID 添加到 API.
的每个请求的日志中
- 为队列的每个消息读取添加一个相关 ID。
让我感到困惑的是,如果多个请求同时到达 API,或者我们同时处理多条消息,会发生什么情况。由于 LogContext
是静态 class,我是否可以不小心用另一个线程的值覆盖 LogContext
中的 RequestId
属性,而不是最初设置 属性?
假设线程 1 将 RequestId
设置为 1
。在完成之前,线程 2 将 RequestId
设置为 2
,因为我们收到了另一个请求。线程 1 现在会在记录时使用 2
作为 RequestId
的值吗?我猜它不会,但有人可以解释为什么吗?根据此 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.
Serilog 从 LogContext.PushProperty(...)
方法返回的每个句柄是否有一个堆栈?有什么方法可以覆盖 RequestId
,或许不需要再次调用 LogContext.PushProperty("RequestId", Request.Id)
?
LogContext is thread-safe via AsyncLocal/ThreadStatic。每个线程都有自己的 LogContext,尽管它是通过静态 class 访问的。请求不共享相同的 LogContext。
根据 this 文章,您可以像这样在 Serilog 中将请求 ID 附加到环境上下文(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);
}
这很好,而且似乎有效。我有两种情况需要这个:
- 将关联 ID 添加到 API. 的每个请求的日志中
- 为队列的每个消息读取添加一个相关 ID。
让我感到困惑的是,如果多个请求同时到达 API,或者我们同时处理多条消息,会发生什么情况。由于 LogContext
是静态 class,我是否可以不小心用另一个线程的值覆盖 LogContext
中的 RequestId
属性,而不是最初设置 属性?
假设线程 1 将 RequestId
设置为 1
。在完成之前,线程 2 将 RequestId
设置为 2
,因为我们收到了另一个请求。线程 1 现在会在记录时使用 2
作为 RequestId
的值吗?我猜它不会,但有人可以解释为什么吗?根据此 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.
Serilog 从 LogContext.PushProperty(...)
方法返回的每个句柄是否有一个堆栈?有什么方法可以覆盖 RequestId
,或许不需要再次调用 LogContext.PushProperty("RequestId", Request.Id)
?
LogContext is thread-safe via AsyncLocal/ThreadStatic。每个线程都有自己的 LogContext,尽管它是通过静态 class 访问的。请求不共享相同的 LogContext。