Log4Net: RollingFileAppender, new instead of override - c#

I'm using Log4Net to log to files. I wish to let the logs be seperated by date so i use a datepattern:
<DatePattern value=".yy-MM-dd.'xml'" />
However, if the program is shut down and started again, the same file is either overwridden, or appended to (by AppendToFile property). I would like that if the program has previously been started on the same day, another file with a incremented count be created instead.
The directory might look like this:
Logs/
log.15-01-03.xml
log.15-01-04.xml
log.15-01-04.0.xml
log.15-01-04.1.xml //program opened 3 times on the 4th of jan. '15
log.15-01-05.xml
So, roll on date and count on session. Any Ideas?
Also, if i would like backup files of all logs, should i use a second appender, to a Logs/Backup/ directory, or is there a fancy way in Log4Net?
my RollingFileAppender is currently setup like this:
<appender name="RollingFileAppender"
type="log4net.Appender.RollingFileAppender">
<File value="Log/log" />
<DatePattern value=".yy-MM-dd.'xml'" />
<Layout type="log4net.Layout.XmlLayout" />
<RollingStyle value="Date" />
<MaxSizeRollBackups value="2147483647" />
<CountDirection value="0"/>
<StaticLogFileName value="false"/>
<Encoding value="Unicode"/>
<ImmediateFlush value ="true"/>
<PreserveLogFileNameExtension value="true"/>
</appender>

Related

Why am I getting two log files per day using log4net with ASMX web service?

I have a ASMX web service running IIS 10 and have added log4net to the project with the following configuration:
<appender name="AsmxDebugLogFile" type="log4net.Appender.RollingFileAppender">
<file value="App_Data/ASMX.DEBUG_" type="log4net.Util.PatternString" />
<appendToFile value="true" />
<rollingStyle value="Composite" />
<datePattern value="yyyy-MM-dd'.log'" />
<maximumFileSize value="5GB" />
<staticLogFileName value="false" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
</layout>
</appender>
<logger name="AsmxDebugLogFile">
<level value="DEBUG" />
<appender-ref ref="AsmxDebugLogFile" />
</logger>
But for some reason, I'm getting two log files per day in the format of yyyy-MM-dd.log.yyyy-MM-dd.log as per the screenshot below, seemingly at random times as well, whereby the log file will switch to the newly created log file, and then will start logging again in the log file at was created at midnight of the day in question. All log files are way below the 5GB max file size as well.
Below is an updated list of log files
It seems that initially, log4net logs to the file yyyy-MM-dd.log, and then after a random amount of time creates a new log file yyyy-MM-dd.log.yyyy-MM-dd.log starts writing to this log file and then goes back and logs to yyyy-MM-dd.log which was created at the start of the day.
These are the IIS recycle settings
I am wanting 1 log file per day in the format of ASMX.DEBUG_yyyy-MM-dd.log. Where am I going wrong with this configuration?
UPDATE
It seems that because we are recycling the application pool every 60 minutes depending on whether the log file is being written to at this time, depends on whether a new one is created. Any suggestions as to how to overcome this issue. At the minute I've now added the process_id in the log file name and it seems to work in that I get a new log file created every hour, but ideally I want just 1 log file a day.
I use log4net for all my applications and I never encountered this re-creation of file after a pool recycling.
Here are my parameter that differ from yours :
<appendToFile value="true"/>
<staticLogFileName value="true" />
<lockingModel type="log4net.Appender.FileAppender+MinimalLock"/>
And here's how the behaviour will be different :
staticLogFileName means current day's file name will always be the same (ASMX.DEBUG_.log here). It will be automatically renamed with the date pattern on the day after.
appendToFile means it will not overwrite current day's file, but rather append to it.
I think those first two parameters will avoid the creation of multiple file for the current day which may fix your problem.
MinimalLock's role is less clear to me, but I should mention it anyway :
Opens the file once for each AcquireLock()/ReleaseLock() cycle, thus holding the lock for the minimal amount of time. This method of locking is considerably slower than FileAppender. ExclusiveLock but allows other processes to move/delete the log file whilst logging continues.
<appender name="AsmxDebugLogFile" type="log4net.Appender.RollingFileAppender">
<lockingModel type="log4net.Appender.FileAppender+MinimalLock"/>
I think you need Locking model which will not lock your file.I think when main file gets created and get locked. The File appender creates file name with same date time stamp over the exisiting file.
You should also use Remote path for logging like \\server\file\debug since you might have load balancer for IIS or Web server is hosted with static IP or F5.
Try with this parameters.
<param name="File" value="C:\YourLogFilePath\" />
<rollingStyle value="Composite" />
<param name="DatePattern" value="dd.MM.yyyy'.log'" />
<param name="AppendToFile" value="true" />
<maxSizeRollBackups value="2" />
<maximumFileSize value="5GB" />
<staticLogFileName value="false" />
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
You are using the "RollingFileAppender" which as its name suggests rolls to a new file on dates, try using the FileAppender, more information about how to use FileAppender you can refer to this link: FileAppender.

Log4net outputting random method names after applciation is obfuscated via .net -reactor

I have obfuscated my application using .net reactor. Application is working fine other then on some places method names in log file created through log4net is coming as random string.
Strange thing is within same method different logs are coming with different behavior. Some coming with actual method name while other with random method name.
e.g,
My log4net appender is
<appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender" >
<file value="..\\Logs\\MyApp_N1" />
<encoding value="utf-8" />
<appendToFile value="true" />
<datePattern value="_yyyyMMdd'.log'" />
<staticLogFileName value="false" />
<rollingStyle value="Composite"/>
<maxSizeRollBackups value="-1"/>
<maximumFileSize value="10MB"/>
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<filter type="log4net.Filter.LevelRangeFilter">
<acceptOnMatch value="true" />
<levelMin value="DEBUG" />
<levelMax value="FATAL" />
</filter>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%d{yyyy-MM-dd HH:mm:ss.fff} %p MyApp N1 %t %c{1}.%M %property{SessionId} %m%n" />
</layout>
</appender>
log4net version 2.0.8
.net reactor version 5.0
Sample Log Messages are
2017-12-08 15:17:33.722 DEBUG TWS N1 13 MyclassName.SendMessage My method start
2017-12-08 15:17:33.840 DEBUG TWS N1 13 MyclassName.urT1VHsGarQ1gTcc8O Message request add in db id =166364
2017-12-08 15:17:33.852 DEBUG TWS N1 13 MyclassName.SendMessage Message Services - Send End
If the method 'urT1VHsGarQ1gTcc8O' is not a public one then this is the expected output.
To obfuscate all public classes and methods as well you need to set "2. Protection Settings"->"Obfuscation"->"Obfuscate Public Types" to "True".

log4.net does not write until Windows Service Stops

I am using log4.net in my Windows Service for logging.
Here is my config;
<appender name="RollingFile" type="log4net.Appender.RollingFileAppender">
<file value="MyApp.log" />
<appendToFile value="true" />
<bufferSize value="1" />
<maximumFileSize value="100000KB" />
<maxSizeRollBackups value="5" />
<rollingStyle value="Size" />
<immediateFlush value="true" />
</appender>
for some reason it does not write into file until I stop the service. Is there a sort of buffering is happening? Once I stop the service all pending logs are getting written.
What would be the issue?
Strange, are you sure it actually works at all?
My version of log4net (version 1.2.11) requires a Layout (otherwise nothing gets logged) and does not have a BufferSize property (but that doesn't stop it working)
Also, immediateFlush should default to true, so isn't needed.
The following works for me.
<appender name="RollingFile" type="log4net.Appender.RollingFileAppender">
<file value="MyApp.log" />
<appendToFile value="true" />
<maximumFileSize value="100000KB" />
<maxSizeRollBackups value="5" />
<rollingStyle value="Size" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %level %logger - %message%newline" />
</layout>
</appender>
I had a similar problem with my windows service, which only wrote to the log when the Service was stopped.
My initial thought was this feels like some sort of locking issue, either in the .Net code or on the file itself and by stopping the windows service, it removes the lock and allows the write to complete.
Having said that, I noticed that changing the User Account under which the Windows Service ran, to one with higher privileges, made it update immediately, rather than only on Service Stop.
I changed it from Local System to Administrator and it fixed the problems. Of course, running as Administrator isn't recommended, but it may at least help you to diagnosis if the problem is related to Profile/Permissions.
I still haven't figured out the root cause of this yet...

Problematic N-Tier logging with log4net

I am currently developing series of web services in WCF using .NET 4.5. For my logging I have chosen log4net framework but I found that its a big problem to use it in my project design.
I have everything separated into projects like this :
DataAccess
Common
etc. etc.
ExternalServicesContracts
ExternalServices
ExternalServicesProxies
InternalService
All of the services projects contains more services.
Situation
I need my log files to look like this ServiceName_YYYY_DDMM.log.
So in the log4net config file i need to use different loggers per namespace of the web service. I can achieve it by using loggers like this :
For the first service :
private static readonly ILog Log = LogManager.GetLogger(typeof(MyFirstService));
And the same for the second service :
private static readonly ILog Log = LogManager.GetLogger(typeof(MySecondService));
and then in config file I just point to them by loggers
<logger name="ExternalServices.MyFirstService">
<appender-ref ref="FirstServiceAppender"/>
</logger>
<logger name="ExternalServices.MySecondService">
<appender-ref ref="SecondServiceAppender"/>
</logger>
And in appenders
<appender type="log4net.Appender.RollingFileAppender" name="FirstServiceAppender">
<file value="c:\temp\FirstService"/>
<rollingStyle value="Composite" />
<datePattern value="_yyyy_MM_dd.lo\g"/>
<maxSizeRollBackups value="-1"/>
<maximumFileSize value="100MB"/>
....
</appender>
<appender type="log4net.Appender.RollingFileAppender" name="SecondServiceAppender">
<file value="c:\temp\SecondService"/>
<rollingStyle value="Composite" />
<datePattern value="_yyyy_MM_dd.lo\g"/>
<maxSizeRollBackups value="-1"/>
<maximumFileSize value="100MB"/>
....
</appender>
Problem
After this change, I can`t see anything from my DataAccess and Common because I had to do the same strategy with classes inside the layer.
So the logger will be loaded the same way like this:
private static readonly ILog Log = LogManager.GetLogger(typeof(UsersProvider));
I could add another logger for both projects but I need the logs from it to be written inside the same file (the log file used by the caller).
Question
I really cant separate the services into more projects because of the client.
Is there a way to use the same logger inside a library as the caller is using ? (So the DataAccess and Common writes logs into FirstServiceAppender when the service is using it.)
Or is there any pattern that would get me out of this situation ?
I don't have time to try this out right now, but this should be easier that you think it is. You can try configuring log4net to have a dynamic file name based on a GlobalContext.Properties value. In each service, put a value GlobalContext.Properties that "names" the service. This should be ok as each service is essentially a separate process, so using the GlobalContext should not result in any conflicts. This way you will need only one file target and your loggers can be configured very simply (just send the output to the one file target).
Configuration should be something like this:
<appender type="log4net.Appender.RollingFileAppender" name="RollingFileAppender">
<file type="log4net.Util.PatternString" value="C:\temp\%property{Service}"/>
<rollingStyle value="Composite" />
<datePattern value="_yyyy_MM_dd.log"/>
<maxSizeRollBackups value="-1"/>
<maximumFileSize value="100MB"/>
....
</appender>
<root>
<appender-ref ref="RollingFileAppender" />
</root>
In your code, when each service is initialized, put something like this:
GlobalContext.Properties["Service"] = "FirstService"; // for FirstService
GlobalContext.Properties["Service"] = "SecondService"; // for SecondService
Note that you must set the value into GlobalContext.Properties BEFORE anything else is done with log4net. The best place would be in the static constructor of your application/service.
This configuration should all logs generated in "FirstService" to be written to the FirstService log file and all logs generated in "SecondService" to be written to the SecondService log.
Update:
<appender name="DynamicRollingFileAppender" type="log4net.Appender.RollingFileAppender">
<file type="log4net.Util.PatternString" value="c:\temp\%property{Service}" />
<datePattern value="_yyyy_MM_dd.lo\g" />
<appendToFile value="true" />
<maxSizeRollBackups value="-1" />
<maximumFileSize value="5000KB" />
<preserveLogFileNameExtension value="true"/>
<staticLogFileName value="false" />
<countDirection value="1"/>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger [%method] - %message%newline" />
</layout>
</appender>
You can pass logger as a parameter for classes. So maybe your DataAccess classes should take a logger as a constructor parameter and use it for loggin. Then you could give a desired logger from outside.

Creating new Log file everyday and deleting previous log files

I have one windows service. For Logging purpose in that service I am using Log4Net.dll. Now my requirement is that I want to create a new log file everyday and it should keep the log of only previous 7 days. Means on 8th day, it should delete first day file and use new file. I am using appender as:
<appender name="LogFileAppender" type="log4net.Appender.RollingFileAppender">
<file type="log4net.Util.PatternString" value="D:\Log\%property{LogName}" />
<AppendToFile value="true" />
<rollingStyle value="Date" />
<maxSizeRollBackups value="100" />
<staticLogFileName value="false" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%newline %date %-5level %C.%M() - %message" />
</layout>
</appender>
And at service startup I am configuring logger as:
log4net.GlobalContext.Properties["LogName"] = "App_" + DateTime.Now.ToString("MMddyyyy") + ".log";
log4net.Config.XmlConfigurator.Configure();
So is there any functionality of Log4Net that will achieve above functionality? Or is there any other way to do it? Any type of help will be appreciated.
I'm afraid you can't: RollingFileAppender Class
A maximum number of backup files when rolling on date/time boundaries
is not supported
Have a look at this thread for other suggestions: Log4Net: set Max backup files on RollingFileAppender with rolling Date
To implement log file everyday you would use:
<rollingStyle value="Date" />
<datePattern value="yyyyMMdd" />

Categories