When I use log4net for logging in .NET4.0 I use the following code
LogManager declaration:
private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
And when used in code:
log.Info("My info text");
This outputs the following to the log-file:
2013-10-01 14:41:11,010 [3] INFO MyNamespace.MyClass [(null)] - My info text
I am wondering what the [(null)] means and how I can remove/change it?
This is my config-file:
<?xml version="1.0"?>
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,Log4net"/>
</configSections>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup>
<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>
Fix
To stop it appearing in the log remove [%property{NDC}] from the config file.
This happens because log4net automatically populates a context of information that might be useful for logging - in some cases this might result in a null value.
log4net NDC
This post explains how to use NDC: When to use 'nested diagnostic context' (NDC)?
In short log4net calls the static method log4net.NDC.Push to set the context of the the code.
You could for example set the NDC manually by running the following:
log4net.NDC.Push("context")
From that point forward outputting a log message will supply %property{NDC} as the string context.
UPDATE:
NDC.Push has been deprecated. Alternatively, you can use ThreadContext.Stacks["NDC"].Push("context")
if you just want the (null) to disappear you can also set log4net.Util.SystemInfo.NullText to some other value like "" or string.Empty, it will use that instead.
Related
I have this as my config file:
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" />
</configSections>
<log4net>
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="c:\\logging\\EwsSearch.log" />
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<appendToFile value="true" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="-1" />
<maximumFileSize value="100KB" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />
</layout>
</appender>
</log4net>
<root>
<level value="ERROR" />
<appender-ref ref="RollingFileAppender" />
</root>
</configuration>
I then have in my C# code:
public class VsiEWSSearch
{
private static readonly ILog logger = LogManager.GetLogger(typeof(VsiEWSSearch));
public EWSResponse PdeProcessInquiry(int BusinessLineCode, int ClientCaseId, string callingApp)
{
XmlConfigurator.Configure(new System.IO.FileInfo("VSI.EWSSearch.config"));
logger.Error("This is an error");
No log file is produced even though I have adjusted permissions for the directory. What's wrong?
The root node has to be inside the log4net node. Depending on the type of configuration file you need to make some further adjustments:
If you have a standalone config file for log4net then you need to remove the configuration and configSections node. I also think that log4net is not going to find you configuration file unless you specify the full path (you can of course do that without hard-coding any path in your application).
If you are simply using app.config then you do not need further modifications, but you need to call the XmlConfigurator.Configure() method without any argument.
Note: You should call the XmlConfigurator.Configure() method only once in your application.
So I am trying to set up Log4Net in my Web .NET 4.0 application. I have added the correct .dll to my project and have appended the following to my Web.Config file as starters:
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
<root>
<level value="DEBUG" />
<appender-ref ref="RollingLogFileAppender" />
</root>
</configSections>
<log4net debug="true">
<appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="C:\\TestProj\\TestLog.txt" />
<appendToFile value="true" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="10" />
<maximumFileSize value="10MB" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%-5p %d %5rms %-22.22c{1} %-18.18M - %m%n" />
</layout>
</appender>
However, if I append the "log4net" section to Web.Config, I will receive the error message
Unable to start debugging on the web server. See help for common
configuration problems.....
Make sure the server is running correctly. Verify there are no syntax
errors in the web.config........
NOTE
I can remove all the internals of this section and leave only the declaration:
<log4net></log4net>
and I will still get the same error.
Can someone give me some pointers on how to track down this error?
For developers who are not sure exactly how to get started following might be a help
ConfigSections in app.config
Remember to tell your application that a library is introducing a custom configuration section are you are intended to utilize, I am not perfectly sure if it is mandatory or not but I always use it as first section within root <configuration> tag.
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
</configSections>
log4net config in app.config
There are quite a variety of different appenders available in log4net but I usually use RollingFileAppender so I am using the same one in this sample, you can find rest of those here.
<log4net>
<!-- file appender -->
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="C:/logs/my_log_file.log"/>
<appendToFile value="true"/>
<rollingStyle value="Date"/>
<maxSizeRollBackups value="30"/>
<datePattern value=".yyyy-MM-dd"/>
<staticLogFileName value="true"/>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger - %message%newline"/>
</layout>
</appender>
<root>
<level value="DEBUG"/>
<appender-ref ref="RollingFileAppender"/>
</root>
</log4net>
Update AssemblyInfo.cs file
I always miss this step whenever I have to create a new project. So remember you have to tell your application to watch for XMLConfigurator to perform configuration of log4net, so following line goes at the end of AssemblyInfo.cs file:
[assembly: log4net.Config.XmlConfigurator(Watch = true)]
Get Started
Remember to include the reference of log4net.dll then use following line of code to initialize logger within a class
private static ILog log = LogManager.GetLogger(typeof(MyClass));
And at the end lets use it like following
log.Info("Hello log4net");
Happy Logging :)
Take a look at a sample configurations at log4net documentation homepage.
Chances are you've misplaced required tags.
Trying to get log4net setup for .net 4.0 asp.net mvc2 app. I have bare minimum configuration but nothing is getting logged. Am I missing something?
referencing log4net 1.2.10 released version dll
added in sections
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
added section
<log4net>
<appender name="Console" type="log4net.Appender.ConsoleAppender">
<layout type="log4net.Layout.PatternLayout">
<!-- Pattern to output the caller's file name and line number -->
<conversionPattern value="%5level [%thread] (%file:%line) - %message%newline" />
</layout>
</appender>
<appender name="RollingFile" type="log4net.Appender.RollingFileAppender">
<file value="c:\\example.log" />
<appendToFile value="true" />
<maximumFileSize value="100KB" />
<maxSizeRollBackups value="2" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%level %thread %logger - %message%newline" />
</layout>
</appender>
<root>
<level value="DEBUG" />
<appender-ref ref="Console" />
<appender-ref ref="RollingFile" />
</root>
</log4net>
trying to log message with log4net.LogManager.GetLogger("global").Error("test error");
But there is nothing getting logged and no error. Tried lot of config variations like only console, only rollingfile, to file appender only. but nothing works. And yes it's .net 4.0 full project not client profile.
What could be wrong in here?
Did you start log4net?
protected void Application_Start()
{
XmlConfigurator.Configure();
...
}
I didn't want to make the title too long but this question specifically refers to running an NServiceBus Generic Host as a Windows Service (thanks to TopShelf) configured to run as Local System (on a Vista machine)
In a previous question I explain why I decided to adapt the PubSub sample to run as a Windows Service so that I can easily stop and start the service to fully prove to myself that NServiceBus was doing what it was supposed to do.
For some reason I can't get Log4Net to log anything to disk, so this could well just be a Log4Net (newbie) configuration problem?
Below is my brute-force attempt to get some sort of tracing going - all I'm getting so far is files writen as follows:
C:\logs\<-GUID->log4net.log
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="MsmqTransportConfig" type="NServiceBus.Config.MsmqTransportConfig, NServiceBus.Core" />
<section name="UnicastBusConfig" type="NServiceBus.Config.UnicastBusConfig, NServiceBus.Core" />
<sectionGroup name="common">
<section name="logging" type="Common.Logging.ConfigurationSectionHandler, NServiceBus.Core"/>
</sectionGroup>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net"/>
</configSections>
<!-- in order to configure remote endpoints use the format: "queue#machine"
input queue must be on the same machine as the process feeding off of it.
error queue can (and often should) be on a different machine.
-->
<MsmqTransportConfig
InputQueue="worker2"
ErrorQueue="error"
NumberOfWorkerThreads="1"
MaxRetries="5"
/>
<UnicastBusConfig>
<MessageEndpointMappings>
<add Messages="Messages" Endpoint="messagebus" />
</MessageEndpointMappings>
</UnicastBusConfig>
<common>
<logging>
<factoryAdapter type="Common.Logging.Log4Net.Log4NetLoggerFactoryAdapter, NServiceBus.Core">
<arg key="configType" value="INLINE"/>
</factoryAdapter>
</logging>
</common>
<log4net debug="true">
<appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender,log4net">
<param name="File" value="c:\logs\Subscriber2.log" />
<param name="AppendToFile" value="true" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="2" />
<maximumFileSize value="100KB" />
<staticLogFileName value="true" />
<datePattern value="yyyyMMdd" />
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
</layout>
</appender>
<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionpattern value="%date [%thread] %-5level %logger - %message%newline" />
</layout>
</appender>
<appender name="EventLogAppender" type="log4net.appender.eventlogappender">
<applicationname value="Subscriber2.EndPointConfig_v1.0.0.0" />
<layout type="log4net.layout.patternlayout">
<conversionpattern value="%date [%thread] %-5level %logger - %message%newline" />
</layout>
</appender>
<appender name="TraceAppender" type="log4net.Appender.TraceAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
</layout>
</appender>
<root>
<level value="ALL" />
<appender-ref ref="RollingLogFileAppender" />
<appender-ref ref="EventLogAppender" />
<appender-ref ref="ConsoleAppender" />
<appender-ref ref="TraceAppender" />
</root>
</log4net>
<appSettings>
<add key="log4net.Internal.Debug" value="true"/>
</appSettings>
<system.diagnostics>
<trace autoflush="true">
<listeners>
<add
name="textWriterTraceListener"
type="System.Diagnostics.TextWriterTraceListener"
initializeData="c:\logs\log4net.log" />
</listeners>
</trace>
</system.diagnostics>
</configuration>
NSB will not pick up log settings from config files as default. To do this implement IConfigureLogging in your endpoint config class.
More info here:
http://tech.groups.yahoo.com/group/nservicebus/message/3655
Hope this helps!
/Andreas
It looks as if your other two appenders are throwing exceptions while trying to log. I suspect the %property{NDC} in your patterns - remove them from the pattern and try again.
If your pattern contains %property{X} then you need to set a property with key "X" using code such as
ABC.Properties["X"] = /* some value */
where ABC is either a LoggingEvent instance or ThreadContext or GlobalContext.
I don't know if you've set properties with key "NDC", but I suspect not...
I've set up a logfileAppender and a consoleAppender in my log4net config for my application. I would like the logfile appender to only write ERROR messages and above and the console appender to write DEBUG and above.
My config is:
<log4net debug="false">
<appender name="LogFileAppender" type="log4net.Appender.FileAppender,log4net" >
<param name="File" value="log.txt" />
<param name="AppendToFile" value="true" />
<layout type="log4net.Layout.PatternLayout,log4net">
<param name="ConversionPattern" value="%d %M - %m%n" />
</layout>
<threshold value="ERROR"/>
</appender>
<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender" >
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%d %m%n" />
</layout>
</appender>
<root>
<priority value="DEBUG" />
<appender-ref ref="ConsoleAppender" />
<appender-ref ref="LogFileAppender" />
</root>
</log4net>
I'm finding that both ERROR and DEBUG is being output to my logfile appender. How to restrict it to only ERROR?
Note also that the level tag in the logger doesn't work the same way as threshold or a LevelMatchFilter.
Level indicates what log statements that actually will be generated. This is what you can test on in you code.
Threshold on the other hand, filters away all log messages that falls below your threshold.
This means that having a threshold that is higher than the highest logger level makes no sense. I have seen many times how one sets a level of INFO (because that is what most appenders will use), and then create an appender that has a threshold of DEBUG. And then you are surprised when no DEBUG messages actually appears on the appender...
To get very specific filtering for an appender, you need to configure a LevelMatchFilter or a LevelRangeFilter for the logfile appender to filter the events which are actually output.
For example:
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="ERROR"/>
<levelMax value="FATAL"/>
</filter>
or
<filter type="log4net.Filter.LevelMatchFilter">
<levelToMatch value="ERROR"/>
</filter>
put one of these inside your <appender> tag, and this should work for you:
<appender name="LogFileAppender" type="log4net.Appender.FileAppender,log4net" >
<filter type="log4net.Filter.LevelMatchFilter">
<levelToMatch value="ERROR"/>
</filter>
<param name="File" value="log.txt" />
<param name="AppendToFile" value="true" />
<layout type="log4net.Layout.PatternLayout,log4net">
<param name="ConversionPattern" value="%d %M - %m%n" />
</layout>
<threshold value="ERROR"/>
</appender>
Note: Updated to remove mistake pointed out by kgiannakakis.
I've created a sample console application using your log4net config and I'm getting the exact behaviour you appear to be wanting....
using System;
using System.IO;
using log4net;
using log4net.Config;
namespace SO_1171258
{
class Program
{
private static readonly ILog log = LogManager.GetLogger(typeof(Program));
static void Main()
{
XmlConfigurator.ConfigureAndWatch(new FileInfo(AppDomain.CurrentDomain.GetData("APP_CONFIG_FILE").ToString()));
log.Error(new Exception("error log statment"));
log.Debug("debug log statment");
}
}
}
When I run this application, the only thing in the logfile is:
2014-01-27 15:02:51,387 Main - System.Exception: error log statment
And to the screen I see:
2014-01-27 15:05:52,190 System.Exception: error log statment
2014-01-27 15:05:52,218 debug log statment
Here is the entirety of my app.config file:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net"/>
</configSections>
<log4net debug="false">
<appender name="LogFileAppender" type="log4net.Appender.FileAppender,log4net" >
<param name="File" value="log.txt" />
<param name="AppendToFile" value="true" />
<layout type="log4net.Layout.PatternLayout,log4net">
<param name="ConversionPattern" value="%d %M - %m%n" />
</layout>
<threshold value="ERROR"/>
</appender>
<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender" >
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%d %m%n" />
</layout>
</appender>
<root>
<priority value="DEBUG" />
<appender-ref ref="ConsoleAppender" />
<appender-ref ref="LogFileAppender" />
</root>
</log4net>
</configuration>
The answers you are receiving are partly correct. The Threshold is only used to set a lower limit on the level appended. A threshold of ERROR will actually receive ERROR and FATAL (which is "above" ERROR).
You do want to implement a LevelMatchFilter with a level value of "ERROR" (and "DEBUG" for the other appender). However, you must also add a DenyAllFilter to the end of your filter chain.
For example:
<appender name="LogFileAppender" type="log4net.Appender.FileAppender,log4net" >
<param name="File" value="log.txt" />
<param name="AppendToFile" value="true" />
<layout type="log4net.Layout.PatternLayout,log4net">
<param name="ConversionPattern" value="%d %M - %m%n" />
</layout>
<filter type="log4net.Filter.LevelMatchFilter">
<levelToMatch value="ERROR" />
</filter>
<filter type="log4net.Filter.DenyAllFilter" />
</appender>
I've had to implement the DenyAllFilter since log4net 1.2.10 (you can see the question I had on this topic here).
You need to use additivity property. See here for an example. You need to define two loggers.