How to append rolling index BEFORE file extension in log filename - log4net

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

Related

How can I specify an absolute file path in log4net, with a datePattern?

I want log files to be written to a directory where log files are kept. I'm using a RollingFileAppender with a datePattern. Here is what I have that doesn't work:
<?xml version="1.0" encoding="utf-8"?>
<log4net>
<appender name="RollingFile" type="log4net.Appender.RollingFileAppender">
<file value="x:\Logs\log" />
<immediateFlush value="true" />
<appendToFile value="true" />
<datePattern value="yyyyMMdd"/>
<maximumFileSize value="10MB" />
<maxSizeRollBackups value="5" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date %level %thread %logger - %message%newline" />
</layout>
</appender>
<root>
<level value="DEBUG" />
<appender-ref ref="RollingFile" />
</root>
</log4net>
I'm hoping this will result in something like:
x:\Logs\log-20211026.log
Instead I get
x:\Logs\log
Examples that I've seen use no path, e.g.:
<file value="log">
<datePattern value="yyyyMMdd"/>
Is there a way to have the data pattern, and an absolute path, and ".log" at the end?
Someone at my work had the answer:
The file name should contain the extention and 2 additional properties need to be set:
<file value="x:\Logs\log.log"/>
<preserveLogFileNameExtention value="true"/>
<staticLogFileName value="false"/>

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");

How to log in Azure Webjob with Log4net?

I have a web project and a console project. I've published my web project on Azure (after having the console app attached as a Azure Webjob to the web project).
Now I want to use Log4net to log in files. It works for the web project but I can't get it to work for the Webjob...
Here is my log4net config :
<log4net>
<appender name="FileAppender" type="log4net.Appender.RollingFileAppender">
<file type="log4net.Util.PatternString" value="./_logs/[%date{yyyy-MM-dd-HH}]_webjob.log" />
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<appendToFile value="true" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="10" />
<maximumFileSize value="4096KB" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%newline %date [%thread] %-5level %logger - %message%newline" />
</layout>
</appender>
<logger name="myloggername">
<level value="ALL" />
<appender-ref ref="FileAppender" />
</logger>
Some guy said it would work with a absolute path but it doesn't :
<file type="log4net.Util.PatternString" value="D:/home/site/wwwroot/App_Data/Logs/AccountMaintenance/log4net_%date{yyyyMMdd}.log" />
Please try the following value instead:
<file type="log4net.Util.PatternString" value="d:\home\logfiles\mylogfile.log" />

Is there a way to have log4net create log file only when there is logging activity?

We changed our log4net file name to include the current date but only want log files created on those dates that there is logged activity. This is our current configuration:
<log4net>
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
<file type="log4net.Util.PatternString" value="{0}\\logfiles\\log%date{{yyyyMMdd}}-${{COMPUTERNAME}}.log" />
<appendToFile value="true" />
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="10" />
<maximumFileSize value="10MB" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date %-5level %logger %message%newline" />
</layout>
</appender>
<root>
<level value="WARN" />
<appender-ref ref="RollingFileAppender" />
</root>
</log4net>
It's producing empty files on days when the logger is created but no messages of WARN or greater are written. Is there a configuration to prevent empty files?

log4net one file per run

I need my application to create a log file each time it runs.
My preferred format would be App.log.yyyy-MM-dd_HH-mm-ss. If that's not possible, I'd settle for App.log.yyyy-MM-dd.counter
This is my current appender configuration:
<appender name="File" type="log4net.Appender.RollingFileAppender">
<file value="App.log"/>
<rollingStyle value="Date"/>
<datePattern value=".yyyy-MM-dd_HH-mm-ss"/>
<staticLogFileName value="false"/>
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
</appender>
But it creates a random number of files based on the date and time.
I assume that the application should create only one log file every time it runs, so you do not need a rolling file appender (though my solution would apply for rolling file appenders as well):
<appender name="FileAppender" type="log4net.Appender.FileAppender">
<file type="log4net.Util.PatternString" value="c:\temp\App-%date{yyyy-MM-dd_HH-mm-ss}.log" />
<appendToFile value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%2thread] %-5level - %message%newline" />
</layout>
</appender>
(Obviously you can use other your own layout and other settings for the file appender.)
Also note that you can set your rolling style as
rollingstyle="Once"
and it will create a new file every time it is run. If staticLogFileName is set to true (e.g., logname.log) the previous logs will be set to logname.log.1, logname.log.2, etc.
The number of files kept before overwriting the oldest (say, 10) can be controlled by setting
maxSizeRollBackups="10"
Edit:
My config, which creates a datestamped log per execution (unless one exists, in which case it follows the .1 rule, looks like this:
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
<file type="log4net.Util.PatternString" value="Logs\MyLog-%date{dd-MM-yyyy}.log" />
<appendToFile value="false" />
<maxSizeRollBackups value="-1" /> <!--infinite-->
<staticLogFileName value="true" />
<rollingStyle value="Once" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%-5level %date [%thread] %c{1} - %m%n" />
</layout>
</appender>
Not 100% sure if I need appendToFile="false" as the docs say that's done automatically when you use rollingStyle="Once", but this makes it clearer in any case.
It's documented from apache in the log4net docs at:
https://logging.apache.org/log4net/release/config-examples.html
ctrl+f for "per program execution"
<appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="logfile.txt" />
<appendToFile value="false" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="-1" />
<maximumFileSize value="50GB" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />
</layout>
</appender>

Resources