With log4net, do you specify which appender to use? - c#

When you have 2 appenders, say one for debug errors and one for product errors, in your code, do you explicitly create 2 log classes or is an appender basically going to write any log messages that meet a certain criteria?
So in your code, you use a single log method, and depending on how your appenders are setup, it will log the message if it e.g. is logged from a specific namespace, or is a certain log level.
So its possible a single log entry is written to 2 log files?

Yes, you can have single log statements post to multiple appenders. As long as it meets the criteria for each, it will use each appender.
For example, take this config section, it logs all messages to file, and also logs warnings and errors to event viewer.:
<log4net>
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="c:\logs\MySite"/>
<appendToFile value="true"/>
<datePattern value=".yyyy-MM-dd.\l\o\g"/>
<rollingStyle value="Date"/>
<MaxSizeRollBackups value="14"/>
<param name="StaticLogFileName" value="false"/>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%d{HH:mm:ss.fff} [%thread] %-5level %logger{1} - %m%n"/>
</layout>
</appender>
<appender name="EventLogAppender" type="log4net.Appender.EventLogAppender">
<applicationName value="Trading.Web"/>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%d{HH:mm:ss.fff} [%thread] %-5level %logger{1} - %m%n"/>
</layout>
<filter type="log4net.Filter.LevelRangeFilter">
<param name="LevelMin" value="WARN"/>
<param name="LevelMax" value="ERROR"/>
</filter>
</appender>
<root>
<level value="DEBUG"/>
<appender-ref ref="RollingFileAppender"/>
<appender-ref ref="EventLogAppender" />
</root>
</log4net>
So this:
_log.Debug("This is a debug message");
Will only appear in the log file (because it doesn't meet the event log appender's filter criteria).
But this:
_log.Error("This is an error message.");
Will log to both the log file and the event viewer.
UPDATE: On your filtering question, if you had:
<root>
<level value="DEBUG"/>
<appender-ref ref="RollingFileAppender"/>
</root>
<!-- Print only messages of level WARN or above in the namespace Com.Foo -->
<logger name="Com.Foo">
<level value="WARN" />
</logger>
Then all things under Com.Foo will log if WARN or higher, but everything else would log at DEBUG or higher....

Related

log4net You have tried to set a null level to root

I have a WPF application that uses Log4Net to log all kinds of information. The application runs fine and everything is logged as it should be. However, when scrolling trhough the Output window, I found following messages:
log4net:ERROR You have tried to set a null level to root.
log4net:ERROR You have tried to set a null level to root.
log4net.Core.LogException: Error in the application.
log4net.Core.LogException: Error in the application.
Here's my config file:
<log4net>
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="c:\temp\logs\UtexbelAppLog.txt"></file>
<appendToFile value="true"></appendToFile>
<rollingStyle value="Size"></rollingStyle>
<maximumFileSize value="1MB"></maximumFileSize>
<maxSizeRollBackups value="5"></maxSizeRollBackups>
<staticLogFileName value="true"></staticLogFileName>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date{dd-MM-yyyy HH:mm:ss} %level - %message - %line%newline%exception"></conversionPattern>
</layout>
</appender>
<root>
<level value="WARNING"></level>
<appender-ref ref="RollingFileAppender"></appender-ref>
</root>
</log4net>
I have no idea why I'm getting these messages. Any help would be much appreciated.
Try to add this between your "root" quotes :
<logger name="LoggerName">
<level value="WARN" />
<appender-ref ref="RollingFileAppender" />
</logger>
Here is the available levels, in order of increasing priority :
ALL
DEBUG
INFO
WARN
ERROR
FATAL
OFF
More informations on this link, chapter "Loggers" : https://logging.apache.org/log4net/release/manual/configuration.html
Not sure if there is <level value="WARNING"></level> it should be <level value="WARN"></level>

Can log4net create log files in a yyyy\\MM\\ddMMyyyy_file.log structure?

I am trying to make log4net create it's log files in a folder structure, but so far I'm not successful.
What I'd like to accomplish is that log4net creates log files like this:
..\log\2017\10\30-10-2017_eva360Recorder.log
..\log\2017\10\31-10-2017_eva360Recorder.log
..\log\2017\11\01-11-2017_eva360Recorder.log
..\log\2017\11\02-11-2017_eva360Recorder.log
In my app.config I now have the following:
<!-- Log4net Logging Setup -->
<log4net>
<root>
<level value="ALL" />
<appender-ref ref="LogFileAppender" />
</root>
<appender name="LogFileAppender" type="log4net.Appender.RollingFileAppender, log4net">
<file type="log4net.Util.PatternString" value="log\\%date{yyyy}\\%date{MM}\\%date{dd-MM-yyyy}_eva360Recorder.log" />
<appendToFile value="true" />
<rollingStyle value="Date" />
<maxDateRollBackups value="60" />
<datePattern value="dd-MM-yyyy" />
<preserveLogFileNameExtension value="true"/>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger %M - %message%newline" />
</layout>
</appender>
</log4net>
This, however, results in the following:
d:\Eva360\Recorder\log\2017\10\31-10-2017_eva360Recorder.log
d:\Eva360\Recorder\log\2017\10\31-10-2017_eva360Recorder31-10-2017.log
As you can see, this is not what I wanted. It did not create a month folder (..\2017\11..) and also did not change the name of the log file, but added a date within the file name.
Is what I want even possible?
If so, how should I do that?
And also importantly, where is this to be found in the documentation of log4net?
I realise that this conjecture, rather than a definitive answer, but this could probably be achieved through the use of a custom log4net appender. See IAppender in the log4net SDK.
Google is chock full of articles about creating custom log4net appenders, so no need to repeat anything here.

Multiple instances of same process logging on different files

I'm trying to log to multiple files with multiple instances of the same scheduled process, and the target file is chosen based on runtime parameters.
The problem here is that, while one instance is running, no other one is able to log, producing just empty files.
Here's a sample scenario:
The schedlued task program.exe A starts and begins to log to A_{currentDate}.log
The schedlued task program.exe B starts while program.exe A is still running and should start logging to B_{currentDate}.log
When they both end, the second file is empty while the first is not, and this is not the expected result as I'm 100% sure that the second instance has something to log. Basically it looks like that the first instance to run prevents all the other ones from logging, being the only one that can do it.
Given that we have about 20 scheduled tasks for the same program, this is causing a lot of issues as we're missing some important logs.
Here's a snippet of log4net.config file:
<appender name="A_appender" type="log4net.Appender.FileAppender">
<file type="log4net.Util.PatternString" value="A_%property{Date}.log" />
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<param name="AppendToFile" value="true" />
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%d [%t] %-5p %c - %m%n" />
</layout>
</appender>
<appender name="B_appender" type="log4net.Appender.FileAppender">
<file type="log4net.Util.PatternString" value="B_%property{Date}.log" />
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<param name="AppendToFile" value="true" />
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%d [%t] %-5p %c - %m%n" />
</layout>
</appender>
<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender" >
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%d [%t] %-5p %c - %m%n" />
</layout>
</appender>
...
<logger name="A.Logger">
<appender-ref ref="A_appender" />
<level value="DEBUG" />
</logger>
<logger name="B.Logger">
<appender-ref ref="B_appender" />
<level value="DEBUG" />
</logger>
...
<root>
<level value="ALL" />
<appender-ref ref="ConsoleAppender" />
</root>
and here's the initialization code for each instance:
protected Module(string logName)
{
ThreadContext.Properties["Date"] = GlobalContext.Properties["Date"] = DateTime.Now.ToString("yyyyMMdd");
XmlConfigurator.Configure(new System.IO.FileInfo(properties.get("log4net.config.file")));
log = LogManager.GetLogger(logName);
...
}
Can someone help me with that?
The way it looks to me is that both of your processes are trying to hold both files open (both appender A and appender B) so whichever one starts first blocks the second process from running. You may only be grabbing a reference to one or the other appender to use, but it is creating both of them even though it is only logging to whichever one you grab.
You will likely need to set a second GlobalContext property for each process that is unique and include that in the filename, since it sounds like both processes run on the same date.

Class will not log to a file with log4net

I've got a MVC based C# Windows Forms application. I've got the following configuration in the app.config file:
<log4net>
<root>
<level value="ALL"/>
<appender-ref ref="LogConsoleAppender"/>
<appender-ref ref="RollingLogFileAppender"/>
</root>
<appender name="LogConsoleAppender" type="log4net.Appender.ConsoleAppender">
<layout type="QAC.Source.Services.Log.LogPatternLayout">
<conversionPattern value="%date %level [Thread: #%thread] %message [%logger -> %M]%newline"/>
</layout>
</appender>
<appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="logs/QAC_"/>
<datePattern value="yyyy-MM-dd_HH-mm-ss'.log'"/>
<staticLogFileName value="false"/>
<appendToFile value="false"/>
<rollingStyle value="Date"/>
<maxSizeRollBackups value="50"/>
<maximumFileSize value="10MB"/>
<layout type="QAC.Source.Services.Log.LogPatternLayout">
<conversionPattern value="%date %level [Thread: #%thread] %message [%logger -> %M]%newline"/>
</layout>
</appender>
</log4net>
In the main method, in the first lin, I call private static ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); and after that I initialize my main service:
mainService = MainFactory.getMainServiceInstance();
And there is the problem. All log outputs in the main method are logged successfully to the file and console, also of other services (underlying services from MainService). The only class which is not logged is the MainService. The curiosity at this is, that the logging for this class starts after some time. I don't use any filter. I've turned on the log4net debugging:
<add key="log4net.Internal.Debug" value="true"/>
, but there is no error at least. So I think, that the initialization goes through. Also if I log before I initialize the MainService, it also logs to console and file. Just this class will not log.
Any help would be very nice. Thank you in advance.
I've found the solution. I am using a custom LogPatternLayout which tries also to initialize the MainService and so the MainService is initialized before the LogPatternLayout could be read and initialized into the Logger. Therefore logging takes place after the initialization of the MainService.

Logging in an application

I built an application and want to use logging in my application before giving it out to a user to know the actions the user did in case before any error. I haven't used logging before, so I did a bit of study to find out good methods for the same and perhaps Trace class in .NET looks like what might help in this scenario.
Using a text file seems to be a better idea here for the logging setting a TextWriterTraceListener in the App.Config file of my project, and using in the code Trace.Writeline("Error info", "Field");
1) Even after reading good amount of content, I am not sure about good approaches for logging? Should there be different error logger and information logging files? How does logging work for specifying different types of error (such as warning, critical, error etc.?)
2) I want to use the same logfile in one of my other projects in the solution. So, do I add the same Trace Listener section in the App.Config of my project?
With a logging library (such as log4net), you can do all the things you are asking about easily. You can set up your logging in a config file to go to event log, file, console, etc (or any combination) and set the logging levels independently.
That is, you can say the file will have informationals, warnings, errors, and fatals, but the event log will log only the errors and fatals.
In general, nearly all of the logging libraries have these features. The examples below are just in terms of log4net but the same concepts apply to most logging libraries...
To get the logger in any class in your solution, you just need to ask for a logger in your class:
public MyClass
{
private static readonly ILog _log = log4net.LogManager.GetLogger(typeof(MyClass));
public void SomeMethod()
{
_log.Debug("This is a debug message.");
_log.Info("This is an informational message.");
_log.Warn("This is a warning message.");
_log.Error("This is an error message.");
_log.Fatal("This is a fatal message.");
}
}
In addition, you can filter based on the loggers, that is, you could suppress log messages from paraticular classes or only display logging messages for a subset of classes, etc.
A sample config settings block would look like this. This creates a rolling file appender (keeps several days worth of logs) and Console appender
<log4net>
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="c:\logs\AgentLog"/>
<appendToFile value="true"/>
<datePattern value=".yyyy-MM-dd"/>
<rollingStyle value="Date"/>
<MaxSizeRollBackups value="14"/>
<param name="StaticLogFileName" value="false"/>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%d{HH:mm:ss.fff} [%thread] %-5level %logger{1} - %m%n"/>
</layout>
</appender>
<appender name="ColoredConsoleAppender" type="log4net.Appender.ColoredConsoleAppender">
<mapping>
<level value="FATAL"/>
<foreColor value="Yellow"/>
<backColor value="Red, HighIntensity"/>
</mapping>
<mapping>
<level value="ERROR"/>
<foreColor value="Red, HighIntensity"/>
</mapping>
<mapping>
<level value="WARN"/>
<foreColor value="Yellow, HighIntensity"/>
</mapping>
<mapping>
<level value="INFO"/>
<foreColor value="Green, HighIntensity"/>
</mapping>
<mapping>
<level value="DEBUG"/>
<foreColor value="White"/>
</mapping>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%d{HH:mm:ss.fff} [%thread] %-5level %logger{1} - %m%n"/>
</layout>
</appender>
<root>
<level value="INFO"/>
<appender-ref ref="RollingFileAppender"/>
<appender-ref ref="ColoredConsoleAppender"/>
</root>
</log4net>

Categories

Resources