如何在写入 MemoryTarget Logs 时在 NLog 中以线程安全的方式检索该属性

How to retrieve a MemoryTarget Logs property in a thread-safe manner in NLog while it is being written to

提问人:Jean-Baptiste Zeller 提问时间:11/15/2023 最后编辑:Jean-Baptiste Zeller 更新时间:11/19/2023 访问量:58

问:

我在我的代码中使用了 MemoryTarget 记录器,它将从另一个线程馈送。

有时,我需要向某些 webapi 调用提供日志,因此我需要检索 Logs 属性的内容。

问题是,Logs 属性是由 List 支持的 IList。因此,在写入日志时,通过 NLog 的帮助保持线程安全。在写入日志时,我无法访问日志的内容,并且我无法控制人们何时何地写入日志,并且似乎没有线程安全选项来检索数据。

我正在使用 .Net 4.8 框架。

当前简化代码

public const string filter = "theFilterHere";

public string TargetName { get; set; }

public MemoryTarget Logger { get; private set; }

public void InitLog() {
  Logger = new MemoryTarget();
  var rule = new LoggingRule(filter, LogLevel.Debug, Logger);
                    LogManager.Configuration.AddTarget(TargetName, Logger);
                    LogManager.Configuration.LoggingRules.Add(rule);
                    LogManager.ReconfigExistingLoggers();
}

public List<string> Logs { 
  // Crash happens here. I need the list in reverse order because reasons, but looking at it I know I would have the same problem if I did a ToList first.
  return Logger.Logs.Reverse().ToList();
}

我知道使用日志的 SyncRoot 无济于事,因为我没有锁定对日志的写入访问权限。我今天唯一的想法是将日志(IList)转换为列表,然后执行类似于以下内容的代码:

List<string> currentLogs = Logger.Logs as List<string>;
if (currentLogs is null) {
  // NLog changed the internal structure of MemoryTarget.
  return Logger.Logs.Reverse().ToList();
}
int count = currentLogs.Count;
string[] logs = new string[count];

// Assumption : the list doesn't shrink, the log will only grow and never empty.
// this is only available on List<T>, and internally seems to do an Array copy of the _items array.
currentLogs.CopyTo(0, logs, 0, count);

我是走在正确的轨道上,还是无可救药地错了?

C# 日志记录 nlog net-4.8

评论

1赞 Rolf Kristensen 11/16/2023
创建 github.com/NLog/NLog/pull/5409,使 Logs 属性线程安全,即将推出的 NLog 版本 5.2.6
0赞 Jean-Baptiste Zeller 11/17/2023
@RolfKristensen我从没想过会有这么快的响应,尤其是来自贡献者。先生,你是山羊。在等待下一个版本时,我继续制作了自己的 LayoutTarget,由 ConcurrentStack 支持。我不需要 IList 可以做的所有事情,例如修剪或修改日志列表,而且我需要反转列表,以便一鸟两石。但非常感谢您的快速回复!

答:

1赞 Rolf Kristensen 11/19/2023 #1

NLog v5.2.6 已发布,允许对 NLog MemoryTarget 属性进行线程安全枚举:Logs

Смотритетакже: https://github.com/NLog/NLog/pull/5409