Creating new Log file everyday and deleting previous log files - c#

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" />

Related

How to create new log4net every day if service running continuously from many days

I have implemented log4net in my windows service and it works as expected and created new file with current date as per config setting.
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,Log4net" />
</configSections>
<log4net>
<appender name="file" type="log4net.Appender.RollingFileAppender">
<file type="log4net.Util.PatternString" value="Logs\log-%utcdate{yyyy-MM-dd}.txt" />
<staticLogFileName value="false" />
<appendToFile value="true" />
<rollingStyle value="Composite" />
<maxSizeRollBackups value="5" />
<maximumFileSize value="5MB" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %level %logger - %message%newline" />
</layout>
<param name="DatePattern" value="dd.MM.yyyy'.log'" />
</appender>
<root>
<level value="ALL" />
<appender-ref ref="file" />
</root>
</log4net>
Problem here is that, if my service is running from last 2 days, so it will not create new file with current date it keep reference of 2 days older file and adding logs into older file instead of create new file for that day.
Logger code is like
public static class Logger
{
public static log4net.ILog Log { get; set; }
static Logger()
{
Log = log4net.LogManager.GetLogger(typeof(System.Reflection.MethodBase));
}
public static void Trace(string message)
{
Log.Info(message);
}
public static void LogException(Exception ex)
{
StringBuilder builer = new StringBuilder();
builer.AppendLine("=============Exception===========");
builer.AppendLine("Exception: {0}");
builer.AppendLine("StackTrack: {1}");
Log.ErrorFormat(builer.ToString(), ex.Message, ex.StackTrace);
}
}
To log info into log file I am using code
Logger.Trace("Hello");
What is code level changes require for me to, create new log file every day even service/desktop application is running continuously from last many days?
Your configuration has both <staticLogFileName value="false" /> and <staticLogFileName value="true" />, which is may explain why it's not rolling correctly.
I suggest that you remove the <staticLogFileName value="true" /> and change the file and DatePattern as follows:
<file value="Logs\log-" />
...
<param name="DatePattern" value="yyyy-MM-dd'.log'" />
With staticLogFileName false, the date string will be appended to the base file name to give e.g.:
Logs\log-2018-01-30.log
I would note however that log4net will only check if it needs to roll the log file when you actually log a message, so if you aren't logging frequently, it may not roll the moment the next day begins.

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...

Log4Net: RollingFileAppender, new instead of override

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>

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.

Log4Net - Change Log File Folder Dynamically [duplicate]

I want to save all logs during each day in folder named YYYYMMdd - log4net should handle creating new folder depending on system datetime - how I can setup this?
I want to save all logs during the day to n files of 1MB - I don't want to rewrite old files but to really have all logs during one day - how I can setup this?
I am usin C#
Regards
Alex
Try this (It should be OK!):
<appender name="LogFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="logs\\" />
<appendToFile value="true" />
<DatePattern value="yyyy\\\\MM\\\\dd'.inf.log'" />
<rollingStyle value="Date" />
<param name="StaticLogFileName" value="false" />
<layout type="log4net.Layout.PatternLayout">
<header value="[Header]
" />
<footer value="[Footer]
" />
<conversionPattern value="%date [%thread] %-5level %logger [%ndc] <%property{auth}> - %message%newline" />
</layout>
</appender>
It will create a logfile named 'logs\2010\04\02.inf.log' (let date be 2010-04-02)
Thank you all.
We created SortByFolderFileAppender, which inherit from RollingFileAppender
Example of final result:
somewhere\Logs\20100305\Client-104615.0
namespace CustomLogging
{
public class SortByFolderFileAppender : log4net.Appender.RollingFileAppender
{
protected override void OpenFile(string fileName, bool append)
{
//Inject folder [yyyyMMdd] before the file name
string baseDirectory = Path.GetDirectoryName(fileName);
string fileNameOnly = Path.GetFileName(fileName);
string newDirectory = Path.Combine(baseDirectory, DateTime.Now.ToString("yyyyMMdd"));
string newFileName = Path.Combine(newDirectory, fileNameOnly);
base.OpenFile(newFileName, append);
}
}
}
<appender name="SortByFolderFileAppender" type="CustomLogging.SortByFolderFileAppender">
<file type="log4net.Util.PatternString" value="Logs\Client"/>
<appendToFile value="true"/>
<rollingStyle value="Composite"/>
<datePattern value="-HHmmss"/>
<maxSizeRollBackups value="40"/>
<maximumFileSize value="1MB"/>
<countDirection value="1"/>
<encoding value="utf-8"/>
<staticLogFileName value="false"/>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date{HH:mm:ss.fff}|%-5level|%message%newline"/>
</layout>
</appender>
I believe, you may create your own appender, based on the FileAppender class. You may need to override the OpenFile method to create a file in the right location.
You could use the rollinglogfileappender which creates files named by date and starts a new file at midnight. Then just write a script that moves them to a correct map at 00.01.
As for logging all files during one day with a maximum of 1 MB per file, here's an example:
<appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
<file type="log4net.Util.PatternString" value="Logging\\MWLog"/>
<appendToFile value="true"/>
<rollingStyle value="Composite"/>
<datePattern value="-yyyyMMdd"/>
<maxSizeRollBackups value="-1"/>
<maximumFileSize value="1MB"/>
<countDirection value="1"/>
<encoding value="utf-8"/>
<staticLogFileName value="false"/>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date{HH:mm:ss.fff}|%-5level|%message%newline"/>
</layout>
</appender>
To build from the answer above using the SortByFolderFileAppender.
This is how we resolved the issue using rolling date for log filenames. I changed the staticLogFileName to true so the entire filename is passed into the OpenFile method.
If the filename ends in ".log" then nothing needs to be appended. I'm guessing some kind of locking has occurred and I want log4net to try using the same filename again, hoping the previous lock has been released.
Although, I'm not sure if this could end up causing an infinite call to OpenFile if the file is locked and won't let go of it. We did create a web service using the producer consumer pattern to log everything in one location from all applications in the system, which is currently ten and growing.
We don't need to include log4net into any of the other applications but we needed to create a web client class that is accessible by all applications to use for logging to the web service.
The result for the filename is "Logs\Client\2017\11\08.log" and obviously changes everyday.
protected override void OpenFile( string fileName, bool append )
{
// append "\yyyy\mm\dd.log" to create the correct filename.
if ( !fileName.EndsWith( ".log") )
fileName = $#"{fileName}\{DateTime.Now:yyyy\\MM\\dd}.log";
base.OpenFile( fileName, append );
}
Modification of the configuration from above.
<appender name="xxxRollingFileAppender" type="namespace.xxxRollingFileAppender">
<file value="Logs\Client"/>
<staticLogFileName value="true"/>
<appendToFile value="true"/>
<maxSizeRollBackups value="40"/>
<maximumFileSize value="1MB"/>
<encoding value="utf-8"/>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date{HH:mm:ss.fff}|%-5level|%message%newline"/>
</layout>
</appender>

Categories