Pass dynamic value to appender - log4net

I am creating different reports and trying to pass the report name and append it to the name of the log4net report. The report name will be different each time the report is run so it will be dynamically assigned.
I've tried using the LOG4NET.GLOBALCONTEXT.PROPERTIES("RptName") = sReportName", but all I get is a 'null' value in the report title.
class Program
{
static void Main(string[] args)
{
log4net.Config.XmlConfigurator.Configure();
log4net.ILog log = log4net.LogManager.GetLogger(typeof(Program));
log4net.GlobalContext.**Properties("RptName")** = sReportName
log.Info("this is an info message");
Console.ReadLine();
}
}
<!--RollingFileAppender: Provides output of all log entries to a file in the \logs directory
Filename: RSGetReport_yyyyMMdd_hh:mm:ss_processID.txt-->
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
<file type="log4net.Util.PatternString" value="logs\RSGetReport_%date{yyyyMMdd}_%date{hhmmss}_%processid**_%property{myContext}.**txt" />
<appendToFile value="true" />
<rollingStyle value="Once" />
<maxSizeRollBackups value="10" />
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="ALL" />
</filter>
<maximumFileSize value="1MB" />
<countDirection value="1" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
</layout>
</appender>strong text

You need to set the global property before configuring log4net. See also this question.

Related

log4net with asp.net core 2

i'm using log4net to create log files dynamicaly , i tried the following steps here http://geekswithblogs.net/rgupta/archive/2009/03/03/dynamic-log-filenames-with-log4net.aspx but i'm getting (null).txt file , Here is my log4net.config file
`<log4net>
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
<file type="log4net.Util.PatternString" value="app_data/log/%date{yyyy-MM-dd}/%property{LogName}.txt" />
<rollingStyle value="Date" />
<appendToFile value="true" />
<rollingStyle value="Size" />
<datePattern value="yyyyMMdd" />
<maxSizeRollBackups value="10" />
<maximumFileSize value="10000KB" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value=" %-5level %date{dd-mm-yyyy HH:mm:ss} %logger [%thread] - %message %exception%newline%property{LogName}" />
</layout>
</appender>
<root>
<appender-ref ref="RollingFileAppender" />
<level value="All" />
</root>
</log4net>`
and this is my test code
log4net.GlobalContext.Properties["LogName"] = "xx#xx.xx";
As i said i'm getting (null).txt FileName instead of xx#xx.xx.txt , thanks for helping
I just tested your code and its working just fine, so I can only assume, that you are assigning your GlobalContext property to late. Remember, to set it before you call XmlConfigurator.Configure method. Set it up in your Program.cs file like this:
public static class Program
{
public static void Main(string[] args)
{
// ...
GlobalContext.Properties["LogName"] = "xx#xx.xx";
XmlConfigurator.Configure(new FileInfo("log4net.config"));
// ...
}
}

log4Net filtering for multiple outputs confusion

Trying to understand the log4net filtering.
After reading the docs some aspects are still elusive to me.
For example I have this config file:
<?xml version="1.0" encoding="utf-8" ?>
<log4net>
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="..\Logs\CurrentLog" />
<appendToFile value="true" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="10" />
<maximumFileSize value="10000" />
<staticLogFileName value="true" />
<filter type="log4net.Filter.LevelRangeFilter">
<acceptOnMatch value="true" />
<levelMin value="INFO" />
<levelMax value="FATAL" />
</filter>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%-5level %date [%thread] %-22.22c{1} - %m%n" />
</layout>
</appender>
<appender name="LogFileAppender" type="log4net.Appender.FileAppender">
<file value="log-file.txt" />
<appendToFile value="true" />
<layout type="log4net.Layout.PatternLayout">
<header value="Service Logging -- Start" />
<footer value="Service Logging -- End" />
<conversionPattern value="%date [%thread] %-5level %logger [%ndc]
<%property{auth}> - %message%newline" />
</layout>
</appender>
<appender name="EventLogAppender" type="log4net.Appender.EventLogAppender" >
<applicationName value="WindowsService1.exe" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger
[%property{NDC}] - %message%newline" />
</layout>
</appender>
<!-- Set the default logging level and add the active appenders -->
<root>
<level value="DEBUG" />
<appender-ref ref="LogFileAppender" />
<appender-ref ref="RollingFileAppender" />
</root>
<!-- Specify the level for specific categories (“namespace.class”)-->
<logger name="WindowsService1.MyMonitor">
<level value="WARN" />
<appender-ref ref="EventLogAppender" />
</logger>
</log4net>
My expectations were:
The RollingFileAppender has a range of [INFO:FATAL] The Root has a
Level of DEBUG so it would let DEBUG and "greater" pass. Which
means all of RollingFileAppender's range would go through.
The LogFileAppender has no range specified so it would use Root's of DEBUG or greater.
And the EventLogAppender would only send event messages of WARN or greater to the Windows Event System - and - they would only
be messages from the class "WindowsService1.MyMonitor".
However it appears that all the messaging gets filtered to the WARN level!
Including my rolling log files and the log file "log-file.txt"
This seems like it should be simple - don't know why I'm so confused by it.
Hope someone can enlighten me.
Please feel free to use crayons and pictures because I think I need them.
Thanks.
UPDATE
In my Program.cs I have:
[assembly: log4net.Config.XmlConfigurator(ConfigFile = "Log4Net.config", Watch = true)]
And in each class where logging is done:
private static readonly ILog log =
LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
UPDATE 2
At a different computer now. Had to recreate everything and used log4net debugging to assist.
But still can't get the desired output.
Basically want the WARN and above messages to go to one file and the Event logger. And those messages would be a subset of all the INFO and above messages.
The INFO and above messages - superset - would go into the rolling appender and overwrite themselves eventually. But the warnings and errors would always be maintained.
So here is a rework of all the files for a simple service. If I set WARN on the appender-ref ref=EventLogAppender then all the INFOs are suppressed.
Program.cs
[assembly: log4net.Config.XmlConfigurator(ConfigFile = "Log4Net.config", Watch = true)]
// Ref: http://www.c-sharpcorner.com/UploadFile/naresh.avari/develop-and-install-a-windows-service-in-C-Sharp/
//
// use 'sc' to install/delete the service
// run 'sc' as administrator
// sc create "MySillyService" binpath= "C:\whatever\something.exe"
// sc delete "MySillyService"
namespace SimpleService1
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main()
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new Service1()
};
ServiceBase.Run(ServicesToRun);
}
}
}
Service1.cs
namespace SimpleService1
{
public partial class Service1 : ServiceBase
{
private static readonly ILog log =
LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private Timer timer1;
private int counter = 0;
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
timer1 = new Timer();
timer1.Interval = 4000;
timer1.Elapsed += new ElapsedEventHandler(timer1_Tick);
timer1.Enabled = true;
log.Info("my service is started");
}
private void timer1_Tick(object sender, ElapsedEventArgs e)
{
counter++;
if (counter%2 == 0)
{
log.Info(String.Format("Counter({0:D}) is now even", counter));
}
else
{
log.Error(String.Format("Counter({0:D}) is now even", counter));
}
}
protected override void OnStop()
{
timer1.Enabled = false;
log.Info("my service was stopped");
}
}
}
App.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<appSettings>
<add key="log4net.Internal.Debug" value="true"/>
</appSettings>
<system.diagnostics>
<trace autoflush="true">
<listeners>
<add
name="textWriterTraceListener"
type="System.Diagnostics.TextWriterTraceListener"
initializeData="C:\tmp\log4net.txt" />
</listeners>
</trace>
</system.diagnostics>
</configuration>
Log4net.config
<?xml version="1.0" encoding="utf-8" ?>
<!--
Ref: http://mitch-wheat.blogspot.com/2007/04/log4net-net-logging-tool.html
I keep this config file in a separate directory and copy it with a
post-build event:
copy /Y $(SolutionDir)Logger\Log4Net.config $(TargetDir)Log4Net.config
-->
<log4net>
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="..\Logs\CurrentLog" />
<appendToFile value="true" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="10" />
<maximumFileSize value="10000" />
<staticLogFileName value="true" />
<filter type="log4net.Filter.LevelRangeFilter">
<acceptOnMatch value="true" />
<levelMin value="INFO" />
<levelMax value="FATAL" />
</filter>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%-5level %date [%thread] %-22.22c{1} - %m%n" />
</layout>
</appender>
<appender name="LogFileAppender" type="log4net.Appender.FileAppender">
<file value="log-file.txt" />
<appendToFile value="true" />
<layout type="log4net.Layout.PatternLayout">
<header value="Service Logging -- Start - " />
<footer value="Service Logging -- End - " />
<conversionPattern value="%date [%thread] %-5level %logger [%ndc]
<%property{auth}> - %message%newline" />
</layout>
</appender>
<appender name="EventLogAppender" type="log4net.Appender.EventLogAppender" >
<applicationName value="Service1" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger
[%property{NDC}] - %message%newline" />
</layout>
</appender>
<!-- Set the default logging level and add the active appenders -->
<root>
<level value="DEBUG" />
<appender-ref ref="LogFileAppender" />
<appender-ref ref="RollingFileAppender" />
</root>
<!-- Specify the level for specific categories (�namespace.class�)-->
<logger name="SimpleService1.Service1">
<level value="WARN" />
<appender-ref ref="EventLogAppender" />
</logger>
</log4net>
Thanks for your help
Finally figured out the nuances to get this working as desired. Here's the config for anyone interested.
<?xml version="1.0" encoding="utf-8" ?>
<!--
I keep this config file in a separate directory and copy it with a
post-build event:
copy /Y $(SolutionDir)Logger\Log4Net.config $(TargetDir)Log4Net.config
-->
<log4net>
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="..\Logs\CurrentLog" />
<appendToFile value="true" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="10" />
<maximumFileSize value="10000" />
<staticLogFileName value="true" />
<filter type="log4net.Filter.LevelRangeFilter">
<acceptOnMatch value="true" />
<levelMin value="INFO" />
<levelMax value="FATAL" />
</filter>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%-5level %date [%thread] %-22.22c{1} - %m%n" />
</layout>
</appender>
<appender name="LogFileAppender" type="log4net.Appender.FileAppender">
<file value="log-file.txt" />
<appendToFile value="true" />
<filter type="log4net.Filter.LevelRangeFilter">
<acceptOnMatch value="true" />
<levelMin value="WARN" />
<levelMax value="FATAL" />
</filter>
<layout type="log4net.Layout.PatternLayout">
<header value="Service Logging -- Start - " />
<footer value="Service Logging -- End - " />
<conversionPattern value="%date [%thread] %-5level %logger [%ndc]
<%property{auth}> - %message%newline" />
</layout>
</appender>
<appender name="EventLogAppender" type="log4net.Appender.EventLogAppender" >
<!-- Put whatever name you want to display in the event log
for 'applicationName value=XX'
-->
<applicationName value="ServiceSkippy" />
<filter type="log4net.Filter.LevelRangeFilter">
<acceptOnMatch value="true" />
<levelMin value="WARN" />
<levelMax value="FATAL" />
</filter>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger
[%property{NDC}] - %message%newline" />
</layout>
</appender>
<!-- put namespace of service application in following name -->
<logger name="ServiceWithLog4Net">
<appender-ref ref="LogFileAppender" />
<appender-ref ref="RollingFileAppender" />
<appender-ref ref="EventLogAppender" />
</logger>
</log4net>
-Skippy

Log4Net: how to avoid Dummy entry created in Eventlog

I have created a sample program and every time I run this program, it is creating a dummy entry in the event log as below. How to avoid without creating a logger?
2014-02-24 18:04:53,557 [8] ERROR Log4NetSample.Program [(null)] - Error message
My Code:
using log4net;
using log4net.Config;
namespace Log4NetSample
{
class Program
{
static void Main(string[] args)
{
Program pg= new Program();
pg.Log4netCode();
}
private void Log4netCode()
{
XmlConfigurator.Configure();
ILog log = LogManager.GetLogger(typeof(Program));
log.Debug("Debug message");
log.Info("Info message");
log.Warn("Warning message");
log.Error("Error message");
log.Fatal("Fatal message");
}
}
}
Config file:
<log4net>
<appender name="LogFileAppender" type="log4net.Appender.RollingFileAppender">
<param name="File" value="C:\Log\MyFirstLogger.log"/>
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<appendToFile value="true" />
<rollingStyle value="Date" />
<maxSizeRollBackups value="2" />
<maximumFileSize value="2KB" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%d [%t] %-5p %c %m%n"/>
</layout>
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="DEBUG" />
<levelMax value="WARN" />
</filter>
</appender>
<appender name="EventLogAppender" type="log4net.Appender.EventLogAppender">
<Eventid value="100"/>
<LogName value="Log4NetSample" />
<applicationName value="Log4NetSample" source="Api" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />
</layout>
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="ERROR" />
<levelMax value="ERROR" />
</filter>
</appender>
<root>
<level value="ERROR" />
<appender-ref ref="LogFileAppender" />
<appender-ref ref="EventLogAppender" />
</root>
</log4net>
You message is the actual to message from the line log.Error. You do not need to log or test you logger right after init the config.

how to configure static log file name with compositely named roll backups

I used this config but a date is always added to the current file ('log.20130805.0.log').
<appender name="LogFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="Logs/logFile.log" />
<appendToFile value="true" />
<preserveLogFileNameExtension value="true" />
<rollingStyle value="Composite" />
<datePattern value=".yyyyMMdd" />
<maximumFileSize value="10MB" />
<countDirection value="1"/>
<maxSizeRollBackups value="-1" />
<staticLogFileName value="false" />
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%date [%thread] %-5level %logger - %message%newline" />
</layout>
</appender>
The result of that config is :
log.20130805.0.log
log.20130805.1.log
log.20130805.2.log
log.20130805.3.log
What I get with staticLogFileName = true is :
log.log
log.1.log
log.2.log
log.3.log
What I want is :
log.log
log.20130805.1.log
log.20130805.2.log
log.20130805.3.log
I know I'm late to the party, but I believe I have figured out how to use a composite RollingFileAppender properly. I'm posting it here for posterity, in case anyone stumbles upon this in a search:
<appender name="rollingfileappender" type="log4net.Appender.RollingFileAppender">
<file value="C:\Logs\logfile.log" />
<datePattern value=".yyyyMMdd" />
<preserveLogFileNameExtension value="true" />
<appendToFile value="true" />
<rollingStyle value="Composite" />
<maxSizeRollBackups value="10" />
<maximumFileSize value="100Kb" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.DynamicPatternLayout">
<conversionPattern value="%[level] - %date - %message" />
</layout>
</appender>
The key here is:
<preserveLogFileNameExtension value="true" />
and
<staticLogFileName value="true" />
When your current log files are being appended, you'll see:
logfile.log
logfile.1.log
logfile.2.log
etc...
Once the new day hits, those should be renamed to:
logfile.20200623.log
logfile.20200623.1.log
logfile.20200623.2.log
etc...
and you'll have a new logfile.log, still catching your current logs.
You can use the function below.
This function first gets the file location that you set in web.config and after that you can add any path that you want! (like Date or Customer or...)
WebConfig:
<appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="C:\\t4\\"/>
<appendToFile value="true"/>
<rollingStyle value="Composite"/>
<datePattern value="_yyyy-MM-dd.lo'g'"/>
<maxSizeRollBackups value="10"/>
<maximumFileSize value="1MB"/>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date User:%identity IP:%X{addr} Browser: %X{browser} Url: %X{url} [%thread] %-5level %c:%m%n"/>
</layout>
</appender>
Function:
public static void ChangeFileLocation(string _CustomerName,string _Project)
{
XmlConfigurator.Configure();
log4net.Repository.Hierarchy.Hierarchy h =(log4net.Repository.Hierarchy.Hierarchy)LogManager.GetRepository();
foreach (IAppender a in h.Root.Appenders)
{
if (a is FileAppender)
{
FileAppender fa = (FileAppender)a;
string sNowDate= DateTime.Now.ToLongDateString();
// Programmatically set this to the desired location here
string FileLocationinWebConfig = fa.File;
string logFileLocation = FileLocationinWebConfig + _Project + "\\" + CustomerName + "\\" + sNowDate + ".log";
fa.File = logFileLocation;
fa.ActivateOptions();
break;
}
}
}
and result is like this: C:\t4\TestProject\Customer1\Saturday, August 31, 2013.log
Based on these tips I guess it isn't possible, unfortunately (with the current implementation of RollingFileAppender):
http://geekswithblogs.net/rgupta/archive/2009/03/03/tips-on-using-log4net-rollingfileappender.aspx

How to generate file with name yyyyMMdd.2.log with log4net

Here is the appender I used in app.config, it will generate files like 20120501.log.1, while what I expected is 20120501.1.log.
<appender name="LogFileAppender" type="log4net.Appender.RollingFileAppender">
<lockingModel type="log4net.Appender.FileAppender+MinimalLock"/>
<file value="logs\" />
<appendToFile value="true" />
<rollingStyle value="Composite" />
<datePattern value="yyyyMMddt'.log.'" />
<countDirection value="1" />
<maxSizeRollBackups value="100" />
<maximumFileSize value="1000kb" />
<staticLogFileName value="false" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />
</layout>
</appender>
This functionality is part of version 1.2.11. There is a new setting for the rolling file appender:
<preserveLogFileNameExtension value="true"/>
Here is the link to the JIRA issue:
https://issues.apache.org/jira/browse/LOG4NET-64
In order to do this first you need to set your config file:
<appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender,log4net">
<File type="log4net.Util.PatternString" value="App_Data/%property{LogName}" />
...
</appender>
Then in your Global.asax file you set your LogName details:
private static readonly log4net.ILog log = log4net.LogManager.GetLogger("Global.asax");
void Application_Start(object sender, EventArgs e)
{
// Set logfile name and application name variables
log4net.GlobalContext.Properties["LogName"] = String.Format("{0}.2.log",DateTime.Now.ToString("yyyyMMdd"))
...
}

Resources