【问题标题】:NLog is skipping log messages. .NET issue? Multi-thread issue?NLog 正在跳过日志消息。 .NET 问题?多线程问题?
【发布时间】:2016-01-12 22:08:28
【问题描述】:

我正在运行一个多线程 C# .NET 4.5 应用程序。

在我的本地 Windows 7 笔记本电脑上运行,NLog 记录我的所有消息。 我使用 Visual Studio 发布应用程序...将已发布的应用程序复制到 Windows Server 2008...并在服务器上运行该应用程序:这会导致跳过日志消息。有人可以帮助我了解为什么以及如何解决此问题或建议 NLog 的替代方案吗?

我的配置文件如下:

我在没有“async = true”的情况下试过这个

<targets async="true">


    <target  xsi:type="ColoredConsole"
            name="ColoredConsole"
            layout="${date} ${level} ${message} ${event-context:item=AlgID} " />

    <target name="xmlfile" xsi:type="File"
            fileName="C:\QRT\Logs\LogEmiter.Nlog.xlog" keepFileOpen="true"
            layout="${log4jxmlevent}" />

    <target xsi:type="File"
            name ="LogFile" fileName="C:\QRT\Logs\QRTLog-${shortdate}.log"
            layout ="${date:format=yyyy-MM-dd HH\:mm\:ss.fff}|${level}|${threadid}|${threadname}|${event-properties:item=FromID}|${message}${exception:format=tostring} "/>

    <target xsi:type="File"
            name ="TapeLogFile" fileName="C:\QRT\Logs\QRTMarketLog.txt"
            layout ="${date:format=yyyy-MM-dd HH\:mm\:ss.fff}|${level}|${message}"/>

  </targets>
     <rules>
        <!-- add your logging rules here -->

        <logger name ="TapeLogFile" minlevel="Trace" writeTo="TapeLogFile" />
        <logger name ="TapeLogFile" minlevel="Trace" writeTo="ColoredConsole" final="true"/>
        <logger name="*" minlevel="Trace" writeTo="ColoredConsole" />
        <logger name="*" minlevel="Trace" writeTo="xmlfile" />
        <logger name="*" minlevel="Trace" writeTo="LogFile" />


        <!--
        Write all events with minimal level of Debug (So Debug, Info, Warn, Error and Fatal, but not Trace)  to "f"
        <logger name="*" minlevel="Debug" writeTo="f" />
        -->
      </rules>
    </nlog>

我以这种方式记录消息:

在我的典型课程中,我会这样初始化我的 NLog 助手类:

    private void InitliazlieLogger()
    {
        LogManager.ThrowExceptions = true;
        m_logger = new NLogHelper(LogManager.GetCurrentClassLogger());
        m_logger.Set("FromID", "Email"); // Class setting.
    }

private void DoSomething(int _x) 
{
    m_logger.Debug ("Print this statement: {0}", _x);
}

我有一个 NLog 助手类...

public NLogHelper(Logger Logger)
{
    m_logger = Logger;
    m_properties = new Dictionary<string, object>();
}

public void Debug(string Message, params object[] Args)
        {
            m_logger.Debug()
                .Message(Message, Args)
                .Properties(m_properties)
                .Write();
            notify(Severity.Debug, Message);
        }

问题是一些日志消息被跳过了。 我添加了自己的日志记录类,它手动写入文件并在 NLogHelper.Debug 中插入了对 is 的调用,我发现我手动编写的文件有一组完整的日志消息,但 NLog 输出缺少一些。

同样,这适用于我的笔记本电脑,但在 Windows Server 2008 上失败。我的服务器安装了 .NET 4.6.1。我的 Windows 7 机器上似乎只有 4.5.2。会这样吗?

附带说明:如果我将所有源文件上传到服务器并在服务器上使用 Visual Studio 编译完全相同的代码,NLog 似乎可以工作?!?

-困惑。

谢谢 -埃德

【问题讨论】:

  • 'm_logger.Debug()' 将在源处于调试模式时记录。不是吗?这意味着当您在服务器上发布源代码时,这些二进制文件将以 RELEASE 模式运行。这意味着它将跳过日志记录语句。你不觉得吗?
  • 您提到,在您的服务器上,您从 VS 运行源代码,因此您再次以 DEBUG 模式运行它。对吗?
  • 你是对的。我尝试了几种在服务器上运行的方法。我发现“发布”需要在目标系统上“安装”,因此很难找到配置文件,所以我现在只需复制整个 bin/Debug 目录。无论如何,Logger.Debug 日志工作。丢失的是 Logger.Info。

标签: c# .net nlog


【解决方案1】:

编辑:这不是一个完整的答案。下面的答案解决了一半的问题。我没有注意到丢失的消息是 INFO 而不是 DEBUG。将我的所有 INFO 日志转换为 DEBUG 日志解决了我的问题。似乎即使我可以在本地机器上输出 INFO 日志,INFO 也可以在我的服务器上运行。仍然不是根本原因。 :(

嗯,我认为工作系统(我的笔记本电脑运行 Windows 7)和服务器(运行 Window Server 2008)之间的唯一区别是 Windows 版本和安装的 .NET 版本。

问题实际上是,感谢 Sibers 发现这一点,服务器有多个硬件 CPU 并且它的多线程比我的笔记本电脑上更接近真正的多线程。 NLog 发出错误消息,但我没有看到它们。它试图重写自己。

所以我(西伯斯)改变了:

<target xsi:type="File"
        name ="LogFile" fileName="C:\QRT\Logs\QRTLog-${shortdate}.log"
        layout ="${date:format=yyyy-MM-dd HH\:mm\:ss.fff}|${level}|${threadid}|${threadname}|${event-properties:item=FromID}|${message}${exception:format=tostring} "/>

到

    <target name="asyncWrapper" xsi:Type="AsyncWrapper" queueLimit="20000">
        <target name="LogFile"
            xsi:type="File"
            fileName="C:\QRT\Logs\QRTLog-${shortdate}.log"
            layout="${date:format=yyyy-MM-dd HH\:mm\:ss.fff}|${level}|${threadid}|${threadname}|${event-properties:item=FromID}|${message}${exception:format=tostring} "
            concurrentWrites="true" />
   </target>

问题已解决。 伙计……这花了我一个月的时间!我正要放弃,自己动手写一个logger。

-埃德

【讨论】:

  • 像你这样的 cmets 让我很兴奋:“我正要放弃并亲手编写自己的记录器。”对,因为那样你就没有没有问题了!要是这么简单就好了。假设“我无法让这个现有的东西工作,因此更好的答案是自己实现它”的逻辑错误。只是巨大的。
【解决方案2】:

我正在使用以下代码并且工作正常。

 public class ServerDataSource : IDataSource
    {
        private Logger _log;
        public ServerDataSource()
        {
            _log = LogManager.GetLogger("ServerDataSource");
        }
      public bool DoSomething()
        {
            try
            {
                  _log.Info("Doing something");

            }
            catch (Exception ex)
            {
                _log.Error("Error occurred" + ex.Message);
            }
        }
}

配置如下

  <configSections>
    <section name="nlog" type="NLog.Config.ConfigSectionHandler, NLog"/>
  </configSections>

【讨论】:

  • LogManager.GetLogger 和 LogManager.GetCurrentClassLogger 有什么区别?你是多线程的吗?你用过异步吗?
  • LogManager.GetCurrentClassLogger() 使用当前类名初始化 Logger 对象,但 LogManager.GetLogger("ServerDataSource") 使用您在参数中提供的名称初始化 Logger 对象。据我所知,记录器是线程安全的。您可以将记录器创建为静态变量一次。
  • 嗯...好的。但是...您没有将其声明为静态 :) 听起来区别仅在于命名。 '底线是我实现它的方式略有不同,因为我需要一个自定义变量(这样我就可以为类似类的多个实例输出 instanceID ......例如 StudentID)。 '还是不明白为什么我的实现不正确?
  • 感谢 Rajan 提供的信息,但您的代码不支持多线程。
猜你喜欢
  • 2015-11-11
  • 1970-01-01
  • 1970-01-01
  • 2012-08-17
  • 1970-01-01
  • 2013-01-13
  • 2018-08-07
  • 1970-01-01
相关资源
最近更新 更多