NLog LayoutRenderer for assembly version


This post will be short and is inspired by Robert’s comment under my previous post (Thanks for it!). Robert pointed (and I completely agree) that it might be useful to have application assemblies versions listed in the log output.

So here comes AssemblyVersionLayoutRenderer:

[LayoutRenderer("asmver")]
[ThreadAgnostic]
public class AssemblyVersionLayoutRenderer : LayoutRenderer
{
    /// <summary>
    /// Specifies the assembly name for which the version will be displayed.
    /// By default the calling assembly is used.
    /// </summary>
    public String AssemblyName { get; set; }
    
    private String asmver;
    private String GetAssemblyVersion() {
        if (asmver != null) {
            return asmver;
        }
    
        InternalLogger.Debug("Assembly name '{0}' not yet loaded: ", AssemblyName);
        if (!String.IsNullOrEmpty(AssemblyName)) {
            // try to get assembly based on its name
            asmver = AppDomain.CurrentDomain.GetAssemblies()
                                  .Where(a => String.Equals(a.GetName().Name, AssemblyName, StringComparison.InvariantCultureIgnoreCase))
                                  .Select(a => a.GetName().Name + " v" + a.GetName().Version).FirstOrDefault();
            return asmver == null ? String.Format("<{0} not loaded>", AssemblyName) : asmver;
        }
        // get entry assembly
        var entry = Assembly.GetEntryAssembly();
        asmver = entry.GetName().Name + " v" + entry.GetName().Version;
        return asmver;
    }

    /// <summary>
    /// Renders the current trace activity ID.
    /// </summary>
    /// <param name="builder">The <see cref="StringBuilder"/> to append the rendered data to.</param>
    /// <param name="logEvent">Logging event.</param>
    protected override void Append(StringBuilder builder, LogEventInfo logEvent)
    {
        builder.Append(GetAssemblyVersion());
    }
}

To use it, simply add ${asmver} to your layout configuration. As you can read from the above snippet you may specify which assembly version should be added to the output (by default entry assembly is used) and it’s completely legal to have more than one AssemblyVersionLayoutRender in your layout. Example configuration:

  <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        internalLogToConsole="true" internalLogLevel="Debug" throwExceptions="true">
    <extensions>
      <add prefix="lld" assembly="LowLevelDesign.NLog.Ext" />
    </extensions>
    <targets>
      <target name="console" xsi:type="ColoredConsole" layout="${longdate}|${lld.asmver:assemblyname=NLog}|${lld.asmver}|${logger}|${uppercase:${level}}|${message}${onexception:|Exception occurred\:${exception:format=tostring}}" />
    </targets>
    <rules>
      <logger name="TestLogger" minlevel="Debug" writeTo="console" />
      <logger name="TestSource" minlevel="Debug" writeTo="console" />
    </rules>
  </nlog>

will produce the following output for my TestNLog application:

2012-11-22 07:18:13.7340|NLog v2.0.0.0|TestNLog v0.0.0.0|TestLogger|INFO|Start
In the middle of tracing
2012-11-22 07:18:13.8200|NLog v2.0.0.0|TestNLog v0.0.0.0|TestLogger|ERROR|Error occured|Exception occurred:System.Exception: TestException
2012-11-22 07:18:13.8360|NLog v2.0.0.0|TestNLog v0.0.0.0|TestLogger|INFO|End

I updated the NLog project on my samples website so if you would like to use the new layout renderer feel free to download it. And as usual if you have any suggestions or ideas I will be more than happy to see them in comments:)

NLog LayoutRenderer for assembly version

4 thoughts on “NLog LayoutRenderer for assembly version

  1. Robert says:

    Hi Sebastian,

    thank you for posting a layout renderer which logs the assembly versions. It looks good and does it’s job, but I think it can be improved. If the programmer adds or removes assemblies, he always has to update the config file. I have seen somewhere on the internet in a different context a code snippet which uses reflection to get all the referenced assemblies. This can be used in the Append method, i.e.
    StackFrame frame = logEvent.UserStackFrame;
    AssemblyName[] assemblies = frame.GetMethod().DeclaringType.Assembly.GetReferencedAssemblies();
    Now a for each loop can be used to get the name and version of each assembly and append it to the builder. What do you think?

    Regards,
    Robert

    1. Hi Robert,

      That might be a very interesting improvement if you are interested in all the loaded libraries (it will also list framework libraries which might be useful in some situations). I was thinking more about logs from a particular library. As you pasted the code snippet people can easily change the presented layout renderer to log all the referenced assemblies.

      Thanks again for your comments and ideas:)
      Sebastian

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s