Log4Net FileAppender not working - c#

We've been using Database appender (AdoNetAppender) in my company for a while. We're working on a deploy right now and not seeing any errors being persisted to the database. one thought we have is that the Database Connection is being blocked by a firewall, but you can already see where this goes into a circle of pain.
I added a RollingFileAppender, a FileAppender, tried using a bufferingForwarder, and have tried everything on stackoverflow's green world to solve this problem and absolutely nothing is changing. I even removed the reference to the AdoNetAppender and now it's just not logging errors at all, whereas with the AdoNetAppender it was logging errors twice -- once for AdoNetAppender, once for FileAppender.
My xml code is:
<root>
<level value="ALL"/>
<appender-ref ref="RollingFileAppender"/>
<appender-ref ref="AdoNetAppender"/>
</root>
<appender name="AdoNetAppender">
<!--working xml. No need to post this information-->
</appender>
<appender name="BufferingForwarder" type="log4net.Appender.BufferingForwardingAppender">
<bufferSize value="5" />
<lossy value="false" />
<appender-ref ref="fileAppender" />
<!-- or any additional appenders or other forwarders -->
</appender>
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="logs\log4net.log"/>
<datePattern value="yyyy-MM-dd'-FULL.log'" />
<appendToFile value="true"/>
<preserveLogFileNameExtension value="true"/>
<rollingStyle value="Size"/>
<maximumFileSize value="250KB"/>
<maxSizeRollBackups value="-1"/>
<staticLogFileName value="false"/>
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%date [%thread] %-5level %logger - %message%newline"/>
</layout>
</appender>
My c# code is:
(using Logger: ExceptionFilterAttribute)
private static ILog Log;
private static ILog FileLog;
private static bool _isConfigured = false;
private static void ConfigureLogger()
{
if (_isConfigured) return;
XmlConfigurator.Configure();
FileLog = LogManager.GetLogger("RollingFileAppender")
Log = LogManager.GetLogger("AdoNetAppender")
_isConfigured = true;
}
public static void Error(string message, Exception e) {
ConfigureLogger();
Log.Error(message, e);
}
public override void OnException(HttpActionExecutedContext context)
{
Error("Unexpected error occurred", context.Exception);
ConfigureLogger();
if (FileLog != null)
FileLog.Error("Unexpected Error Occurred", context.Exception);
}

Related

Class will not log to a file with log4net

I've got a MVC based C# Windows Forms application. I've got the following configuration in the app.config file:
<log4net>
<root>
<level value="ALL"/>
<appender-ref ref="LogConsoleAppender"/>
<appender-ref ref="RollingLogFileAppender"/>
</root>
<appender name="LogConsoleAppender" type="log4net.Appender.ConsoleAppender">
<layout type="QAC.Source.Services.Log.LogPatternLayout">
<conversionPattern value="%date %level [Thread: #%thread] %message [%logger -> %M]%newline"/>
</layout>
</appender>
<appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="logs/QAC_"/>
<datePattern value="yyyy-MM-dd_HH-mm-ss'.log'"/>
<staticLogFileName value="false"/>
<appendToFile value="false"/>
<rollingStyle value="Date"/>
<maxSizeRollBackups value="50"/>
<maximumFileSize value="10MB"/>
<layout type="QAC.Source.Services.Log.LogPatternLayout">
<conversionPattern value="%date %level [Thread: #%thread] %message [%logger -> %M]%newline"/>
</layout>
</appender>
</log4net>
In the main method, in the first lin, I call private static ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); and after that I initialize my main service:
mainService = MainFactory.getMainServiceInstance();
And there is the problem. All log outputs in the main method are logged successfully to the file and console, also of other services (underlying services from MainService). The only class which is not logged is the MainService. The curiosity at this is, that the logging for this class starts after some time. I don't use any filter. I've turned on the log4net debugging:
<add key="log4net.Internal.Debug" value="true"/>
, but there is no error at least. So I think, that the initialization goes through. Also if I log before I initialize the MainService, it also logs to console and file. Just this class will not log.
Any help would be very nice. Thank you in advance.
I've found the solution. I am using a custom LogPatternLayout which tries also to initialize the MainService and so the MainService is initialized before the LogPatternLayout could be read and initialized into the Logger. Therefore logging takes place after the initialization of the MainService.

programatically altering the fileappender of log4net

I am trying to set up logging using log4net, with no prior experience of log4net, in a wpf application
taken from this SO answer, I have
public partial class App : Application
{
private static readonly ILog Log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
protected override void OnStartup(StartupEventArgs e)
{
XmlConfigurator.Configure();
base.OnStartup(e);
//Set data directory
string baseDir = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + #"\BlowTrial";
if (!Directory.Exists(baseDir))
{
Directory.CreateDirectory(baseDir);
}
//Set logging
foreach (var appender in LogManager.GetRepository().GetAppenders())
{
var fileAppender = appender as FileAppender;
if (fileAppender != null)
{
fileAppender.File = fileAppender.File.Replace("|DataDirectory|", baseDir);
...
but there are no elements in LogManager.GetRepository().GetAppenders() despite the app.config having the following within the configuration node:
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,Log4net"/>
</configSections>
<log4net>
<root>
<level value="DEBUG"/>
<appender-ref ref="LogFileAppender"/>
<appender-ref ref="ColoredConsoleAppender"/>
</root>
<appender name="LogFileAppender" type="log4net.Appender.RollingFileAppender">
<param name="File" value="|DataDirectory|\log.txt"/>
<param name="AppendToFile" value="true"/>
<rollingStyle value="Size"/>
<maxSizeRollBackups value="10"/>
<maximumFileSize value="1MB"/>
<staticLogFileName value="false"/>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger: %message%newline"/>
</layout>
</appender>
<appender name="ColoredConsoleAppender" type="log4net.Appender.ConsoleAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger: %message%newline"/>
</layout>
</appender>
</log4net>
I was wondering why the appender "LogFileAppender" is not an element within the LogManager.GetRepository().GetAppenders() method, and how I might change the name of the file?
Thanks for your expertise
The RollingFileAppender does some stuff internally when it's initialized (using XmlConfigurator.Configure();), which results in the path of |DataDirectory|\log.txt throwing a System.ArgumentException when trying to retrieve the path. You can view how to debug log4net if you want more details here.
According to this answer, since you're using a special folder path anyways, you can specify this in the app.config, and not worry about setting the path from the code:
<param name="File" type="log4net.Util.PatternString" value="%envFolderPath{CommonApplicationData}\\BlowTrial\\log.txt"/>

Write a Server.MapPath in the web.config file?

Hi there i'm trying to write log for my live website and am having problems with my paths, I need to use the method Server.MapPath but i need it done in my web.config.
How would i go about this?
The file value holds the path, but i need to set a Server.MapPath on it.
<log4net>
<add key="LogFilePath1" value="../Logs/CurrentLog" id="FP1"/>
<add key="LogFilePath2" value="../Logs/CurrentLog.txt" id="FP2" />
<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="../Logs/Log.txt"/>
<appendToFile value="true"/>
<layout type="log4net.Layout.PatternLayout">
<header value="**"/>
<footer value="**"/>
<conversionPattern value="%newline%date [%thread] %-5level %logger - %message%newline" />
</layout>
</appender>
<root>
<level value="DEBUG"/>
<appender-ref ref="LogFileAppender"/>
<appender-ref ref="ConsoleAppender"/>
<appender-ref ref="RollingFileAppender"/>
</root>
<logger name="ConsoleApp.LoggingExample">
<level value="ERROR"/>
<appender-ref ref="EventLogAppender"/>
</logger>
Logger code C#:
public class Logger
{
protected static readonly ILog logger = LogManager.GetLogger(typeof(Logger));
public void logError(string message, Exception ex)
{
HttpContext.Current.Server.MapPath(Convert.ToString(ConfigurationManager.AppSettings["LogFilePath1"]));
HttpContext.Current.Server.MapPath(Convert.ToString(ConfigurationManager.AppSettings["LogFilePath2"]));
log4net.Config.XmlConfigurator.Configure();
logger.Error(message + ex);
}
public void logInfo(string message)
{
HttpContext.Current.Server.MapPath(Convert.ToString(ConfigurationManager.AppSettings["LogFilePath1"]));
HttpContext.Current.Server.MapPath(Convert.ToString(ConfigurationManager.AppSettings["LogFilePath2"]));
log4net.Config.XmlConfigurator.Configure();
logger.Info(message);
}
}
I have added C# code to Server.MapPath the Keys, i'm just struggling calling the keys in thhe file value =
Store your path in the config as
<add key="LogFilePath1" value="~/Logs/CurrentLog" id="FP1"/>
From your code read the key
string path = GetPath("LogFilePath1");
string fullPath = System.Web.HttpContext.Server.MapPath(path);
Log4net does not use Server.Map path when reading the paths from your configuration files. It does not know it is running in a web context. I geuss you can implement your own version of the Rolling File Appender and override the function which gets the path from the config. However I would just use the full paths to the log locations. Normally you do want to log on an other disk your application is running to prevent running out of diskspace and killing your application.

log4net logging in different files

Two instances of the same program are configured to log in separate files, here is my log4net.config:
<log4net>
<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="[%utcdate] %-5level %logger: %message%newline%exception"/>
</layout>
</appender>
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
<file type="log4net.Util.PatternString" value="Log/svc-%property{ServiceName}"/>
<appendToFile value="true"/>
<rollingStyle value="Date"/>
<datePattern value="'-'yyyy'-'MM'-'dd'.log'"/>
<staticLogFileName value="false"/>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="[%utcdate] %-5level %logger: %message%newline%exception"/>
</layout>
</appender>
<root>
<level value="DEBUG"/>
<appender-ref ref="ConsoleAppender"/>
<appender-ref ref="RollingFileAppender"/>
</root>
</log4net>
And here's how I instance the logs:
log = LogManager.GetLogger(ServiceName);
GlobalContext.Properties["ServiceName"] = ServiceName;
XmlConfigurator.ConfigureAndWatch(new FileInfo("log4net.config"));
Now, the services are called stuff like "Service1" "Service10" "Service2".
When I start services 1 and 10, the ones I'm testing with, they both create their log files:
svc-BettweenSvc1-2011-07-26.log
svc-BettweenSvc10-2011-07-26.log
But when the second service is started, the logs from the first one start being appended to the second log, and that one is no longer used.
How can I log to separate log files properly in windows services using log4net?
I believe the problem is that you only have one log4net Repository configured (most likely the default one). When you change the log4net log file name, therefore, all loggers start logging to the new file name.
I believe that you will need to configure separate repositories for each separate log file you want active at the same time.
I'm sorry I can't help more, I'm struggling with almost the same issue right now (among other, more pressing, issues).
Good luck!
edit:
check out this question/answer for a possible solution:
how-to-stop-log4net-from-writing-to-two-separate-files
For the record, this works, but it's not what I'm testing against, it still doesn't work in my service, I'll just post it to hopefully help others though:
namespace log4netMultiLogTester
{
public static class Program
{
public static void Main(string[] args)
{
if (args.Length == 0)
{
Process.Start(new ProcessStartInfo("log4netMultiLogTester.exe", "testApp1"));
Process.Start(new ProcessStartInfo("log4netMultiLogTester.exe", "testApp2"));
}
else
{
var logId = args[0];
var log = LogManager.GetLogger(logId);
GlobalContext.Properties["ServiceName"] = logId;
XmlConfigurator.ConfigureAndWatch(new FileInfo("log4net.config"));
log.Info("Starting log: {0}".FormatWith(logId));
do
{
log.Info("Log: {0}, latest entry is {1}".FormatWith(logId,DateTime.Now.Ticks));
} while (Console.ReadKey().Key != ConsoleKey.R);
}
}
}
public static class StringExtensions
{
public static string FormatWith(this string text,params object[] args)
{
return string.Format(text, args);
}
}
}
<log4net>
<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="[%utcdate] %-5level %logger: %message%newline%exception"/>
</layout>
</appender>
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
<file type="log4net.Util.PatternString" value="Log/svc-%property{ServiceName}"/>
<appendToFile value="true"/>
<rollingStyle value="Date"/>
<datePattern value="'-'yyyy'-'MM'-'dd'.log'"/>
<staticLogFileName value="false"/>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="[%utcdate] %-5level %logger: %message%newline%exception"/>
</layout>
</appender>
<root>
<level value="DEBUG"/>
<appender-ref ref="ConsoleAppender"/>
<appender-ref ref="RollingFileAppender"/>
</root>
</log4net>

log4net not working in dll

I'm currently having issues with getting log4net to work within a particular dll. I'm currently using log4net in other dlls being called by my test app and logging is working fine within those dlls and also within my test app. It's this one particular dll that I'm having trouble with. Here is snippet of code from the dll I'm having trouble with.
//This is from ABC.dll
public class SessionFactory
{
protected static ISessionFactory sessionFactory;
private static readonly ILog log = LogManager.GetLogger(typeof(SessionFactory));
private static void Init()
{
try
{
//Read the configuration from hibernate.xml.cfg or app.config
Configuration normalConfig = new Configuration().Configure();
ConfigureNhibernateValidator(normalConfig);
log.Debug("Initializing session factory");
sessionFactory = Fluently.Configure(normalConfig)
.Mappings(m =>
m.FluentMappings
.AddFromAssemblyOf<OrderHeaderMap>()
.Conventions.AddFromAssemblyOf<PascalCaseColumnNameConvention>())
.ProxyFactoryFactory("NHibernate.ByteCode.LinFu.ProxyFactoryFactory, NHibernate.ByteCode.LinFu")
.BuildSessionFactory();
log.Debug("Finished initializing the session factory");
}
catch(Exception ex)
{
//Code not shown
}
}
}
In my test app I am calling:
log4net.Config.XmlConfigurator.Configure();
Here is my log4net configuration in my App.config file:
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
</configSections>
<log4net>
<!-- ALL|DEBUG|INFO|WARN|ERROR|FATAL|OFF -->
<root>
<level value="DEBUG"/>
<appender-ref ref="SpeedTest"/>
</root>
<!-- This is a default logger that nhibernate uses to push out all the SQL statements to-->
<logger name="NHibernate.SQL" additivity="false">
<level value="DEBUG"/>
<appender-ref ref="NHibernateConsoleLog"/>
<appender-ref ref="NHibernateFileLog"/>
</logger>
<!-- This is a default logger that nhibernate uses to push out all the debugging type information to-->
<logger name="NHibernate" additivity="false">
<level value="DEBUG"/>
<appender-ref ref="NHibernateFileLog"/>
</logger>
<appender name="NHibernateConsoleLog" type="log4net.Appender.TraceAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline"/>
</layout>
</appender>
<appender name="NHibernateFileLog" type="log4net.Appender.RollingFileAppender">
<file value="Logs/nhibernate.txt" />
<appendToFile value="true" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="10" />
<maximumFileSize value="10MB" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%d{HH:mm:ss.fff} [%t] %-5p %c - %m%n" />
</layout>
</appender>
<appender name="SpeedTest" type="log4net.Appender.RollingFileAppender">
<file value="Logs/SpeedTest.txt" />
<appendToFile value="true" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="10" />
<maximumFileSize value="10MB" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%d{HH:mm:ss.fff} [%t] %-5p %c - %m%n" />
</layout>
</appender>
</log4net>
</configuration>
Again logging is working fine within my test application using the SpeedTest appender but the logging within the above snippet of code is not working. I set breakpoints above on when it initializes the logger and it seems to hit it. I can post the log4net debug output if necessary but I didn't really see much. Just let me know if you need it and I will post.
Any suggestions as to why logging is not being recorded in the above snippet of code?
It seems that this issue was stemming from me changing the directory to all my external dependencies (log4net being one of them) awhile back in TFS. All I did was drop all my references in my visual studio project and re-add them from my new dependencies folder and everything worked as expected after this. Thanks for all those that helped here.
My suspicion would be that it isn't reading the configuration from the configuration file when you call configure.
If you add the following lines to your application, what do you see (either on the console, or in IDE output window, or by stepping through in the debugger):
var log4netConfig = ConfigurationManager.GetSection("log4net");
var log4netConfigIsNull = log4netConfig == null;
Console.WriteLine(log4netConfigIsNull);
Does it look like the configuration is actually available from the configuration file?
[Edit: in response to your comment]
If you now add another line of debug code to your app:
Console.WriteLine(log.IsDebugEnabled);
what output do you get? Does the logger think it is configured for debug logging? (I'm particularly interested in the behaviour of this in, or after, SessionFactory.Init).
The immediate thought would be that your logging code isn't getting hit, possibly due to an exception being thrown prior to your first log4net call. Can you put a log entry into a finally block, just to test that the logger works?

Categories

Resources