log information into different log files - log4net

I have the following configurations in my web.config file, but how can I log the information into data.txt and general.txt separately in C#?
Could anyone provide some sample code for me?
<appender name="GeneralLog" type="log4net.Appender.RollingFileAppender">
<file value="App_Data/Logs/general.txt" />
<appendToFile value="true" />
<maximumFileSize value="2MB" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="5" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%d{HH:mm:ss.fff} [%t] %-5p %c - %m%n" />
</layout>
</appender>
<appender name="DataLog" type="log4net.Appender.RollingFileAppender">
<file value="App_Data/Logs/data.txt" />
<appendToFile value="true" />
<maximumFileSize value="2MB" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="5" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%d{HH:mm:ss.fff} [%t] %-5p %c - %m%n" />
</layout>
</appender>

In your app, ideally, you should log the same way for both general and data, just using different loggers. In configuration you have a few options how to "route" the incoming log messages to different appenders.
The first is the loggers themselves. Depending on how your app is organized in terms of classes and namespaces, you organize your loggers in a hierarchical manner according to your namespace hierarchy. Then you can have different branches in the hierarchy going to different appenders. Read up on the Level Inheritance section here.
In addition to logger hierarchies, you can use any name as logger names. So for your general sections of your app, you could use a logger named "general".
Next thing you can use to control log message flow is using filters. You can filter messages on logger name, level, properties etc. or you can implement your own filters.
Here's a sample to show how you could route general and data to your appenders using the logger element and a filter. We route the root element (which receives all log messages) to the data appender. At the data appender we filter out all messages coming from the general logger.
Additionally, we route the general logger to the general appender.
<appender name="GeneralLog" type="log4net.Appender.RollingFileAppender">
...
</appender>
<appender name="DataLog" type="log4net.Appender.RollingFileAppender">
<filter type="log4net.Filter.LoggerMatchFilter">
<loggerToMatch value="general" />
<acceptOnMatch value="false" />
</filter>
...
</appender>
<root>
<level value="DEBUG" />
<appender-ref ref="DataLog" />
</root>
<logger name="general">
<level value="WARN" />
<appender-ref ref="GeneralLog" />
</logger>

Related

ASP.NET Boilerplate adding an additional log file with Log4Net and Castle Logging

I've been trying to find documentation and guidance on how to use a separate log file in ASP.NET Boilerplate MVC.
It's straight forward to inject ILogger and push messages into the default Log.txt file, however I need a separate log file to record a lot of batch job messages and keep things tidy.
I can't find any methods to use another log from the Log4Net.config file. Can anyone advise on the correct code / configuration?
So I found the answer by chance in looking at the Hangfire documentation, where it was shown you can configure Hangfire messages to be sent to another log file by getting Log4Net to listen for the Hangfire name and route based on that.
With the following additional configuration in Log4Net.config I now have Log messages created normally within MyClass sent to the MyClass.txt log file:
<appender name="RollingFileAppender_MyClass" type="log4net.Appender.RollingFileAppender" >
<file value="App_Data/Logs/MyClass.txt" />
<appendToFile value="true" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="32" />
<maximumFileSize value="10000KB" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%-5level %date [%-5.5thread] %-40.40logger - %message%newline" />
</layout>
</appender>
<logger additivity="false" name="MyNamespace.MyClass">
<level value="DEBUG" />
<appender-ref ref="RollingFileAppender_MyClass" />
</logger>
And for completeness, it's called in the standard way documented within the AspNet Boilerplate documentation:
https://aspnetboilerplate.com/Pages/Documents/Logging
Way-1:
In this sample, the default log file is App_Data/Logs/Logs.txt.
But when I use the logger in the namespace MySite.Web.Controllers.PaymentController, the logs will be written in App_Data/Logs/PaymentLogs.txt
log4net.config
<?xml version="1.0" encoding="utf-8" ?>
<log4net>
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender" >
<file value="App_Data/Logs/Logs.txt" />
<appendToFile value="true" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="10" />
<maximumFileSize value="10000KB" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%-5level %date [%-5.5thread] %-40.40logger - %message%newline" />
</layout>
</appender>
<appender name="RollingFileAppender_PaymentController" type="log4net.Appender.RollingFileAppender" >
<file value="App_Data/Logs/PaymentLogs.txt" />
<appendToFile value="true" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="32" />
<maximumFileSize value="10000KB" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%-5level %date [%-5.5thread] %-40.40logger - %message%newline" />
</layout>
</appender>
<root>
<appender-ref ref="RollingFileAppender" />
<level value="DEBUG" />
</root>
<logger name="NHibernate">
<level value="WARN" />
</logger>
<logger name="MySite.Web.Controllers.PaymentController" additivity="false">
<appender-ref ref="RollingFileAppender_PaymentController" />
<level value="DEBUG" />
</logger>
</log4net>
Way-2:
You can get a specific logger by calling LogManager.GetLogger() with a appender name.
private static readonly ILog paymentLogger = LogManager.GetLogger("MySite.Web.Controllers.PaymentController");

Log4Net smtpappender is ignoring level filter

I'm using Log4Net for logging all different kinds of events in my application. Therefore I configured a fileAppender and a smtpAppender.
While the fileAppender is logging everything, the smptAppender should only send me an e-mail if the logging level is FATAL.
Right now, Log4Net is sending me e-mails for both ERROR and FATAL level.
That's my configuration:
<log4net>
<appender name="FileAppender" type="log4net.Appender.RollingFileAppender">
<file value="C:\Temp\xxx.txt" />
<appendToFile value="true" />
<rollingStyle value="Size" />
<maximumFileSize value="10MB" />
<staticLogFileName value="true" />
<maxSizeRollBackups value="150" />
<layout type="log4net.Layout.PatternLayout">
<header value="DateTime | Thread | Level | ClassName | Message" />
<conversionPattern value="%date | %thread | %-5level | %logger | %message%newline" />
</layout>
</appender>
<appender name="SmtpAppender" type="log4net.Appender.SmtpAppender">
<filter type="log4net.Filter.LevelMatchFilter">
<acceptOnMatch value="true" />
<levelToMatch value="FATAL" />
</filter>
<filter type="log4net.Filter.DenyAllFilter" />
<to value="xxx" />
<from value="xxx" />
<subject value="Error" />
<smtpHost value="xxx" />
<bufferSize value="512" />
<lossy value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date | %thread | %-5level | %logger | %message%newline" />
</layout>
</appender>
<root>
<level value="ALL" />
<appender-ref ref="FileAppender" />
<appender-ref ref="SmtpAppender" />
</root>
</log4net>
I'm using the most recent Log4Net version[1.2.15] 2.0.5.
Curiously, the smptAppender is filtering the INFO and DEBUG level with this configuration.
Using the level evaluator or the level range instead of the level match filter didn't work either.
Level evaluator:
<evaluator type="log4net.Core.LevelEvaluator">
<threshold value="FATAL"/>
</evaluator>
Level range filter:
<filter type="log4net.Filter.LevelRangeFilter">
<param name="LevelMin" value="FATAL"/>
<param name="LevelMax" value="FATAL"/>
</filter>
I know that there are many threads about this topic here on stackOverflow, but none of them could help me with my problem.
Threads with the same topic:
How do I configure a log4net SmtpAppender to only send me e-mails when a certain level is hit?
Log4j2: SMTPAppender does not send mails with error or fatal level
Log4Net LevelEvaluator Ignored when bufferSize greater than 1 for SmtpAppender
well I know that this question is quite old, but I post this answer for others having this problem.
You are using the "lossy" and "bufferSize" settings. I guess that it is to get the last 512 events (not only the FATAL events) when the log is reaching a FATAL event.
Instead of using a LevelMatchFilter or a LevelEvaluator, can you simply test with a simple "threshold" (not in an evaluator).
See Why do Log4Net Filters Receive Messages Outside of the Evaluator Threshold? for more information.
But I think that in this case you will not have other events in the mail that you will receive, so the buffering would be useless.

What's wrong with my log4net config file

I have a config file with two appenders, one file appender and one database appender. I want to log everything to the file appender, and only log exceptions to the database appender. When setting up both appenders in the section it logs fine but all log events are sent to both appenders, which is not what i want.
I changed the configuration but with this current configuration, exceptions get logged to the database, and nothing is getting written to the file appender. Can anyone tell me why I am not getting anything written to the file appender?
<log4net debug="true">
<appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="C:\Log4net\Workflow\TestLog.txt" />
<threshold value="All" />
<appendToFile value="true" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="10" />
<maximumFileSize value="10KB" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%-5p {%logger} %d %5rms %-22.22c{1} %-18.18M - %m%n" />
</layout>
</appender>
<appender name="AdoNetAppender" type="log4net.Appender.AdoNetAppender">
<!-- Removed to keep this snippet simple-->
</appender>
<root>
<level value="Error" />
<appender-ref ref="AdoNetAppender" />
</root>
<logger name="AllLogs">
<level value="ALL" />
<appender-ref ref="RollingLogFileAppender" />
</logger>
</log4net>
What you have here is the following:
all logs events with the level Error or more will go to the AdoNetAppender
all logs events originating from a logger whose name is based on AllLogs will go to the RollingLogFileAppender
From what I understand you want all logs to default to the file, and only error ones to go also to the database. Then simply add both appenders to your root logger so that both get all events, and add filters to only let filters you're interested in pass through: a level range filter on your database appender would work
<log4net debug="true">
<appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
<!-- rest of config snipped to save space -->
</appender>
<appender name="AdoNetAppender" type="log4net.Appender.AdoNetAppender">
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="ERROR" />
<levelMax value="FATAL" />
</filter>
<!-- rest of config snipped to save space -->
</appender>
<root>
<appender-ref ref="AdoNetAppender" />
<appender-ref ref="RollingLogFileAppender" />
</root>
</log4net>
Of course if you don't want any duplicate just filter errors and above in the rolling file appender

log4Net - Loggers between classes - Releasing a File

I am new to log4net. Here is my app.config. What is happening is at a point after going through a switch statement, my logger "X" stops writing to my log file. I tried x.Logger.Repository.Shutdown();, and all that does is stop my "Y" from even logging. My suspicion is that the file is in use, and can't be written to (the next logging statement does begin in a different class. Again, I'm new. Basically, it writes about 10 lines, goes to another class with a logger of the same name, works in that class for a few more lines, and then when it goes back to the original class, it stops logging. I'm a little lost. P.S. I have the correct section name, and I am calling my log as such:
private static readonly ILog eventLog = LogManager.GetLogger("EventLog");
<appender type="log4net.Appender.FileAppender" name="event">
<file value="C:X.log" />
<layout type="log4net.Layout.PatternLayout">
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<conversionpattern value="%d [%t] %-5p %c - %m%n" />
</layout>
</appender>
<appender type="log4net.Appender.FileAppender" name="cLog">
<file value="Y.log" />
<layout type="log4net.Layout.PatternLayout">
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<conversionpattern value="%d [%t] %-5p %c - %m%n" />
</layout>
</appender>
<logger name="EventLog">
<level value="INFO" />
<maximumfilesize value="256KB" />
<param value="INFO" name="Threshold" />
<appender-ref ref="event" />
</logger>
<logger name="crLog">
<level value="INFO" />
<maximumfilesize value="256KB" />
<param value="INFO" name="Threshold" />
<appender-ref ref="cLog" />
</logger>
As it turns out, when you call x.Logger.Repository.Shutdown(); it kills any logs that you might want to write to at that point in time.
I will either move x.Logger.Repository.Shutdown(), or find a different method for releasing my files so the last portion of my app can use (email) the file.

How to append rolling index BEFORE file extension in log filename

I am using the RollingLogFileAppender and it works great and it's rolling over into new files. But it's adding the .1, .2, etc at the very end of the file. So I end up with .log.1, .log.2, etc. So every file technically has a new extension that explorer doesn't know, so I can't just double click on a file to open.
How can I get the rolling file appender to insert that index BEFORE the file extension?
What I want is
.1.log
.2.log
Bonus would be for the current file to always be .0.log, that way they always sort correctly in explorer.
EDIT: added my current config settings
<log4net>
<appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
<lockingModel type="log4net.Appender.FileAppender+MinimalLock"/>
<file value="App_Data\\Logs\\" />
<datePattern value="dd.MM.yyyy'.log'" />
<staticLogFileName value="false" />
<appendToFile value="true" />
<rollingStyle value="Composite" />
<maxSizeRollBackups value="10" />
<maximumFileSize value="5MB" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />
</layout>
</appender>
<logger name="File">
<level value="All" />
<appender-ref ref="RollingLogFileAppender" />
</logger>
</log4net>
You just need to use the PreserveLogFileNameExtension property on the RollingFileAppender.
See the following questions:
Log4net appender filename issue
Log4net RollingFileAppender Size rollingStyle file extension

Resources