Log4J - disable logging for specific class - multiple appenders - log4j

I setup Log4J to use multiple appenders. This is working fine. However, I want to set the default log level to one appender to DEBUG, and restrict logging for a specific class to INFO and above. What I came up with works for the FA appender, but not the DCSLOAD and DCSPROC appenders. What am I doing wrong?
# Set root logger level to DEBUG and its only appender to A1.
log4j.rootLogger = CA, FA
# CA is set to be a ConsoleAppender.
log4j.appender.CA=org.apache.log4j.ConsoleAppender
# CA uses PatternLayout.
log4j.appender.CA.layout=org.apache.log4j.PatternLayout
log4j.appender.CA.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5p %c{3} %x - %m%n
# FA uses PatternLayout.
log4j.appender.FA=org.apache.log4j.RollingFileAppender
log4j.appender.FA.File=${catalina.base}/logs/dcs.log
log4j.appender.FA.layout=org.apache.log4j.PatternLayout
log4j.appender.FA.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5p %c{3} %x - %m%n
log4j.appender.FA.MaxFileSize=1024KB
log4j.appender.FA.MaxBackupIndex=100
# DCSPROC, DCSLOAD and DCSDB are all File Appenders to different targets
log4j.appender.DCSPROC=org.apache.log4j.RollingFileAppender
log4j.appender.DCSPROC.File=${catalina.base}/logs/dcs_process.log
log4j.appender.DCSPROC.layout=org.apache.log4j.PatternLayout
log4j.appender.DCSPROC.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5p %c{3} %x - %m%n
log4j.appender.DCSPROC.MaxFileSize=1024KB
log4j.appender.DCSPROC.MaxBackupIndex=100
log4j.appender.DCSLOAD=org.apache.log4j.RollingFileAppender
log4j.appender.DCSLOAD.File=${catalina.base}/logs/dcs_business.log
log4j.appender.DCSLOAD.layout=org.apache.log4j.PatternLayout
log4j.appender.DCSLOAD.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5p %c{3} %x - %m%n
log4j.appender.DCSLOAD.MaxFileSize=1024KB
log4j.appender.DCSLOAD.MaxBackupIndex=100
log4j.appender.DCSDB=org.apache.log4j.RollingFileAppender
log4j.appender.DCSDB.File=${catalina.base}/logs/dcs_database.log
log4j.appender.DCSDB.layout=org.apache.log4j.PatternLayout
log4j.appender.DCSDB.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5p %c{3} %x - %m%n
log4j.appender.DCSDB.MaxFileSize=1024KB
log4j.appender.DCSDB.MaxBackupIndex=100
# set default logging level for outputs
log4j.logger.CA = DEBUG
log4j.logger.FA = DEBUG
log4j.logger.DCSDB = DEBUG, DCSDB
log4j.logger.DCSPROC = DEBUG, DCSPROC
log4j.logger.DCSLOAD = DEBUG, DCSLOAD
log4j.additivity.DCSDB=false
log4j.additivity.DCSPROC=false
log4j.additivity.DCSLOAD=false
#This works
log4j.logger.LoginServlet=INFO, FA
#These two do not
log4j.logger.LoginServlet=INFO, DCSLOAD
log4j.logger.LoginServlet=INFO, DCSPROC

change theseļ¼š
log4j.logger.DCSDB = DEBUG, DCSDB
log4j.logger.DCSPROC = DEBUG, DCSPROC
log4j.logger.DCSLOAD = DEBUG, DCSLOAD
to
log4j.logger.DCSDB = DEBUG
log4j.logger.DCSPROC = DEBUG
log4j.logger.DCSLOAD = DEBUG

Related

Disable python's root logger with ini fileconfig

I want two loggers, one for prod and one for dev. I found that it's mandatory to declare a root (because if I delete the root logger, python's raise me an error).
Here is my test.ini file:
[loggers]
keys=root,dev,prod
[handlers]
keys=handlerRoot,handlerDev,handlerProd
[formatters]
keys=formatterRoot,formatterDev,formatterProd
# Root
[logger_root]
level=WARNING
handlers=handlerRoot
[handler_handlerRoot]
class=StreamHandler
level=WARNING
formatter=formatterRoot
args=(sys.stdout,)
[formatter_formatterRoot]
format=
%(asctime)s - %(levelname)s - ROOOOT - %(message)s
datefmt=%A %d %B %Y at %H:%M:%S
# Prod
[logger_prod]
level=WARNING
handlers=handlerProd
qualname=prod
[handler_handlerProd]
class=StreamHandler
level=WARNING
formatter=formatterProd
args=(sys.stdout,)
[formatter_formatterProd]
format=
%(asctime)s - %(levelname)s - %(message)s
datefmt=%A %d %B %Y at %H:%M:%S
# Dev
[logger_dev]
level=DEBUG
handlers=handlerDev
qualname=dev
[handler_handlerDev]
class=StreamHandler
level=DEBUG
formatter=formatterDev
args=(sys.stdout,)
[formatter_formatterDev]
format=
%(asctime)s - %(name)s - %(levelname)s - %(module)s - %(filename)s
%(message)s
datefmt=%d-%m-%Y %H:%M:%S
And my main.py file:
import logging
from logging.config import fileConfig
fileConfig('test.ini')
loggerDev = logging.getLogger("dev")
loggerDev.warning("Not supposed to also log in root.")
But my console output this:
21-04-2020 23:05:41 - dev - WARNING - main - main.py
Not supposed to also log in root.
Tuesday 21 April 2020 at 23:05:41 - WARNING - ROOOOT - Not supposed to also log in root.
And I don't want the latest line to be printed. It seems that the loggerDev is a child of the root logger.
How to solve this?
Solution founded: set propagate to false.
In .ini file you can do it by adding this line in the [logger_myLogger] section:
propagate=0

log4net log file get log with a lot of other information which we dint write

I am using log4net feature in my windows based .net application, which interact with different 3rd party com dll. so i could see the log file get log with a lot of other information which we dint write for logging.
so i just want know if any configuration i missed so that it could log only those information which we intent to log.
details
application : c# windows based 3.5 .net framework log4net version: 1.2
sample
2013-11-26 05:16:11,481 [15] INFO - TKS.DataDriver.DataDriver - LoadWorkBook : start LoadWorkBook operation
2013-11-26 05:16:13,653 [15] INFO - TKS.DataDriver.MsExcel.Common - inside method IsFileLocked
2013-11-26 05:16:19,028 [15] INFO - TKS.DataDriver.DataDriver - MergeTestCaseEntities : Merging all Test Case Entities.
2013-11-26 05:16:19,028 [15] INFO - TKS.DataDriver.DataDriver - LoadWorkBook : monitoringFlag: False MonitorQTPstatusOnOff: ON
2013-11-26 05:16:19,028 [15] INFO - TKS.DataDriver.DataDriver - LoadWorkBook : Asyncronus call for status check of the QTP.
2013-11-26 05:16:19,028 [15] INFO - TKS.DataDriver.DataDriver - DataLoadTestSet : DataLoad method call completed and result is : True
2013-11-26 05:16:19,028 [15] INFO - LogCatReplay - CProxy_IQTFuncLibMgrEvents::FireHelper Start. DispID = 4 Func=CProxy_IQTFuncLibMgrEvents<class CQTFuncLibMgr>::FireHelper File=e:\ft\qtp\win32_release\11.52.467.0_clean\qtp\backend\executionengine\app\qtexecutionengine\qtfunclibmgrcp.h Line=16 ThreadID=4636
2013-11-26 05:16:19,028 [15] INFO - LogCatReplay - UnitExecutionEngine: CProxy_IQTASUnitExecutionEngineEvents::FireHelper Start. DispID = 7 Func=CProxy_IQTASUnitExecutionEngineEvents<class CQTASUnitExecutionEngine>::FireHelper File=e:\ft\qtp\win32_release\11.52.467.0_clean\qtp\backend\executionengine\app\qtexecutionengine\qtasunitexecutionenginecp.h Line=15 ThreadID=4636
2013-11-26 05:16:19,028 [15] INFO - LogCatReplay - UnitExecutionEngine: CProxy_IQTASUnitExecutionEngineEvents::FireHelper End Func=CProxy_IQTASUnitExecutionEngineEvents<class CQTASUnitExecutionEngine>::FireHelper File=e:\ft\qtp\win32_release\11.52.467.0_clean\qtp\backend\executionengine\app\qtexecutionengine\qtasunitexecutionenginecp.h Line=39 ThreadID=4636
2013-11-26 05:16:19,043 [16] INFO - TKS.DataDriver.DataDriver - MonitorQTPstatus kick ON Now.
2013-11-26 05:16:19,059 [1] INFO - HP.QTP.QEEE.ExecutionMediator.Execution.ExecutionStatusResolver - Instance 0: Runtime status is updated to Done(micGeneral)
2013-11-26 05:16:19,059 [15] INFO - LogCatReplay - CProxy_IQTFuncLibMgrEvents::FireHelper Start. DispID = 5 Func=CProxy_IQTFuncLibMgrEvents<class CQTFuncLibMgr>::FireHelper File=e:\ft\qtp\win32_release\11.52.467.0_clean\qtp\backend\executionengine\app\qtexecutionengine\qtfunclibmgrcp.h Line=16 ThreadID=4636
2013-11-26 05:16:19,059 [15] INFO - LogCatReplay - UnitExecutionEngine: CProxy_IQTASUnitExecutionEngineEvents::FireHelper Start. DispID = 8 Func=CProxy_IQTASUnitExecutionEngineEvents<class CQTASUnitExecutionEngine>::FireHelper File=e:\ft\qtp\win32_release\11.52.467.0_clean\qtp\backend\executionengine\app\qtexecutionengine\qtasunitexecutionenginecp.h Line=15 ThreadID=4636
2013-11-26 05:16:19,059 [15] INFO - LogCatReplay - cCProxy_IQTTestExecutionEngineEvents::FireHelper Start. DispID = 16 Func=CProxy_IQTTestExecutionEngineEvents<class CQTTestExecutionEngine>::FireHelper File=e:\ft\qtp\win32_release\11.52.467.0_clean\qtp\backend\executionengine\app\qtexecutionengine\qttestexecutionenginecp.h Line=15 ThreadID=4636
2013-11-26 05:16:19,059 [1] INFO - LogCatReplay - ExecutionSite: CProxy_IQTTestExecutionEngineEvents::FireHelper Start. DispID = 16 Func=CProxy_IQTTestExecutionEngineEvents<class CQTTestExecutionSite>::FireHelper File=e:\ft\qtp\win32_release\11.52.467.0_clean\qtp\backend\executionengine\app\qtexecutionsite\qttestexecutionsitecp.h Line=17 ThreadID=880
2013-11-26 05:16:19,059 [1] INFO - LogCatReplay - ExecutionSite: CProxy_IQTTestExecutionEngineEvents::FireHelper End Func=CProxy_IQTTestExecutionEngineEvents<class CQTTestExecutionSite>::FireHelper File=e:\ft\qtp\win32_release\11.52.467.0_clean\qtp\backend\executionengine\app\qtexecutionsite\qttestexecutionsitecp.h Line=41 ThreadID=880
2013-11-26 05:16:19,059 [15] INFO - LogCatReplay - ExecutionEngine: CProxy_IQTTestExecutionEngineEvents::FireHelper End Func=CProxy_IQTTestExecutionEngineEvents<class CQTTestExecutionEngine>::FireHelper File=e:\ft\qtp\win32_release\11.52.467.0_clean\qtp\backend\executionengine\app\qtexecutionengine\qttestexecutionenginecp.h Line=52 ThreadID=4636
If you are using the standard method of declaring the logger, eg
internal static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
then in your log4net configuration file, you can disable logging except for your own code based on the namespaces of your classes.
For example, if you only wanted to log the lines from TKS.DataDriver, then your config file could contain something like
<root>
<level value="OFF" />
<appender-ref ref="RollingFileAppender" />
</root>
<logger name="TKS.DataDriver">
<level value="INFO" />
</logger>
You can add other namespaces if you need them or just use "TKS" etc.

log4net watching function does not work if create appender in code?

I want to set a Rolling Appender dynamic in code rather than in config file. So I have a function that will return log4net.ILog
<Assembly: log4net.config.XmlConfigurator(ConfigFile:="Log4Net.config", Watch:=True)>
Public Function genLogXMLCfg(cls As Object) As log4net.ILog
Dim clsName As String = cls.ToString()
Dim rollAppen As New RollingFileAppender()
rollAppen.Name = clsName + "Appender"
rollAppen.RollingStyle = RollingFileAppender.RollingMode.Composite
rollAppen.File = "logs\\"
rollAppen.DatePattern = "'" + clsName.ToLower() + "'" + "yyyyMMdd'.log'"
rollAppen.LockingModel = New log4net.Appender.FileAppender.MinimalLock()
rollAppen.AppendToFile = True
rollAppen.StaticLogFileName = False
rollAppen.MaxSizeRollBackups = 3
rollAppen.MaximumFileSize = "100KB"
Dim layout As New log4net.Layout.PatternLayout("%d [%t] %-5p %c (line:%L) - %m%n")
rollAppen.Layout = layout
layout.ActivateOptions()
rollAppen.ActivateOptions()
Dim logg As ILog = LogManager.GetLogger(clsName)
Dim l As log4net.Repository.Hierarchy.Logger = DirectCast(logg.Logger, log4net.Repository.Hierarchy.Logger)
l.AddAppender(rollAppen)
l.Repository.Configured = True
Return logg
End Function
Because I want to dynamic generate rolling appender from code but at the same time I want to set the logger from config file, so I have following config file call (Log4Net.config)
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
</configSections>
<appSettings>
<add key="log4net.Config" value="log4net.config"/>
<add key="log4net.Config.Watch" value="True"/>
</appSettings>
<log4net>
<logger name="ConsoleApplication1.LogTest2">
<level value="WARN" />
</logger>
<logger name="ConsoleApplication1.testCls">
<level value="INFO" />
</logger>
</log4net>
Now I test the function by following code:
Dim cls As LogTest2 = New LogTest2()
Dim tCls As testCls = New testCls()
Dim l4n As log4net.ILog
Dim l4n2 As log4net.ILog
l4n = cls.genLogXMLCfg(tCls.GetType().ToString())
l4n2 = cls.genLogXMLCfg(cls.GetType().ToString())
l4n.Debug("... Here is a debug log -2.")
l4n.Info("... and an Info log.")
System.Threading.Thread.Sleep(3000)
l4n.Warn("... and a warning 1.")
l4n.Debug("... Here is a debug log -1.")
l4n.Warn("... and a warning 2.")
l4n.Warn("... and a warning 3.")
l4n2.Warn("l4n2 cls and a warning -1.")
l4n.Warn("... and a warning 4.")
l4n.Warn("... and a warning 5.")
Console.Write(" ... ... ... ")
System.Threading.Thread.Sleep(3000)
l4n.Warn("... and a warning 6.")
l4n.Debug("... Here is a debug log 1.")
l4n.Warn("... and a warning 7.")
l4n2.Debug("l4n2 cls Here is a debug log.")
l4n2.Info("l4n2 cls and an Info log.")
l4n.Fatal("... and a fatal .")
l4n2.Fatal("l4n2 and a fatal .")
l4n.Debug("... Here is a debug log 2.")
l4n.Warn("... and a warning 8.")
l4n.Error("... and an error.")
l4n.Debug("... Here is a debug log 3.")
l4n.Fatal("... and a fatal .")
l4n.Debug("... Here is a debug log 4.")
l4n2.Debug("l4n2 cls Here is a debug log.")
l4n2.Info("l4n2 cls and an Info log.")
l4n2.Warn("l4n2 cls and a warning.")
l4n2.Error("l4n2 cls and an error.")
l4n2.Fatal("l4n2 cls and a fatal .")
After that, two log file generated in logs folder call
**consoleapplication1.logtest220130610.log** and **consoleapplication1.testcls20130610.log**
The content are:
**consoleapplication1.logtest220130610.log**
2013-06-10 18:41:38,802 [9] WARN ConsoleApplication1.LogTest2 (line:182) - l4n2 cls and a warning -1.
2013-06-10 18:41:41,819 [9] FATAL ConsoleApplication1.LogTest2 (line:193) - l4n2 and a fatal .
2013-06-10 18:41:41,831 [9] WARN ConsoleApplication1.LogTest2 (line:206) - l4n2 cls and a warning.
2013-06-10 18:41:41,833 [9] ERROR ConsoleApplication1.LogTest2 (line:207) - l4n2 cls and an error.
2013-06-10 18:41:41,836 [9] FATAL ConsoleApplication1.LogTest2 (line:208) - l4n2 cls and a fatal .
**consoleapplication1.testcls20130610.log**
2013-06-10 18:41:35,767 [9] INFO ConsoleApplication1.testCls (line:176) - ... and an Info log.
2013-06-10 18:41:38,792 [9] WARN ConsoleApplication1.testCls (line:178) - ... and a warning 1.
2013-06-10 18:41:38,795 [9] WARN ConsoleApplication1.testCls (line:180) - ... and a warning 2.
2013-06-10 18:41:38,800 [9] WARN ConsoleApplication1.testCls (line:181) - ... and a warning 3.
2013-06-10 18:41:38,804 [9] WARN ConsoleApplication1.testCls (line:183) - ... and a warning 4.
2013-06-10 18:41:38,806 [9] WARN ConsoleApplication1.testCls (line:184) - ... and a warning 5.
2013-06-10 18:41:41,809 [9] WARN ConsoleApplication1.testCls (line:187) - ... and a warning 6.
2013-06-10 18:41:41,813 [9] WARN ConsoleApplication1.testCls (line:189) - ... and a warning 7.
2013-06-10 18:41:41,817 [9] FATAL ConsoleApplication1.testCls (line:192) - ... and a fatal .
2013-06-10 18:41:41,823 [9] WARN ConsoleApplication1.testCls (line:195) - ... and a warning 8.
2013-06-10 18:41:41,826 [9] ERROR ConsoleApplication1.testCls (line:196) - ... and an error.
2013-06-10 18:41:41,828 [9] FATAL ConsoleApplication1.testCls (line:199) - ... and a fatal .
Everything are OKAY. But....
If I change the config file during the program running, let say I change the level from INFO to FATAL
<logger name="ConsoleApplication1.testCls">
<level value="FATAL" /> <!-- INFO to FATAL -->
</logger>
the two log file now are:
**consoleapplication1.logtest220130610.log**
2013-06-10 19:05:20,880 [9] WARN ConsoleApplication1.LogTest2 (line:182) - l4n2 cls and a warning -1.
**consoleapplication1.testcls20130610.log**
2013-06-10 19:05:17,848 [9] INFO ConsoleApplication1.testCls (line:176) - ... and an Info log.
2013-06-10 19:05:20,872 [9] WARN ConsoleApplication1.testCls (line:178) - ... and a warning 1.
2013-06-10 19:05:20,875 [9] WARN ConsoleApplication1.testCls (line:180) - ... and a warning 2.
2013-06-10 19:05:20,877 [9] WARN ConsoleApplication1.testCls (line:181) - ... and a warning 3.
2013-06-10 19:05:20,884 [9] WARN ConsoleApplication1.testCls (line:183) - ... and a warning 4.
2013-06-10 19:05:20,886 [9] WARN ConsoleApplication1.testCls (line:184) - ... and a warning 5.
I wonder that why the watch function cannot update log properly and seem will affect other log file even I only change one logger data? May I know the reason? What wrong of my code
When you change your config file will your program is running. Log4net will reread you config file because of the Watch:=True. However your genLogXMLCfg is not executed. So your configuration of your appenders in not configured after you save the new config. There is no appender, so you do not see any new entries in your logs.

log4j aligned ConversionPattern

Is it possible to create a ConversionPattern in log4j as such
Some short Msg : [INFO] class date
Some very looooooooooooooong msg : [INFO] class date
What I basically would like to achieve is that message is aligned to left and the rest of information starts after n characters, thus the rest is nicely aligned instead of
Some short Msg : [INFO] class date
Some very looooooooooooooong msg : [INFO] class date
Just put a - in the pattern like:
%-50m | [%p] %c{1} %d %n"/

How to log a message when the BufferingForwardingAppender is flushed?

I have a BufferingForwardingAppender configured to forward the last 10 messages to a RollingFileAppender when an ERROR occurs. Can I get a custom message to appear in the log before each batch of messages?
I want to indicate that this is a new ERROR event and its context, so that the log is readable?
My log4net configuration is kinda like this:
<appender name="ErrorBufferingAppender" type="log4net.Appender.BufferingForwardingAppender">
<bufferSize value="10" />
<lossy value="true" />
<evaluator type="log4net.Core.LevelEvaluator">
<threshold value="ERROR" />
</evaluator>
<appender-ref ref="ErrorFileAppender" />
</appender>
<appender name="ErrorFileAppender" type="log4net.Appender.RollingFileAppender">
<param name="File" value="logs\Errors.txt"/>
<!-- other important parameters -->
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%-4thread] %-5level %logger{1} - %message%newline"/>
</layout>
</appender>
And my desired output is kinda like this
---------- ERROR ----------
2011-05-09 16:59:12,327 [8 ] INFO AppLogger - DiskStorageMonitor.StartMonitoring()
2011-05-09 16:59:12,331 [8 ] INFO AppLogger - DiskStorageMonitor.Initializing File System Watcher...
2011-05-09 16:59:12,341 [8 ] INFO AppLogger - DiskStorageMonitor - LocalSlideDataStorageDrive: C:
2011-05-09 16:59:12,370 [8 ] INFO AppLogger - Transition: From 'MinimumDiskSpaceQuotaState' to 'IdleState'.
2011-05-09 16:59:26,697 [8 ] INFO AppLogger - Transition: From 'IdleState' to 'SlideHolderMacroState'.
2011-05-09 16:59:26,702 [8 ] INFO AppLogger - Transition: From 'SlideHolderMacroState' to 'WaitingForMacroCmdResponseState'.
2011-05-09 16:59:26,781 [12 ] INFO YStageManager - Moving to: -1.25
2011-05-09 16:59:26,782 [14 ] INFO XStageManager - Moving to: -142
2011-05-09 16:59:30,800 [12 ] ERROR RecoveringErrorHandler - An error occurred. Retrying... (snipped exception message & stacktrace)
---------- ERROR ----------
2011-05-09 16:59:30,808 [12 ] WARN MacroCameraRecoverySteps - An error occurred while calling the macro camera. Resetting and retrying...
2011-05-09 16:59:30,809 [12 ] INFO MacroCameraManager - Resetting the Macro Camera.
2011-05-09 16:59:30,886 [12 ] ERROR GetMacroImageCommandHandler - Macro image processing failed for the slide in position 0. (snipped exception message & stacktrace)
I've got a solution that will probably work for you but it is a bit of a work-around. Basically, set two appenders to write to the same file. When you write an error (which will trigger the Buffer to clear to your log file), have the other appender write the "-------Error--------" text first with a newline before the text.
You will have to play around with it a bit to get it to work, but this should be a workable solution. Apache does allow multiple appenders to write to the same file. Just make sure you put the +MinimalLock on your appenders so they don't lock the file. Here is a SO link that explains how two appenders can write to the same file:
Can Log4net have multiple appenders write to the same file?
Thanks to BiggsTRC for the great answers. This is my working log4net configuration and sample output.
This appender responds to any ERROR message by writing the context "header" in the log. The log is minimally locked to allow this and the buffering appender to write to the file. The ignoresException tag set to false actually tells log4net that this layout will write the exception (rather than it writing automatically below the message). But really I don't want it to, that's coming in the other appender.
<appender name="ErrorSectionAppender" type="log4net.Appender.FileAppender">
<filter type="log4net.Filter.LevelMatchFilter">
<levelToMatch value="ERROR" />
</filter>
<filter type="log4net.Filter.DenyAllFilter" />
<file value="logs\Errors.txt" />
<appendToFile value="true" />
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<layout type="log4net.Layout.PatternLayout">
<ignoresException value="false" />
<conversionPattern value="%newline---------- ERROR # %date ----------%newline" />
</layout>
</appender>
This appender buffers all messages until an ERROR message appears, then it dumps the last 10 (bufferSize) messages and the error message to the ErrorFileAppender.
<appender name="ErrorBufferingAppender" type="log4net.Appender.BufferingForwardingAppender">
<bufferSize value="10" />
<lossy value="true" />
<evaluator type="log4net.Core.LevelEvaluator">
<threshold value="ERROR" />
</evaluator>
<appender-ref ref="ErrorFileAppender" />
</appender>
This is the actual error file appender. The conversion pattern is standard. Notice the minimal file lock here as well.
<appender name="ErrorFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="logs\Errors.txt"/>
<appendToFile value="true"/>
<staticLogFileName value="true"/>
<rollingStyle value="Size"/>
<maxFileSize value="1048576"/>
<maxSizeRollBackups value="-1"/>
<countDirection value="1"/>
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%-4thread] %-5level %logger{1} - %message%newline"/>
</layout>
</appender>
The output of these appenders looks like this
---------- ERROR # 2011-05-13 13:51:22,632 ----------
2011-05-13 13:51:04,937 [9 ] INFO OmnyxScannerLogger - Transition: From 'No State' to 'CommunicationSyncState'.
2011-05-13 13:51:05,363 [12 ] DEBUG IMacroImageProcessor - hello, 10
2011-05-13 13:51:05,369 [19 ] INFO XStageManager - Connecting
2011-05-13 13:51:05,369 [12 ] INFO ZStageManager - Connecting
2011-05-13 13:51:05,369 [16 ] INFO YStageManager - Connecting
2011-05-13 13:51:05,393 [9 ] INFO OmnyxScannerLogger - Transition: From 'CommunicationSyncState' to 'SystemInitializeState'.
2011-05-13 13:51:08,528 [17 ] INFO YStageManager - Homing
2011-05-13 13:51:08,539 [12 ] INFO ZStageManager - Homing
2011-05-13 13:51:22,632 [14 ] ERROR RecoveringErrorHandler - An error occurred. Retrying...
Omnyx.Scanner.CliContracts.ScannerException: Injected: The stage failed to home.
at Omnyx.Scanner.Simulation.ErrorInjection.ErrorInjectionInterceptor.Intercept(IInvocation invocation) in D:\Simulation\ErrorInjection\ErrorInjectionInterceptor.cs:line 42
at Castle.DynamicProxy.AbstractInvocation.Proceed()
at Castle.Proxies.IXStageManagerProxy.Home()
---------- ERROR # 2011-05-13 13:51:33,758 ----------
2011-05-13 13:51:29,034 [9 ] INFO OmnyxScannerLogger - DiskStorageMonitor.StartMonitoring()
2011-05-13 13:51:29,037 [9 ] INFO OmnyxScannerLogger - DiskStorageMonitor.Initializing File System Watcher...
2011-05-13 13:51:29,046 [9 ] INFO OmnyxScannerLogger - DiskStorageMonitor - LocalSlideDataStorageDrive: C:
2011-05-13 13:51:29,062 [9 ] INFO OmnyxScannerLogger - -- LocalSlideDataStorageOverhead: 0
2011-05-13 13:51:29,075 [9 ] INFO OmnyxScannerLogger - Transition: From 'MinimumDiskSpaceQuotaState' to 'IdleState'.
2011-05-13 13:51:31,727 [9 ] INFO OmnyxScannerLogger - Transition: From 'IdleState' to 'SlideHolderMacroState'.
2011-05-13 13:51:31,732 [9 ] INFO OmnyxScannerLogger - Transition: From 'SlideHolderMacroState' to 'WaitingForMacroCmdResponseState'.
2011-05-13 13:51:31,792 [12 ] INFO YStageManager - Moving to: -1.25
2011-05-13 13:51:31,793 [20 ] INFO XStageManager - Moving to: -142
2011-05-13 13:51:33,758 [12 ] ERROR RecoveringErrorHandler - An error occurred. Retrying...
Omnyx.Scanner.CliContracts.ScannerException: Injected: The macro camera failed.
at Omnyx.Scanner.Simulation.ErrorInjection.ErrorInjectionInterceptor.Intercept(IInvocation invocation) in D:\Simulation\ErrorInjection\ErrorInjectionInterceptor.cs:line 42
at Castle.DynamicProxy.AbstractInvocation.Proceed()
at Castle.Proxies.IMacroCameraManagerProxy.TakeTopLitAndBackLitPictures()

Resources