Is there a way to add the assemb开发者_运维技巧ly version of assembly that is emiting the logging event?
I don't think there is anything built-in that will do this, so you will probably need to create your own custom PatternConverter and PatternLayout (which is very easy)
The biggest problem is speed, since this will require log4net to generate the caller information and (in their own words)
WARNING Generating the caller class information is slow. Thus, its use should be avoided unless execution speed is not an issue.
If speed is not an issue, then something like this should work.
public class AssemblyVersionPatternConverter : log4net.Util.PatternConverter
{
protected override void Convert(TextWriter writer, object state)
{
var le = state as log4net.Core.LoggingEvent;
if (le != null)
writer.Write(GetAssemblyVersion(le.LocationInformation.ClassName));
}
}
public class AssemblyVersionPatternLayout : log4net.Layout.PatternLayout
{
public AssemblyVersionPatternLayout()
{
AddConverter( new ConverterInfo
{
Name = "AssemblyVersion",
Type = typeof(AssemblyVersionPatternConverter)
});
}
}
Apart from writing the GetAssemblyVersion method, that is all it takes to implement your own customer PatternConverter and PatternLayout.
You then have to change your log4net configuration file to tell it to use your custom routines.
eg if you have something like
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%5level %message%newline" />
</layout>
you change it to something like
<layout type="MyNameSpace.AssemblyVersionPatternLayout, MyDllname">
<conversionPattern value="%5level %AssemblyVersion %message%newline" />
</layout>
The GetAssemblyVersion method, could be something like the following
private string GetAssemblyVersion(string className)
{
Type type = Type.GetType(className);
System.Reflection.Assembly assembly ;
if (type != null)
assembly = type.Assembly ;
else
assembly = AppDomain.CurrentDomain.GetAssemblies()
.FirstOrDefault(a => a.GetType(className) != null);
if (assembly == null)
return String.Empty;
return assembly.FullName.Split(',')[1].Replace("Version=", "");
}
Note, it is not recommended to use assembly.GetName().Version as this can throw a SecurityException if the account has very local privileges.
Check this out: Log Event Context http://www.beefycode.com/post/Log4Net-Tutorial-pt-6-Log-Event-Context.aspx
At start set ThreadContext with Properties you need:
class Program
{
private static log4net.ILog Log = log4net.LogManager.GetLogger( System.Reflection.MethodBase.GetCurrentMethod().DeclaringType );
static void Main( string[] args )
{
log4net.Config.XmlConfigurator.Configure();
log4net.ThreadContext.Properties["myContext"] = "Logging from Main";
log4net.ThreadContext.Properties["AssemblyVersion"] = GetType().Assembly.GetName().Version;
Log.Info( "this is an info message" );
Console.ReadLine();
}
}
}
Use this Properties in your appender conversionPattern:
<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%logger (%property{myContext}) (%property{AssemblyVersion}) [%level]- %message%newline" />
</layout>
</appender>
精彩评论