I have a rather large program that have some odd behaviour once in a while. After it has been deployed at a customer it's not possible to do debugging. But it is permissible to use log files, so this is what I have created. Something like this:
TextWriter tw = new StreamWriter(#"C:\AS-log.txt", true);
tw.WriteLine("ValidateMetaData");
tw.Close();
3 lines like this has been inserted into the code at many places and do give excellent log information. There are 2 problems with this approach however:
The code looks very messy when there are more lines regarding logging than actual code.
I would like to be able to switch logging on and off via a configuration file.
Any suggestions to a way of logging that can do this and still be simple?
Maybe you could try Enterprise libraries from Microsoft. It has a logging application block which works quite nice
http://msdn.microsoft.com/en-us/library/ff648951.aspx
Log4net is a simple framework that you can utilize.
http://logging.apache.org/log4net/
I would suggets to use log4Net. It has a huge potential, that you probbaly don't need, but give you easy predefined formatting in loog entries.
Before use it yuo should configure it your application's .config file.
This is just an example how to do, you can use others that easily can find on internet:
<log4net debug="true">
<appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="Logs\\TestLog.txt" />
<appendToFile value="true" />
<rollingStyle value="Date" />
<maxSizeRollBackups value="10" />
<maximumFileSize value="10MB" />
<staticLogFileName value="false" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%-5p %d %5rms %-22.22c{1} %-18.18M - %m%n" />
</layout>
</appender>
<root>
<level value="DEBUG" />
<appender-ref ref="RollingLogFileAppender" />
</root>
</log4net>
Regards.
You can use a Listener of System.Diagnostics.Debug and System.Diagnostics.Trace.
Normally these are controlled by compile options but you can attach the listener depending on your config option.
System.Diagnosics.Trace.WriteLine("ValidateMetaData");
This also allows you to watch live with DebugView, etc.
A simple solution would be to make the log writing a class. On application startup it opens the file for writing to, and there is a simple method Write. You can then simply use Log.Write("ValidateMetaData") which reduces the amount of code that you use inline, and stops you having to always open and close the file. You can also add checks depending on configuration (the easiest way to do that would be with application settings).
Try log4net or nlog (I prefer nlog)
http://logging.apache.org/log4net/
http://nlog-project.org/
If you want something built-in and configurable from config-file see http://msdn.microsoft.com/en-us/library/ms228993.aspx
Related
I am using log4net for to create logs of my app. One of my client reported that from few days on logs are not writing to log text file. When I go thorough the issue I found that Logs are logged to given location for few seconds and then log path automatically changing to installation folder and then continue.
My config is like this
<appender name="MessageRollingFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="Logs\log.txt" />
<appendToFile value="true" />
<rollingStyle value="Size" />
<encoding value="utf-8" />
<maxSizeRollBackups value="2" />
<maximumFileSize value="5MB" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%message%newline%newline" />
</layout>
</appender>
Predefined log path is set to
C:\Users\testuser\AppData\Roaming
If I change the log.txt path to the Downloads folder. There will be no issue.
I checked. There are no permission issues. Like I said logs happen to write for few seconds.
There were no errors in the app. This is c# standalong app. Why this path chaning happen?
Check if the root tag of logger is pointed to your appender name,
<root>
<level value="ALL"/>
<appender-ref ref="MessageRollingFileAppender"/>
</root>
Also, Make sure you check the size of the file that is getting generated, if more logs are written (happens when application starts throwing error and you are logging all exception details) then that could be problem to handle there may be by limiting the log level to only needed error messages.
As a second check, examine if you have configured your logger path to correct log4net config file.
I hope this is not considered off topic, but it is a C# .Net problem of sorts:
I am using log4net 1.2.10. It has been stated on the apache log4net forum that from 1.2.9 onwards, different file locking schemas are available. I have configured log4net as per examples given to use a non-default method (minimal-locking or interprocess locking) but the immediate effect is the following error message:
log4net:ERROR XmlHierarchyConfigurator: Cannot find Property [lockingModel] to set object on [log4net.Repository.Hierarchy.DefaultLoggerFactory+LoggerImpl]
log4net:ERROR [RollingFileAppender] Unable to acquire lock on file C:\Program Files (x86)\Autoscribe\Matrix Gemini LIMS\Exe\log\Trace.log. The process cannot access the file 'C:\Program Files (x86)\Autoscribe\Matrix Gemini LIMS\Exe\log\Trace.log' because it is being used by another process.
My log4net.config file is:
<logger name="Matrix.Trace">
<!--this is for routine debug logging to a file-->
<level value="OFF" />
<lockingModel type="log4net.Appender.RollingFileAppender+InterProcessLock" />
<appender-ref ref="RollingFileAppenderTRACE" />
</logger>
<appender name="RollingFileAppenderTRACE" type="log4net.Appender.RollingFileAppender">
<file value=".\log\Trace.log" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%m%newline" />
</layout>
<appendToFile value="true" />
<maximumFileSize value="100KB" />
<maxSizeRollBackups value="2" />
</appender>
etc...
My C# application does this:
private static readonly ILog bllDebugLog = LogManager.GetLogger("Matrix.Trace"); //for debugging
and
log4net.Config.XmlConfigurator.ConfigureAndWatch(new System.IO.FileInfo("log4net.config"));
If I use the default locking method, logging does work (but I have file-lock problems with multiple processes, which is what I am trying to resolve).
I cannot see from the log4net documentation why this should fail. The error appears to suggest that log4net 1.2.10 does not support non-default locking, but the apache documentation is quite clear that it should. What am I doing wrong?
TIA
Apologies all round - I was being dumb. The lockingmodel bit needs to go in the appender definitions, not the logger definitions, and it appears the locking model should be log4net.Appender.FileAppender+InterProcessLock, not log4net.Appender.RollingFileAppender+InterProcessLock (even though I am using a RollingFileAppender logger type).
In my application, I include 3 libraries:
Log4net
Common.Logging.log4net
Quartz (use Common.Logging.log4net to write logs)
This is my log4net section config:
<log4net>
<root>
<level value="ALL" />
<appender-ref ref="FileAppender" />
</root>
<appender name="FileAppender" type="log4net.Appender.FileAppender">
<file value="quartz.log" />
<appendToFile value="false" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %level %logger - %message%newline" />
</layout>
</appender>
</log4net>
Everything is ok but having a problem about XmlConfigurator.Configure(). This command are called 2 times by order:
Called when init application -> I write log.
Called when starting Quartz. (I verified when to read source codes Common.Logging.log4net) -> Quartz write log.
After Quartz started, my logs was cleared because of XmlConfigurator.Configure(). This means that when calling this command, log will be cleared. I don't want my log is cleared after this command called in a process.
I can get source dll Common.Logging.log4net to change code to check whether log4net is really configured yet, and calling XmlConfigurator.Configure() if not. But I don't like this solution.
Please help me to find another solution without change codes in DLL library.
More info: http://neilkilbride.blogspot.com/2008/04/configure-log4net-only-once.html
You have configured that the file appender creates a new log file when log4net is reconfigured:
<appendToFile value="false" />
Change this to:
<appendToFile value="true" />
The log messages will be appended at the end of file, even if you call XmlConfigurator.Configure() multiple times.
I have been trying to use the class located here . But I have not been able to get this to work. I obviously do not understand something correctly, But I am curious how to get that example Logger class to work.
My research has sent me towards using MSBuild but the use of MSBuild correctly is still baffeling me. Any pointers would be helpful. I have built the logger class into a .dll,and referenced it in the project as well, but that is where my research seemed to run dry with helpful information.
My goal currently is just to get the above noted logger class working so I can use my own logger class.
That class is specifically for logging MSBuild events. If you want a generic logger that has nothing to do with MSBuild look at some of these alternatives:
MS Enterprise Library - Logging Application Block
Log4Net
Elmah (designed for logging ASP.NET errors, but can be used to log other events)
NLog
Don't be afraid of using a library to do the work. In the tutorial here for log4net it's a simple seven step process to start using a fully functional and scalable logging library. I'm going to inline pieces of the tutorial just in case the link ever dies.
First you build a very simple configuration section in your App.config file:
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,Log4net"/>
</configSections>
<log4net>
<root>
<level value="DEBUG" />
<appender-ref ref="LogFileAppender" />
</root>
<appender name="LogFileAppender" type="log4net.Appender.RollingFileAppender" >
<param name="File" value="log-file.txt" />
<param name="AppendToFile" value="true" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="10" />
<maximumFileSize value="10MB" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />
</layout>
</appender>
</log4net>
</configuration>
For your needs you pretty much just need to change the value of the first param named File as it's already setup to append to a text file.
Next you'll need to run the configuration in some startup method, like Application_Start or the main method of your program.
log4net.Config.XmlConfigurator.Configure();
Finally, just use it by plugging in a couple of lines:
private static readonly ILog log = LogManager.GetLogger(typeof(Bar));
... (rest of class)
... (somewhere in a method) ... log.Debug("this is the first log message");
I have a client-side application that uses log4net's RollingFileAppender and that can be instantiated multiple times. Initially I've written all my logs into a single file, however, I've realized soon enough that log4net locks the file while writing, though, even if I used a less restrictive writing mode, I would still end up with a lot of mess in my log files.
I've decided to incorporate process-id into the file name, like so:
<appender name="HumanRollingLog" type="log4net.Appender.RollingFileAppender">
<file type="log4net.Util.PatternString" value="Log\TestLog[%processid].txt"/>
<param name="DatePattern" value="dd.MM.yyyy'.log'"/>
<appendToFile value="true"/>
<rollingStyle value="Size"/>
<staticLogFileName value="true" />
<maxSizeRollBackups value="10"/>
<maximumFileSize value="1KB"/>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%type] [%thread] %-5level %logger - %message%newline%exception%"/>
</layout>
</appender>
That worked. However, it completely messed up the rolling features since now every process spawns its own log file, the actual rolling would happen only after process ids start repeating. E.g, starting my application 3 times resulting the following logs being created:
TestLog[5396].txt
TestLog[5396].txt.1
TestLog[5396].txt.10
TestLog[5396].txt.2
TestLog[5396].txt.3
TestLog[5396].txt.4
TestLog[5396].txt.5
TestLog[5396].txt.6
TestLog[5396].txt.7
TestLog[5396].txt.8
TestLog[5396].txt.9
TestLog[5976].txt
TestLog[5976].txt.1
TestLog[5976].txt.10
TestLog[5976].txt.2
TestLog[5976].txt.3
TestLog[5976].txt.4
TestLog[5976].txt.5
TestLog[5976].txt.6
TestLog[5976].txt.7
TestLog[5976].txt.8
TestLog[5976].txt.9
TestLog[6860].txt
TestLog[6860].txt.1
TestLog[6860].txt.10
TestLog[6860].txt.2
TestLog[6860].txt.3
TestLog[6860].txt.4
TestLog[6860].txt.5
TestLog[6860].txt.6
TestLog[6860].txt.7
TestLog[6860].txt.8
TestLog[6860].txt.9
Anyone has an idea what can I do to resolve this issue? I'd like to have each process its own file, but I can't allow the rolling to be reused among ALL the processes.
Thanks!
If you insist on using a process identifier in the name of the log file, then the built-in rolling patterns will never work. I would like to explore your requirements. What does "I would still end up with a lot of mess in my log files" really mean? What answers are you trying to get from your log files?
A solution to a different problem is to append the process id to the log messages and filter/search with one of the many tools available (log4net dashboard, log4net viewer, Apache Chainsaw, Microsoft LogParser, or Kiwi LogViewer.