How to name log4net output files with the assembly

2019-03-03 12:30发布

问题:

Is there any variable which I could use to name my log files?

<file value="${ALLUSERSPROFILE}\${AssemblyName}.log.xml" />

Where

  • ${ALLUSERSPROFILE} really works
  • ${AssemblyName} doesn't, it is something I made up just for illustration of what I want.

回答1:

Not by default.

This syntax is for expanding Windows Environment Variables. Whilst ALLUSERSPROFILE is a standard environment variable, AssemblyName is not. You would have to set AssemblyName yourself, which will not be easy\possible as a dynamic solution.



回答2:

As others said, there is no builtin placeholder for the assemblyname and a couple of ways to achieve it anyhow. Another one is to register your own handler/converter with the Log4Net framework.

Basically, you do the same that the log4net.Util.PatternString class does internally (and you might check the relevant source code for a more complete "example" than the fragements given below).

Example:

<file value="[ASSEMBLYNAME].log" type="MyExpressionHandler, MyAssembly"/>

Then the code:

enter code here

using log4net.Core;

public sealed class MyExpressionHandler : IOptionHandler
{
   private string m_str;

   public MyExpressionHandler(string str)
   {
      m_str = str;
   }

   public void ActivateOptions()
   {
   }

   public string Format()
   {
      return m_str.Replace("[ASSEMBLYNAME]", /* ... whatever ... */);
   }
}

Then provide a matching "Converter Class".

   internal class MyExpressionHandlerConverter : IConvertTo, IConvertFrom
    {
        public bool CanConvertTo(Type targetType)
        {
            return (typeof(string).IsAssignableFrom(targetType));
        }

        public object ConvertTo(object source, Type targetType)
        {
            MyExpression patternString = source as MyExpression;
            if (patternString != null && CanConvertTo(targetType))
            {
                return patternString.Format();
            }
            throw ConversionNotSupportedException.Create(targetType, source);
        }

        public bool CanConvertFrom(System.Type sourceType)
        {
            return (sourceType == typeof(string));
        }

        public object ConvertFrom(object source)
        {
            string str = source as string;
            if (str != null)
            {
                return new MyExpression(str);
            }
            throw ConversionNotSupportedException.Create(typeof(MyExpression), source);
        }
}

And finally make your converter known to the Log4Net framework:

ConverterRegistry.AddConverter(typeof(MyExpression), typeof(MyExpressionConverter));


回答3:

processname within NLog is akin to the PatternLayout within log4net; they are both part of the layout/rendering of the logs themselves.

If you want to use an environment variable within your application either force the creation as part of the install or create your own within your code; a C# example is here.

If that option does not suit your needs then you can dynamically set the path as shown here.



回答4:

You could write your own pattern layout converter. I posted a sample here and I think it is easy to modify that so that it writes the assembly name...



回答5:

Another option is, to define a global property at initialization time:

GlobalContext.Properties["pid"] = System.Diagnostics.Process.GetCurrentProcess().Id;
this.logger = log4net.GetLogger("LoggerSample");

In your configuration file, you can use the "pid" property like this:

<param name="ConversionPattern" value="%d;%property{log4net:HostName};%property{pid};%t;%p;%c;%M;%L;%m%n" />

Hope, I was clear!

br++mabra