Tuesday, July 11, 2017

Bizagi logging: The Right Way!

In many projects one of the repetitive questions is how to produce effective logs in our processes, and how to use them in production, unfortunately the answer is: "you can use logs in development, but you need to switch them off in production or the performance will be hurt".

There are several logs in the market that we can use to include in our rules, so I implemented a wrapper of the Log4Net that you can found here: https://github.com/crossleyjuan/bizagilogger.

The good thing about this is that you can use logs in production environments without having to worry (too much) about the impact in performance, it's just a matter of configuring this right and get the best based on configuration. The bad, this is something you need to configure in the config files and not from the Bizagi Management Console, therefore turning off the traces from Bizagi console will not have any effect.

How to use the BizagiLogger

To use Log4net in your projects you will need 3 elements:
  • The Component Library: BizagiLogger
  • Configure the .config files
  • Create a Library Rule to wrap all the logs (Recommended)

Component Library: Bizagi Logger

Feel free to download the required dlls from here: https://github.com/crossleyjuan/bizagilogger/releases/tag/1.0 or download the source code and compile it yourself. This dll depends on log4net.dll, a great Apache Project that makes this possible.

Register both dlls as Component Libraries in Bizagi

Using the logger in your rules

Syntax:
 var log = Logger.getLogger(emitter);  
 log.Info(ctx, text);  
 log.Error(ctx, text);  
 log.Warn(ctx, text);  
 log.Debug(ctx, text);  

  • The emitter is a very useful filter, as you can collapse the same messages related to the same emitter, my suggestion is to use the Case Number
  • ctx is a tag variable called NDC in Log4Net, this helps to search for an additional parameter. for example you can use the name of the process

Example

 var sEmitter = Me.Case.CaseNumber;  
 var log = Logger.getLogger(sEmitter);  
 log.Info("Process A", sLogText);  

Configuration

To configure the way the logger works you can use the appenders as explained in the log4net documentation, to make this easier here's an example that could be useful in a production environment:
  • Add the configuration section:

    To be able to use the log4net options you need to let .net known that you will add some configuration elements for log4net, to do this you need to add this to your config files in the "configSections" section:

      <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />  
    

    full section:

      <configSections>  
       <section name="bizAgiComponentLibrary" type="BizAgi.ComponentLibrary.CComponentLibrarySectionHandler,BizAgi.ComponentLibrary"/>  
       <section name="bizAgiWFESTouchPoints" type="BizAgi.WFES.TP.CTouchPointsSectionHandler,BizAgi.WFES"/>  
           <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />  
       <!-- Uncomment for federate authentication -->  
       <!--<section name="microsoft.identityModel" type="Microsoft.IdentityModel.Configuration.MicrosoftIdentityModelSection, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />-->  
      </configSections>  
    

Now you can add the appenders in any part of the <configuration> tag, you can use the following as starting point

  <log4net>  
           <appender name="BufferingForwarder" type="log4net.Appender.BufferingForwardingAppender">  
                <bufferSize value="512" />  
                <lossy value="false" />  
                <Fix value="268" />  
                <appender-ref ref="RollingFile" />  
                <!-- or any additional appenders or other forwarders -->  
           </appender>  
           <appender name="RollingFile" type="log4net.Appender.RollingFileAppender">  
                <file type="log4net.Util.PatternString" value="c:\temp\Logs\WebApp-%date{yyyy-MM-dd}.log" />  
                <appendToFile value="false"/>  
                <rollingStyle value="Composite"/>  
                <maxSizeRollBackups value="-1"/>  
                <maximumFileSize value="2MB"/>  
                <staticLogFileName value="true"/>  
                <datePattern value="yyyy-MM-dd"/>  
                <preserveLogFileNameExtension value="true"/>  
                <countDirection value="1"/>  
                <layout type="log4net.Layout.PatternLayout">  
                     <conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />  
                </layout>  
           </appender>   

       <root>  
            <appender-ref ref="BufferingForwarder" />  
       </root>  
  </log4net>  

These appenders have a very good performance so you can use as many traces as you want in production with almost no impact in your performance, the reason is that the BufferingForwarder keeps chunks of information in memory and writes them in an asynchronous way to the RollingFile appender, this stores the file creating a new one every day or of the file reaches the maximum defined in the "maximumFileSize> tag.

More information of the available appenders here: https://logging.apache.org/log4net/log4net-1.2.13/release/sdk/log4net.Appender.html

do you have questions? comments? use the comment below if you need additional information