how to create dynamic log using log4net - c#

My Project is in C# (Windows Form) .net3.5
In my code there are multiple events and in each event multiple searches are running.
I have to create log file for each event and multiple searches can access & write this single log file.
The problem is that I don't know how to use log4net for creating multiple logs with dynamic(set at run time) names.
How to set there location(Path)
I explorer internet regarding my problem but haven't found any help which address this type of issues.
any idea pls

log4net is generally used to have mutiple sources and appenders.
To generate a defined source, ask LogManager to have a named log, generally we use a type to identify a log, but feel free to use a string if you want:
var myLog = LogManager.GetLogger("NAME");
....
var myLog = LogManager.GetLogger(GetType());
In the first case logger is identified by "NAME", in the second by the type name with namespaces.
Then you can configure the appenders, for all logs, for a subset of them, with filters and so on.
Let's see an example:
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
</configSections>
<log4net>
<appender name="MYFILE" type="log4net.Appender.RollingFileAppender">
<file value=".\logs\myname.log"/>
<appendToFile value="true"/>
<rollingStyle value="Size"/>
<maxSizeRollBackups value="10"/>
<maximumFileSize value="10MB"/>
<staticLogFileName value="true"/>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date %-5level (%thread) %logger - %message%newline"/>
</layout>
</appender>
<root>
<level value="INFO"/>
<!-- all logger append to these appenders />
<appender-ref ref="xxxxxx"/>
</root>
<logger name="NAME">
<level value="INFO"/>
<appender-ref ref="MYFILE"/>
</logger>
<!-- add other appender here -->
Don't forget to call at your application start XmlConfigurator.Configure();

Related

When do I need to specify log4net.Appender.FileAppender.LockingModel in ASMX services

We have a project which consists of 3 different ASMX service files for example Service1.asmx, Service2.asmx, and Service3.asmx all of which are running from the same application pool.
We've just started using log4net to log our requests and responses, and it seems to be logging every request and response for each service correctly in the same log file (which is what we want).
However, on reading log4net config examples, I've seen some examples that are using log4net.Appender.FileAppender.LockingModel.
Do I need to consider this in my scenario? This is my current code:
public class Global : System.Web.HttpApplication
{
public static readonly log4net.ILog asmxDebugLog = log4net.LogManager.GetLogger("AsmxDebugLogFile");
protected void Application_Start(object sender, EventArgs e)
{
log4net.Config.XmlConfigurator.Configure();
}
}
In my web.config file I have
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
</configSections>
<log4net debug="true">
<appender name="AsmxDebugLogFile" type="log4net.Appender.RollingFileAppender">
<file value="App_Data/log4net_ASMX.DEBUG_" type="log4net.Util.PatternString" />
<appendToFile value="true" />
<rollingStyle value="Composite" />
<datePattern value="yyyy-MM-dd'.log'" />
<staticLogFileName value="false" />
<maximumFileSize value="5GB" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
</layout>
</appender>
<logger name="AsmxDebugLogFile">
<level value="DEBUG" />
<appender-ref ref="AsmxDebugLogFile" />
</logger>
</log4net>
</configuration>
We are logging like this
asmxDebugLog.Debug("Log something useful");
You only really need to care about locking when the loggers are not all in one process, which for you it seems they are (1 app pool ~= 1 process).
The default locking mode is 'exclusive', which is fastest, so you don't need to (or want to) change that (and slow it down).
If you later split the services into different app pools, you can then choose either InterProcess (if all on the same machine) or Minimal.

log4net GenericFailure. Unable to acquire lock on file

I am trying to configure log4net for the first time, I'm certain that I have everything configured properly, however, after getting empty log files I turned on the log4net debugger. I am now continually seeing the following error:
log4net:ERROR [RollingFileAppender] ErrorCode: GenericFailure. Unable to acquire lock on
file "file path\file name" The process cannot access the file "file path\file name" because
it is being used by another process.
I currently have log4net configured through my Web.config file thusly:
<log4net debug="true">
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="Logs\\TransferPicturesApplicationLog.txt"/>
<appendToFile value="true"/>
<rollingStyle value="Size"/>
<maxSizeRollBackups value="5"/>
<maximumFileSize value="10MB"/>
<staticLogFileName value="true"/>
<filter type="log4net.Filter.LevelRangeFilter">
<param name="LevelMin" value="ERROR"/>
<param name="LevelMax" value="DEBUG"/>
</filter>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %level %logger - %message%newline"/>
</layout>
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
</appender>
<root>
<level value="INFO"/>
<appender-ref ref="RollingFileAppender"/>
</root>
<logger>
<level value="DEBUG"/>
<appender-ref ref="RollingFileAppender"/>
</logger>
</log4net>
Help!!!
I also got this error because I specified the name of a directory as opposed to a file in the appender, the error message is cryptic:
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
<lockingModel type="log4net.Appender.FileAppender+MinimalLock"/>
<file value="C:\DirectoryNameHere\MyBad" />
My guess would be that you have multiple copies of the appender across different assemblies trying to access this path, so they all attempt to take hold of the appropriate log file at the same time. However, to be sure, I would recommend you use Unlocker to make sure your file isn't being held by something else you don't expect. If you are having multiple instances of this appender trying to open the same file, your problem would be that you are not using the appender correctly; if the appender is being used across assemblies then the two invocations of it will not play nicely with one another, leading to an already in use error like this. If this is the case, refactoring is likely your only option.
I got this problem when I tried to write the logfile in a subdirectory (same as #PeteN). When using the correct syntax this doens't occur anymore, in de appender config set:
<appender name="TestLogAppender" type="log4net.Appender.RollingFileAppender">
<file type="log4net.Util.PatternString" value=".\logDirectory\LogFileName.csv" />
<....>
hope this helps

Log4net Configuration Issue

Had something weird start happening to me today. I have an asp.net mvc app with log4net setup and everything had been working fine. Something must have changed somewhere and now nothing is getting logged (no log file is being created).
Here's my global.asax.cx
protected void Application_Start()
{
log4net.Config.XmlConfigurator.Configure();
}
Here's my configuration in my web.config:
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
</configSections>
<log4net>
<appender name="FileAppender" type="log4net.Appender.RollingFileAppender">
<file value="c:\logs\api\ApiLog.txt" />
<appendToFile value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date - %message%newline" />
</layout>
</appender>
<root>
<level value="ALL" />
<appender-ref ref="FileAppender" />
</root>
</log4net>
For some reason the c:\logs\api\apilog.txt file never gets created. However, if I change my application_start method to this it works fine:
log4net.Config.XmlConfigurator.Configure(new FileInfo("DirectPathToMy\web.config"));
Any ideas why calling Configure() is not finding the configuration in my web.config by default?
Don't know why your approach don't work but the issue is that you need to make sure it is activated in your project.
I usually put this as an assembly level reference in my AssemblyInfo.cs under /Properties:
[assembly: log4net.Config.XmlConfigurator()]
Reference:
http://logging.apache.org/log4net/release/manual/configuration.html

Log4Net not logging (probably not initialised)

First time playing with Log4Net and I'm running into trouble. I've followed various tutorials but I've been unable to get it to log anything out. Let me show you my code and hopefully you can tell me what I'm doing wrong.
app.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="log4net"
type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
</configSections>
<log4net>
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="CurrentLog.txt"/>
<staticLogFileName value="true"/>
<appendToFile value="true"/>
<rollingStyle value="Date" />
<datePattern value="yyyyMMdd"/>
<filter type="log4net.Filter.LevelRangeFilter">
<acceptOnMatch value="true" />
<levelMin value="DEBUG" />
<levelMax value="FATAL" />
</filter>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date{dd MMM yyy HH:mm:ss} %level %message. %newline %exception" />
</layout>
</appender>
<root>
<level value="ALL" />
<appender-ref ref="RollingFileAppender" />
</root>
</log4net>
</configuration>
AssemblyInfo.cs
[assembly: log4net.Config.XmlConfigurator(Watch=true)]
Presenter.cs
At the top of the class I have this:
private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
Then I try to use the log variable later in the class:
bool isDebugEnabled = log.IsDebugEnabled;
log.Debug("Failed to save", e);
Whenever I inspect the isDebugEnabled variable, it is false, as are all of the other isBlahEnabled if I inspect the log variable.
My suspicion is that I have not hooked up my app.config file correctly because this is the first time I have tried to use one. I created by right clicking on the project in solution explorer, adding a new item, choosing Application Configuration File and naming it app.config.
This one works for me:
app.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
</configSections>
<log4net>
<appender name="Main" type="log4net.Appender.RollingFileAppender">
<file value="${USERPROFILE}\My Documents\MyApp\Logs\Main.log" />
<appendToFile value="false" />
<maximumFileSize value="1GB" />
<maxSizeRollBackups value="3" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date{ABSOLUTE} %-5level %-18logger %message%newline" />
</layout>
</appender>
<root>
<level value="DEBUG" />
<appender-ref ref="Main" />
</root>
</log4net>
</configuration>
Also be sure the build action on app.config is set to None and Copy to output dir is set to "Copy if newer". You can set these settings in the file properties.
Program.cs
public static ILog Log;
static void Main(string[] args)
{
// Setup Logging
log4net.Config.XmlConfigurator.Configure();
Log = LogManager.GetLogger("MyAwesomeApp");
// ...
}
Just to add my 2 cents: I had the same Problem, but I use the above config in separate log4net.config (so I have on all apps the same config), but I simply forgot to set the file property on build 'Copy when newer' (or similar wording, have German Version).
Just to add my 2p in case this helps anyone else searching for a resolution to this problem:
In my case I was using the NServicebus.Logging package in addition to Log4net, and this package contains types with the exact same names as those in Log4net, differing only in the namespace.
Fixing the 'using' statements or fully-qualifying the type names resolved it, but it was very hard to spot the problem.

How to include log4net for a class library?

I want to implement logging function into a class library, which is itself referenced in a webservice. I tried to add app.config and did everything needed, but it seems that when an exception is thrown, log4net simply does nothing.
my app.config
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
</configSections>
<log4net>
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="D:\\mylogfile.txt" />
<appendToFile value="true" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="5" />
<maximumFileSize value="10MB" />
<staticLogFileName value="true" />
<filter type="log4net.Filter.StringMatchFilter">
<stringToMatch value="test" />
</filter>
<filter type="log4net.Filter.StringMatchFilter">
<stringToMatch value="error" />
</filter>
<filter type="log4net.Filter.DenyAllFilter" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %level %logger - %message%newline%exception" />
</layout>
</appender>
<root>
<level value="INFO"/>
<appender-ref ref="RollingFileAppender"/>
<appender-ref ref="ConsoleAppender" />
</root>
</log4net>
in AssemblyInfo.cs:
[assembly: log4net.Config.XmlConfigurator(ConfigFile = "app.config")]
in LogManager.cs:
private static readonly ILog Log = log4net.LogManager.GetLogger
(MethodBase.GetCurrentMethod().DeclaringType);
public static void WriteLog(Exception ex)
{
Log.Error(ex);
}
Can you please tell me what's wrong? How can I get log4net working for my class library?
Thank you
At runtime, config file is always used from host application, unless declared explicitly. Here in case, web.config is being used not app.cofig. Rather mention some other custom config file name and ensure that file is copied in virtual directory of web service. Also as chibacity said, ensure permission on log file. Better keep it in app_data folder for web service host.
You could use some kind of injection, either you build a simple one like:
public interface ILogger
{
void LogInfo(string message);
.
.
.
}
And then you just inject something that matches that interface, like a wrapper for log4net or such.
But, I think the most correct thing is to not log in the class library. Why I think so is because the library itself is not the application, your web service is so your web service should decide what to log. If you want to log exceptions just don't catch them in the class library and let your web service handle the logging. This will also make it easier to centralize the logging.
Please see my answer to the following question:
Use log4net in SDK
It has a log configuration routine that will construct a complete path to a log4net config file. As you are in a webservice it my not be looking where you expect for "app.config".
Also make sure that you have permission to write to "D:\mylogfile.txt" from your webservice.

Categories