在基于多用户的系统中使用 NLOG 的最佳实践?
Best practices for using NLOG with a multi-user based system?
我们需要在用户特定的基础上分离由 REST 网络服务生成的日志,并最终将这些日志导入到像 Datadogs.com 这样的聚合框架中。
有多种方法可以解决这个问题,我有兴趣在选择一种方法之前获得反馈。
基础知识是这样的:
- 使用 UserID 作为参数调用 Rest 服务。
- 设置 nlog LogManager.Configuration.Variable["userid"] = userid,或使用 MappedDiagnosticContext。
- 正常写入日志,直到 REST 调用完成。
视阶段而定
对于开发,使用 NLOG 文件记录器,因此开发人员可以简单地“跟踪”日志文件。使用 nlog 文件名目标中的变量作为
<target filename="/path/file-${var:userid}.log"/>.
或者在 nlog 目标中使用它作为:
layout="${var:userid}-${OtherLayout}
",并让开发人员执行 tail -f masterFile.log | grep USERID.
在生产中切换到使用 nlog JsonLayout,因此像 DataDog 这样的系统可以读取 Time、Threadid、Userid 和消息数据。使用 JsonFormat 并指定一个 userid 属性。我看到 JsonFormat 支持 MappedDiagnosticsLogicalContext 但我更喜欢 ${var:xxx} 格式的简单性来指定值。
问题:
我过去使用过 MappedDiagnosticContext,然后在目标文件名中指定它。我只是尝试使用 ${var} 方法,但它似乎没有用??
顾虑:
我喜欢开发的文件名目标方法。它应该适用于 10-100 名用户,但无法扩展到 1000 名用户。显然,对于 1000 个用户,我们需要在写入每一行后关闭日志文件,因为我们不想让 1000 个文件保持打开状态。
一个主要问题是线程。每个 web 服务可能被不同的用户多次调用,所有方法都需要 Nlog MappedDiagnosticContext 或 ${var} 功能是线程安全的。是吗?有什么问题需要考虑?
最终我们想在系统中引入一些结构化日志记录,但大部分代码库是使用标准日志记录技术构建的。如果在结构化日志记录中记录的对象包含 userid,则可以避免大部分复杂性,但这将需要为结构化日志记录进行大量重写工作。
显然,有很多事情要考虑,我知道我不是第一个考虑这个问题的人。
我们将不胜感激您的意见。
只需在需要的地方使用 NLog.MappedDiagnosticsLogicalContext.Set("userid", "someValue")
和 ${mdlc:item=userid}
。另见 http://github.com/NLog/NLog/wiki/MDLC-Layout-Renderer
MappedDiagnosticsLogicalContext
使用线程安全的 CallContext
(和 NetCore 上的 AsyncLocal
)。设置也将支持异步任务并跟随链式任务,但如果根据用户请求安排时间回调,则计时器回调将看不到用户 ID。
您应该避免在运行时更改 LogManager.Configuration.Variable
,它们对于所有并发请求都是全局的,并且可能会在配置重新加载期间丢失(如果配置了自动重新加载)。
我们需要在用户特定的基础上分离由 REST 网络服务生成的日志,并最终将这些日志导入到像 Datadogs.com 这样的聚合框架中。
有多种方法可以解决这个问题,我有兴趣在选择一种方法之前获得反馈。
基础知识是这样的:
- 使用 UserID 作为参数调用 Rest 服务。
- 设置 nlog LogManager.Configuration.Variable["userid"] = userid,或使用 MappedDiagnosticContext。
- 正常写入日志,直到 REST 调用完成。
视阶段而定
对于开发,使用 NLOG 文件记录器,因此开发人员可以简单地“跟踪”日志文件。使用 nlog 文件名目标中的变量作为
<target filename="/path/file-${var:userid}.log"/>.
或者在 nlog 目标中使用它作为:layout="${var:userid}-${OtherLayout}
",并让开发人员执行tail -f masterFile.log | grep USERID.
在生产中切换到使用 nlog JsonLayout,因此像 DataDog 这样的系统可以读取 Time、Threadid、Userid 和消息数据。使用 JsonFormat 并指定一个 userid 属性。我看到 JsonFormat 支持 MappedDiagnosticsLogicalContext 但我更喜欢 ${var:xxx} 格式的简单性来指定值。
问题:
我过去使用过 MappedDiagnosticContext,然后在目标文件名中指定它。我只是尝试使用 ${var} 方法,但它似乎没有用??
顾虑:
我喜欢开发的文件名目标方法。它应该适用于 10-100 名用户,但无法扩展到 1000 名用户。显然,对于 1000 个用户,我们需要在写入每一行后关闭日志文件,因为我们不想让 1000 个文件保持打开状态。
一个主要问题是线程。每个 web 服务可能被不同的用户多次调用,所有方法都需要 Nlog MappedDiagnosticContext 或 ${var} 功能是线程安全的。是吗?有什么问题需要考虑?
最终我们想在系统中引入一些结构化日志记录,但大部分代码库是使用标准日志记录技术构建的。如果在结构化日志记录中记录的对象包含 userid,则可以避免大部分复杂性,但这将需要为结构化日志记录进行大量重写工作。
显然,有很多事情要考虑,我知道我不是第一个考虑这个问题的人。
我们将不胜感激您的意见。
只需在需要的地方使用 NLog.MappedDiagnosticsLogicalContext.Set("userid", "someValue")
和 ${mdlc:item=userid}
。另见 http://github.com/NLog/NLog/wiki/MDLC-Layout-Renderer
MappedDiagnosticsLogicalContext
使用线程安全的 CallContext
(和 NetCore 上的 AsyncLocal
)。设置也将支持异步任务并跟随链式任务,但如果根据用户请求安排时间回调,则计时器回调将看不到用户 ID。
您应该避免在运行时更改 LogManager.Configuration.Variable
,它们对于所有并发请求都是全局的,并且可能会在配置重新加载期间丢失(如果配置了自动重新加载)。