c# - Nlog - Generating Header Section for a log file -


just got experimenting nlog, , occurs me able add header information top log file such as:

executable name file version release date windows user id etc...

after searching have been unable find in existing on-line documentation or code forums indicates type of functionality. possible? have included sort of information in log files, , have found useful on numerous occsions in past, when sourcing information on production issues @ customer sites. admittedly, functionality custom built solutions , not based on of current .net logging frameworks.

i'm not aware of way easily. having said that, of examples give available (or pretty available custom code) added each log message. is, each logged message can tagged executable name, file version, release date, windows user id, etc via layout , layoutrenderers.

this not same creating header @ top of log file, might not useful you.

on other hand, use technique mentioned in pat's answer in post associate multiple layout renderers same target. define layout contains fields want in header , set filter in filteringwrapper apply layout first message of session (or might use other technique added output file once).

using nlog.config file, here 1 way might achieve want. note have not tried this, don't know if config file valid or, if is, if generate results want.

<nlog xmlns="http://www.nlog-project.org/schemas/nlog.mono2.xsd"        xmlns:xsi="http://www.w3.org/2001/xmlschema-instance"        autoreload="true"        internalloglevel="warn"        internallogfile="nlog log.log"        >      <variable name="headerlayout" value="${processname} ${gdc:item=version} ${gdc:item=releasedate} ${windows-identity}" />      <variable name="normallayout" value="${longdate} ${logger} ${level} ${message} />       <targets async="true">          <target name="file" xsi:type="file" filename="log.log"                  layout="${normallayout}">          </target>           <target name="fileheader" xsi:type="file" filename="log.log"                  layout="${headerlayout}">          </target>           </targets>       <rules>          <logger name="headerlogger" minlevel="trace" writeto="fileheader" final="true" />                    <logger name="*" minlevel="trace" writeto="file" />      </rules>   </nlog>  

in code, startup logic might this:

public void main() {   addheadertologfile(); }  public void addheadertologfile() {   logger headerlogger = logmanager.getlogger("headerlogger");    //use globaldiagnosticcontext in 2.0, gdc in pre-2.0   globaldiagnosticcontext["releasedate"] = getreleasedate();       globaldiagnosticcontext["version"] = getfileversion();        globaldiagnosticcontext["someotherproperty"] = getsomeotherproperty();    headerlogger.info("message doesn't matter since not specified in layout");    //log file should have header defined headerlayout    //you remove global properties if not going log them in   //more messages. } 

the idea here put file version, release date, etc in gdc when program starts. log message "headerlogger" logger. message written log file using "headerlayout" since "headerlogger" associated "fileheader" target associated "headerlayout". fields defined in header layout written log file. subsequence log messages, since not use "headerlogger", use "root" (*) layout. go same file since both "file" , "fileheader" targets point same filename.

before started typing response wasn't sure how accomplish adding header log file. having typed this, think might pretty easy!

good luck!

[edit] might work change layout based on level. in first section have defined several variables, each of defines layout. in next section have defined several targets each of uses same file, filtered allow messages of specific level written. in final section define single rule send messages (hence "*" logger name) targets. since each target filtered level, "trace" target write "trace" messages etc. so, "trace" messages written using "trace" layout, "debug" messages written using "debug" layout, etc. since targets write same file, messages end in same file. haven't tried this, think work.

<variable name="tracelayout" value="this trace: ${longdate} ${level:uppercase=true} ${message}" />  <variable name="debuglayout" value="this debug: ${longdate} ${level:uppercase=true} ${message}" />  <variable name="infolayout" value="this info: ${longdate} ${level:uppercase=true} ${message}" />    <targets async="true">      <target name="fileastrace" xsi:type="filteringwrapper" condition="level==loglevel.trace">          <target xsi:type="file" filename="log.log" layout="${tracelayout}" />      </target>      <target name="fileasdebug" xsi:type="filteringwrapper" condition="level==loglevel.debug">          <target xsi:type="file" filename="log.log" layout="${debuglayout}" />      </target>      <target name="fileasinfo" xsi:type="filteringwrapper" condition="level==loglevel.info">          <target xsi:type="file" filename="log.log" layout="${infolayout}" />      </target>   </targets>   <rules>      <logger name="*" minlevel="trace" writeto="fileastrace, fileasdebug, fileasinfo" />  </rules>  

(note have included 3 levels here).

having shown how (if works, anyway) apply different layout based on level, seems sort of unusual use case. i'm not saying idea or bad idea, can't have seen done much. depending on how want final output look, have shown may or may not best way achieve it. maybe post examples of how want output look.

you might consider accepting original answer , making new question varying output layout per level can focus discussion in question on level/layout issue. if seems useful or not.

this works:

  <variable name="tracelayout" value="this trace - ${longdate} | ${logger} | ${level} | ${message}"/>   <variable name="debuglayout" value="this debug - ${longdate} | ${logger} | ${level} | ${message}"/>   <variable name="infolayout" value="this info - ${longdate} | ${logger} | ${level} | ${message}"/>   <variable name="warnlayout" value="this warn - ${longdate} | ${logger} | ${level} | ${message}"/>   <variable name="errorlayout" value="this error - ${longdate} | ${logger} | ${level} | ${message}"/>   <variable name="fatallayout" value="this fatal - ${longdate} | ${logger} | ${level} | ${message}"/>   <targets>     <target name="fileastrace" xsi:type="filteringwrapper" condition="level==loglevel.trace">       <target xsi:type="file" filename="xxx.log" layout="${tracelayout}" />     </target>     <target name="fileasdebug" xsi:type="filteringwrapper" condition="level==loglevel.debug">       <target xsi:type="file" filename="xxx.log" layout="${debuglayout}" />     </target>     <target name="fileasinfo" xsi:type="filteringwrapper" condition="level==loglevel.info">       <target xsi:type="file" filename="xxx.log" layout="${infolayout}" />     </target>     <target name="fileaswarn" xsi:type="filteringwrapper" condition="level==loglevel.warn">       <target xsi:type="file" filename="xxx.log" layout="${warnlayout}" />     </target>     <target name="fileaserror" xsi:type="filteringwrapper" condition="level==loglevel.error">       <target xsi:type="file" filename="xxx.log" layout="${errorlayout}" />     </target>     <target name="fileasfatal" xsi:type="filteringwrapper" condition="level==loglevel.fatal">       <target xsi:type="file" filename="xxx.log" layout="${fatallayout}" />     </target>   </targets>       <rules>       <logger name="*" minlevel="trace" writeto="fileastrace,fileasdebug,fileasinfo,fileaswarn,fileaserror,fileasfatal" />       <logger name="*" minlevel="info" writeto="dbg" />     </rules> 

i have set 1 layout each logging level, adding literal string @ beginning describes level of message (this show different format used each level). each layout associated filteringwrapper filters based on level of message , directs messages pass filter logged in output file. each filteringwrapper wrapping same output file, log messages logged same file.

here section of code used testing:

  logger.trace("trace msg");   logger.debug("debug msg");   logger.info("info msg");   logger.warn("warn msg");   logger.error("error msg");   logger.fatal("fatal msg"); 

and here output looks like:

this trace - 2010-11-22 13:20:00.4131 | nlogtest.form1 | trace | trace msg debug - 2010-11-22 13:20:00.4131 | nlogtest.form1 | debug | debug msg info - 2010-11-22 13:20:00.4131 | nlogtest.form1 | info | info msg warn - 2010-11-22 13:20:00.4131 | nlogtest.form1 | warn | warn msg error - 2010-11-22 13:20:00.4131 | nlogtest.form1 | error | error msg fatal - 2010-11-22 13:20:00.4131 | nlogtest.form1 | fatal | fatal msg 

apparently problem in earlier config information space between "writeto" values. guess nlog sensitive this. had "writeto=blah1, blah2, blah3". when changed "writeto=blah1,blah2,blah3" error went away. luck!


Comments

Popular posts from this blog

android - Spacing between the stars of a rating bar? -

html - Instapaper-like algorithm -

c# - How to execute a particular part of code asynchronously in a class -