log4net没有为我的登录名做正确的PatternString
替换。我希望我的日志是
日志\ YYYYMMDD \ MSMQcore_ [用户名]的.log
当我使用%username
属性时,我在路径中获取域,这会在其中添加另一个文件夹间接。我只想要用户名。
日志\ YYYYMMDD \ MSMQcore_ [域] \ [用户名]的.log
任何人都有一个在appender的文件名中插入“用户名”的例子?我尝试了很多东西,我还在摸不着头脑。
<appender name="core_Appender" type="log4net.Appender.RollingFileAppender" >
<!-- <file type="log4net.Util.PatternString" value="Logs/%date{yyyyMMdd}/MSMQcore_%identity.log" /> -->
<!-- <file type="log4net.Util.PatternString" value="Logs/%date{yyyyMMdd}/MSMQcore_%property{user}.log" /> -->
<file type="log4net.Util.PatternString" value="Logs/%date{yyyyMMdd}/MSMQcore_%username.log" />
</appender>
答案 0 :(得分:9)
使用环境变量模式对我有用:
<file type="log4net.Util.PatternString" value="Logs\\%env{USERNAME}.txt" />
更新:如果USERNAME环境变量不是选项,则可以替代子类化PatternString。这是一个简单的实现:
public class MyPatternString : PatternString
{
public MyPatternString()
{
AddConverter("usernameonly", typeof(UserNameOnlyConverter));
}
}
public class UserNameOnlyConverter : PatternConverter
{
override protected void Convert(TextWriter writer, object state)
{
var windowsIdentity = WindowsIdentity.GetCurrent();
if (windowsIdentity != null && windowsIdentity.Name != null)
{
var name = windowsIdentity.Name.Split('\\')[1];
writer.Write(name);
}
}
}
新设置如下所示:
<file type="MyPatternString" value="Logs\\%usernameonly.txt" />
更新2:以回答%identity和%property {user}无效的原因:
%identity pattern选取当前线程上的identity属性。这个属性在我的测试中为null,可能是这样,直到为运行的线程分配一个特定的Windows标识。这在appender的上下文中不起作用,因为你不知道哪个线程会执行实际的附加。
%属性模式从GlobalContext和ThreadContext类中获取属性。默认情况下,只在GlobalContext中注册 log4net:HostName (LoggingEvent.HostNameProperty)。因此,除非您在这些上下文中主动注册属性,否则不能将它们与%属性模式一起使用。同样,ThreadContext在appender的上下文中是无用的,因为你无法知道哪个线程将执行追加。
也就是说,在应用程序启动例程中的某个地方注册GlobalContext.Properties集合中名为 username 的属性,将使%property {username}能够按预期工作。
答案 1 :(得分:3)
彼得的回答PatternConverter
:
public class ConfigurationSettingsConverter : PatternConverter
{
protected override void Convert(TextWriter writer, object state)
{
// use Option as a key to get a configuration value...
if (Option != null)
writer.Write(ConfigUtils.Setting[Option]);
}
}
并在ActivateOptions
的子类的PatternString
覆盖中添加此转换器:
public class ConfigurationSettingsPatternString : PatternString
{
public ConfigurationSettingsPatternString()
{}
public ConfigurationSettingsPatternString(string pattern): base(pattern)
{}
public override void ActivateOptions()
{
AddConverter("cs", typeof(ConfigurationSettingsConverter));
base.ActivateOptions();
}
}
我最初尝试在构造函数中执行此操作,因为Peter回答,但转换器未从模式字符串的底层调用返回以解析源字符串。在配置 log4net 之前,我还必须在代码路径中的任何位置注册一个类型转换器(不要与PatternConverter
混淆):
ConverterRegistry.AddConverter(
// type we want to convert to (from string)...
typeof(ConfigurationSettingsPatternString),
// the type of the type converter that will do the conversion...
typeof(ConfigurationSettingsPatternStringConverter));
不执行此操作可防止 log4net 转换FileAppender
的文件节点中的值属性(即一个字符串)到ConfigurationSettingsPatternString
。例如,在此配置片段中,
<file
type="Some.Name.Space.ConfigurationSettingsPatternString, Some.Assembly"
value="some\path\MyLog.%cs{SomeKey}.log" />
%cs.{SomeKey}
不会展开, log4net 会引发异常。这是类型转换器的代码:
public class ConfigurationSettingsPatternStringConverter : IConvertTo, IConvertFrom
{
public bool CanConvertFrom(Type sourceType)
{
return sourceType == typeof(string);
}
public bool CanConvertTo(Type targetType)
{
return typeof(string).IsAssignableFrom(targetType);
}
public object ConvertFrom(object source)
{
var pattern = source as string;
if (pattern == null)
throw ConversionNotSupportedException.Create(typeof(ConfigurationSettingsPatternString), source);
return new ConfigurationSettingsPatternString(pattern);
}
public object ConvertTo(object source, Type targetType)
{
var pattern = source as PatternString;
if (pattern == null || !CanConvertTo(targetType))
throw ConversionNotSupportedException.Create(targetType, source);
return pattern.Format();
}
}
这适用于托管在同一可执行文件中的Windows多个服务(例如,您可以添加%serviceName 模式作为文件名以分隔服务的日志。
答案 2 :(得分:1)
使用“%username”对我有用;
<parameter>
<parameterName value="@identity" />
<dbType value="String" />
<size value="255" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%username" />
</layout>
</parameter>
但是我再次处于标准WinForms应用程序的上下文中,而不是ASP.NET应用程序。不确定这是否是您正在寻找的。 p>
答案 3 :(得分:1)
Kit的解决方案只有一项改进: 使用属性
[TypeConverter("namespace.ConfigurationSettingsPatternStringConverter")]
public class ConfigurationSettingsPatternString : PatternString
{
致电
ConverterRegistry.AddConverter(
// type we want to convert to (from string)...
typeof(ConfigurationSettingsPatternString),
// the type of the type converter that will do the conversion...
typeof(ConfigurationSettingsPatternStringConverter));
不再需要。
答案 4 :(得分:0)
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="Running on ${COMPUTERNAME} / ${USERNAME} %newline %logger %date%newline Thread ID=[%thread]%newline %-5level - %message%newline" />
</layout>
这对我有用。