unable to get log4net working with .net windows service
Solution 1
By Design Log4Net is
fail-stop, we mean that log4net will not throw unexpected exceptions at run-time potentially causing your application to crash
So it is very difficult to figure out what is causing the issue .
How do I enable log4net internal debugging?
FROM FAQ - http://logging.apache.org/log4net/release/faq.html
- Internal debugging can also be enabled by setting a value in the application's configuration file (not the log4net configuration file, unless the log4net config data is embedded in the application's config file). The log4net.Internal.Debug application setting must be set to the value true. For example:
<?xml version="1.0" encoding="utf-8" ?> <configuration> <appSettings> <add key="log4net.Internal.Debug" value="true"/> </appSettings> </configuration>
This setting is read immediately on startup an will cause all internal debugging messages to be emitted.
- . To enable log4net's internal debug programmatically you need to set the log4net.Util.LogLog.InternalDebugging property to true. Obviously the sooner this is set the more debug will be produced.
So here is a custom class i created for log4Net - because config file was very confusing I created this helper class
- you can initiate as many appender you need across the applications so if one dll call other dll both can initiate appenders and both appends will work.
- also you can close the appender and ( as in case of file appender) then send it as a email
Log4NetFileHelper log = new Log4NetFileHelper(); log.Init(); //Initialize log.AddConsoleLogging(); //Add Console Logging log.AddFileLogging(Path.Combine(AssemblyDirectory, "BatchConsole.log")); log.AddFileLogging(Path.Combine(AssemblyDirectory,"BatchConsole_error.log"),log4net.Core.Level.Error);
Do set this Property to True log4net.Util.LogLog.InternalDebugging=true;
public class Log4NetFileHelper
{
private string DEFAULT_LOG_FILENAME=string.Format("application_log_{0}.log",DateTime.Now.ToString("yyyyMMMdd_hhmm"));
Logger root;
public Log4NetFileHelper()
{
}
public virtual void Init()
{
root = ((Hierarchy)LogManager.GetRepository()).Root;
//root.AddAppender(GetConsoleAppender());
//root.AddAppender(GetFileAppender(sFileName));
root.Repository.Configured = true;
}
#region Public Helper Methods
#region Console Logging
public virtual void AddConsoleLogging()
{
ConsoleAppender C = GetConsoleAppender();
AddConsoleLogging(C);
}
public virtual void AddConsoleLogging(ConsoleAppender C)
{
root.AddAppender(C);
}
#endregion
#region File Logging
public virtual FileAppender AddFileLogging()
{
return AddFileLogging(DEFAULT_LOG_FILENAME);
}
public virtual FileAppender AddFileLogging(string sFileFullPath)
{
return AddFileLogging(sFileFullPath, log4net.Core.Level.All);
}
public virtual FileAppender AddFileLogging(string sFileFullPath, log4net.Core.Level threshold)
{
return AddFileLogging(sFileFullPath, threshold,true);
}
public virtual FileAppender AddFileLogging(string sFileFullPath, log4net.Core.Level threshold, bool bAppendfile)
{
FileAppender appender = GetFileAppender(sFileFullPath, threshold , bAppendfile);
root.AddAppender(appender);
return appender;
}
public virtual SmtpAppender AddSMTPLogging(string smtpHost, string From, string To, string CC, string subject, log4net.Core.Level threshhold)
{
SmtpAppender appender = GetSMTPAppender(smtpHost, From, To, CC, subject, threshhold);
root.AddAppender(appender);
return appender;
}
#endregion
public log4net.Appender.IAppender GetLogAppender(string AppenderName)
{
AppenderCollection ac = ((log4net.Repository.Hierarchy.Hierarchy)LogManager.GetRepository()).Root.Appenders;
foreach(log4net.Appender.IAppender appender in ac){
if (appender.Name == AppenderName)
{
return appender;
}
}
return null;
}
public void CloseAppender(string AppenderName)
{
log4net.Appender.IAppender appender = GetLogAppender(AppenderName);
CloseAppender(appender);
}
private void CloseAppender(log4net.Appender.IAppender appender)
{
appender.Close();
}
#endregion
#region Private Methods
private SmtpAppender GetSMTPAppender(string smtpHost, string From, string To, string CC, string subject, log4net.Core.Level threshhold)
{
SmtpAppender lAppender = new SmtpAppender();
lAppender.Cc = CC;
lAppender.To = To;
lAppender.From = From;
lAppender.SmtpHost = smtpHost;
lAppender.Subject = subject;
lAppender.BufferSize = 512;
lAppender.Lossy = false;
lAppender.Layout = new
log4net.Layout.PatternLayout("%date{dd-MM-yyyy HH:mm:ss,fff} %5level [%2thread] %message (%logger{1}:%line)%n");
lAppender.Threshold = threshhold;
lAppender.ActivateOptions();
return lAppender;
}
private ConsoleAppender GetConsoleAppender()
{
ConsoleAppender lAppender = new ConsoleAppender();
lAppender.Name = "Console";
lAppender.Layout = new
log4net.Layout.PatternLayout(" %message %n");
lAppender.Threshold = log4net.Core.Level.All;
lAppender.ActivateOptions();
return lAppender;
}
/// <summary>
/// DETAILED Logging
/// log4net.Layout.PatternLayout("%date{dd-MM-yyyy HH:mm:ss,fff} %5level [%2thread] %message (%logger{1}:%line)%n");
///
/// </summary>
/// <param name="sFileName"></param>
/// <param name="threshhold"></param>
/// <returns></returns>
private FileAppender GetFileAppender(string sFileName , log4net.Core.Level threshhold ,bool bFileAppend)
{
FileAppender lAppender = new FileAppender();
lAppender.Name = sFileName;
lAppender.AppendToFile = bFileAppend;
lAppender.File = sFileName;
lAppender.Layout = new
log4net.Layout.PatternLayout("%date{dd-MM-yyyy HH:mm:ss,fff} %5level [%2thread] %message (%logger{1}:%line)%n");
lAppender.Threshold = threshhold;
lAppender.ActivateOptions();
return lAppender;
}
//private FileAppender GetFileAppender(string sFileName)
//{
// return GetFileAppender(sFileName, log4net.Core.Level.All,true);
//}
#endregion
private void ConfigureLog(string sFileName)
{
}
}
Solution 2
Please note that when the process is run as Windows Service, Environment.CurrentDirectory will be "C:\Windows\system32"
So if you put the log4net configuration file (log4net.config) next to your *.exe, you can use the following code to configure log4net.
var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
XmlConfigurator.Configure(new FileInfo(Path.Combine(assemblyFolder, "log4net.config")));
Solution 3
Here is the config that works for me.
AssemblyInfo.cs
[assembly: log4net.Config.XmlConfigurator(ConfigFile = "Log4net.config", Watch = true)]
Log4net.Config
<?xml version="1.0" encoding="utf-8" ?>
<log4net>
<appender name="LogFileAppender" type="log4net.Appender.RollingFileAppender,log4net">
<param name="File" value="C:\TEMP\Logs.txt"/>
<lockingModel type="log4net.Appender.FileAppender+MinimalLock,log4net" />
<appendToFile value="true" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="2" />
<maximumFileSize value="1MB" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout,log4net">
<param name="ConversionPattern" value="%d [%t] %-5p %c %m%n"/>
</layout>
</appender>
<root>
<level value="ALL" />
<appender-ref ref="LogFileAppender" />
</root>
</log4net>
C# Code
private static readonly log4net.ILog Logger = log4net.LogManager.GetLogger(typeof(class_name));
I have this setup in C# Class library project and all other project uses this project reference to log the exceptions.
Solution 4
After checking and recheck... :-)
All you need is to call XmlConfigurator.Configure();
before you create the logger (only once).
Glad to help you,
Ofir
Solution 5
If you will make a different configuration file and put log4net related things in it, then you will need to use
[assembly: log4net.Config.XmlConfigurator(ConfigFile = @"...\log4net.config", Watch = true)]
inside AssemblyInfo.cs instead of just
[assembly: log4net.Config.XmlConfigurator(Watch = true)]
Otherwise, you have to put
<log4net>
...
</log4net>
part of the configuration inside your App.config
Comments
-
Null Reference about 4 years
I have a windows service with an
app.config
and alog4net.config
.app.config
:<configSections> <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" /> </configSections> <log4net configSource="log4net.config" />
log4net.config
:<log4net> <appender name="LogFileAppender" type="log4net.Appender.RollingFileAppender"> <param name="File" value="D:\Projects\Integration\Interface Module\bin\Logs\MyFirstLogger.log"/> <lockingModel type="log4net.Appender.FileAppender+MinimalLock" /> <appendToFile value="true" /> <rollingStyle value="Size" /> <maxSizeRollBackups value="2" /> <maximumFileSize value="1MB" /> <staticLogFileName value="true" /> <layout type="log4net.Layout.PatternLayout"> <param name="ConversionPattern" value="%d [%t] %-5p %c %m%n"/> </layout> </appender> <root> <level value="ALL" /> <appender-ref ref="LogFileAppender" /> </root> </log4net>
I have added this in
AssemblyInfo.cs
too:[assembly: log4net.Config.XmlConfigurator(Watch = true)]
And in one of my classes, I have:
private readonly ILog _log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
and
_log.Info(content);
I have given all users full permissions to my Logs folder.
My bin folder (which the service is running from) has both my
app.config
andlog4net.config
.But no logging file got generated. What settings did I miss?
Updated on 4-March-2014
If you are using a separate config file like I did (log4net.config), do remember to set the
Copy to output directory
setting toCopy always
in the Solution Explorer -
Null Reference about 11 yearsI did it in my AssemblyInfo.cs [assembly: log4net.Config.XmlConfigurator(Watch = true)]
-
sgmoore about 11 yearsI think you either need to call XmlConfigurator.Configure() or else change your assemblyInfo.cs to use [assembly: log4net.Config.XmlConfigurator(Watch = true, ConfigFile="log4net.config")]
-
Null Reference about 11 yearsConfigFile = @"...\log4net.config" <- this must be the full directory? Or do I just put exactly "...\log4net.config"
-
Alpay about 11 yearsIt must be the full path of the log4net.config. if it is located in your
C:\temp
for example, you should enterC:\temp\log4net.config
I am not sure it accepts relative paths, it worths giving it a try -
Ofir about 11 yearsIt does not work for me in the AssemblyInfo.cs file. Please call 'XmlConfigurator.Configure();' before 'GetLogger'. Let me know if it still doesn't work.
-
Alpay about 11 yearsThis article explains the usage clearly. I hope it helps
-
realnero over 10 yearsin my case issue appeared to be with FileAppender. I've replaced it RollingFileAppender and it worked fine. Nothing helped before.
-
Hernaldo Gonzalez about 8 yearsOnly y change GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); and work perfect thanks man!
-
N8allan almost 7 yearsThis was it for me. Also note that for the same reason you probably don't want to use relative paths in your logging file names, as they'll end up under windows\system32, if permissions even allow writing at all.
-
andrew pate over 4 yearsGood answer. Worked for me too.
-
sox with Monica about 2 years
it is imperative to make a logging call as early as possible during the application start-up
This made me waste an entire day of work looking for bugs in two identically configured projects, one working and one not