【问题标题】:log4net process id informationlog4net 进程 ID 信息
【发布时间】:2010-01-16 00:16:11
【问题描述】:

我正在尝试创建一个涉及多台机器上的多个进程的日志记录解决方案。我计划使用 UDPAppender 将所有日志消息发送到将管理它们的单个机器。我有几个关于模式字符串与模式布局的问题。

因为我需要知道该日志消息来自哪台机器和哪个进程,所以我也想将其包含在日志中。我为主机名找到了 %property{log4net:HostName},效果很好。但是,我在 PatternLayouts 中看不到任何进程 ID。当然,我确实在 PatternString 中看到了类似的东西。来自常见问题解答:

<appender name="LogFileAppender" type="log4net.Appender.FileAppender">
    <file type="log4net.Util.PatternString" value="log-file-[%processid].txt" />

    <layout type="log4net.Layout.PatternLayout" value="%date [%thread] %-5level %logger - %message%newline" />
</appender>

但我不确定是否或如何混合和匹配两者(或者即使这是这样做的规范方式)。

所以,我的问题是:

  1. PatternString 和 PatternLayout 有什么区别?为什么两者都有?

  2. 我在 PatternString 中看到 %processid,如何在 PatternLayout 中得到相同的值?这是我的测试布局:

    <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date [%thread] [%property{log4net:HostName}] %-5level %logger  - %message%newline" />
    </layout>
    
  3. 最后,为 UDP appender 使用 XML 布局是有意义的。看起来 XmlLayoutSchemaLog4j 已经将 HostNameProperty 添加到 XML 消息中。如果我不想将这个新的进程 ID(可能还有进程名称)添加到 XML 消息中,那么最好的方法是什么?我是否应该复制 src\Layouts\XmlLayoutSchemaLog4j.cs,对其进行修改,然后让 log4net 知道我创建了这个新布局(如 SampleLayoutsApp)?

感谢您的帮助

【问题讨论】:

    标签: log4net


    【解决方案1】:

    您可以将所需的任何属性添加到 GlobalContext。我使用这个上下文来存储进程 ID,如下所示:

    log4net.GlobalContext.Properties["pid"] = Process.GetCurrentProcess().Id;
    

    然后您使用常规模式从 appender 中引用此属性,如下所示:

    <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date %property{pid} %level %logger - %message%newline" />
    </layout>
    

    您可以根据需要添加任意数量的属性,但由于它具有全局性,因此它最适用于在应用程序执行期间不会更改的属性。

    【讨论】:

    • 尝试了所有 %pid、%processid 等等,但没有任何效果。您的解决方案有效。谢谢。
    【解决方案2】:

    您可以将 PatternString 输入到 PatternLayout 中:

        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern type="log4net.Util.PatternString" value="%processid" />
        </layout>
    

    【讨论】:

    • 记住要转义要从事件中提取的属性的百分比字符,例如 包括进程 ID 作为日志文件列之一
    • 恕我直言,此答案应标记为正确答案
    【解决方案3】:

    显然 PatternString 只能用于创建日志名称(即文件名等),而布局允许您格式化进入日志的实际消息。如果流程布局中没有内置的流程ID模式,那么您可以轻松添加它。这比创建整个布局要简单得多。

    这是怎么做的:

    创建您自己的自定义模式转换器(下面的示例尝试获取应用程序的名称,无论是 win 还是 web):

    internal sealed class ApplicationNamePatternConverter : PatternLayoutConverter 
    {
        /// <summary>
        /// Write the event application name to the output
        override protected void Convert(TextWriter writer, LoggingEvent loggingEvent)
        {
            string name = string.Empty;
            if( System.Web.HttpContext.Current != null )
            {
                string[] applicationPath = System.Web.HttpContext.Current.Request.ApplicationPath.Split('/');
                name = applicationPath[applicationPath.Length - 1];
            }
            else
            {
                if( System.Reflection.Assembly.GetEntryAssembly() != null )
                {
                    name = System.Reflection.Assembly.GetEntryAssembly().GetName().Name;
                }
            }
            writer.Write(name);
        }
    }
    

    将您的转换器的条目添加到 PatternLayout 类的注册表中

    static PatternLayout()
    {
    ...
      s_globalRulesRegistry.Add("ApplicationName", typeof(ApplicationNamePatternConverter));
    }
    

    现在您可以在 PatternLayout 值中使用%ApplicationName 来获取您需要的内容。

    我建议不要使用 XmlLayoutSchemaLog4j 布局,因为它非常重,如果经常使用会降低应用的性能。

    【讨论】:

      猜你喜欢
      • 2011-03-31
      • 2012-08-05
      • 1970-01-01
      • 2018-02-25
      • 1970-01-01
      • 2010-09-15
      • 1970-01-01
      • 2013-03-06
      • 1970-01-01
      相关资源
      最近更新 更多