我正在尝试创建一个涉及多台计算机上多个进程的日志记录解决方案。我计划使用UDPAppender将所有日志消息发送到管理它们的单个机器。我有一些关于patterntrings和patternlayouts的问题。
因为我需要知道哪个机器以及该日志消息来自哪个进程,所以我也希望将其包含在日志中。我找到了主机名的%property {log4net:HostName},效果很好。但是,我在PatternLayouts中没有看到任何进程ID。当然,我在PatternString中看到类似的东西。来自FAQ:
<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>
但我不确定是否或如何混合和匹配两者(或者即使这是规范的方式)。
所以,我的问题是:
PatternString和PatternLayout有什么区别?为什么两者都有?
我在PatternString中看到%processid,我如何在PatternLayout中获得相同的内容?这是我的测试布局:
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] [%property{log4net:HostName}] %-5level %logger - %message%newline" />
</layout>
最后,将UDP布局用于UDP appender是有意义的。看起来XmlLayoutSchemaLog4j已经将HostNameProperty添加到XML消息中。如果我不想将这个新的进程ID(可能是进程名称)添加到XML消息中,那么最好的方法是什么?我应该只复制src \ Layouts \ XmlLayoutSchemaLog4j.cs,修改它,让log4net知道我创建了这个新的布局(比如SampleLayoutsApp)吗?
感谢您的帮助
答案 0 :(得分:47)
您可以将所需的任何属性添加到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>
您可以根据需要添加任意数量的属性,但由于它具有全局特性,因此最适合在应用程序执行期间不会更改的属性。
答案 1 :(得分:16)
您可以将PatternString提供给PatternLayout:
<layout type="log4net.Layout.PatternLayout">
<conversionPattern type="log4net.Util.PatternString" value="%processid" />
</layout>
答案 2 :(得分: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
布局,因为它非常繁重,如果频繁使用,可能会降低应用的性能。