I built a basic windows service in c# in VS2017 straight from the project template Windows Service. Built no problem. Installed no problem.
Here is the app.config with log4net section:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2" />
</startup>
<log4net>
<appender name="FileAppender" type="log4net.Appender.FileAppender">
<file value="log.txt" />
<appendToFile value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
</layout>
</appender>
<appender name="ConsoleAppender" type="log4net.Appender.ColoredConsoleAppender">
<mapping>
<level value="ERROR" />
<backColor value="Red, HighIntensity" />
</mapping>
<mapping>
<level value="WARN" />
<foreColor value="White" />
<backColor value="Yellow" />
</mapping>
<mapping>
<level value="INFO" />
<foreColor value="White" />
</mapping>
<mapping>
<level value="DEBUG" />
<backColor value="Green" />
</mapping>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
</layout>
</appender>
<root>
<level value="ALL" />
<appender-ref ref="ConsoleAppender" />
<appender-ref ref="FileAppender" />
</root>
</log4net>
</configuration>
And I want to log some events, like here:
public partial class Service1 : ServiceBase
{
private ILog log = LogManager.GetLogger(typeof(Service1));
public Service1()
{
InitializeComponent();
XmlConfigurator.Configure();
}
protected override void OnStart(string[] args)
{
log.Info("OnStart");
}
protected override void OnStop()
{
log.Info("OnStop");
}
}
When I start the service, I dont see any log.txt file created in the folder where the exe resides (Debug\Bin).
Any idea why?
I think the issue here I think is that your log variable is being initialized prior to the constructor being called. So basically you are calling LogManager.GetLogger prior to calling XmlConfigurator.Configure()
Try initializing log in the constructor after configuring log4net and see if that solves your problem.
public Service1()
{
InitializeComponent();
XmlConfigurator.Configure();
log = LogManager.GetLogger(typeof(Service1));
}
Adding another answer since my previous hunch seemed to be wrong (or maybe you actually have two problems here). Assuming you posted your whole app.config file, it doesn't look like you declare the log4net config section anywhere in there:
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
</configSections>
Perhaps that's the problem?
In my particular case, we always set the app.config file when initialize Log4Net on the Class Constructor:
log4net.Config.XmlConfigurator.Configure(new Uri(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "YouAppConfigFile.config")));
Log = log4net.LogManager.GetLogger("ServiceClass1");
Log.Info("ServiceClass1 Started!!!");
Related
So, I have a console app.
Using log4net to log messages.
Below is my log4net.config file.
<?xml version="1.0"?>
<log4net>
<appender name="FileAppender" type="log4net.Appender.FileAppender">
<file value="log.txt" />
<appendToFile value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
</layout>
</appender>
<appender name="ConsoleAppender" type="log4net.Appender.ColoredConsoleAppender">
<mapping>
<level value="ERROR" />
<backColor value="Red, HighIntensity" />
</mapping>
<mapping>
<level value="WARN" />
<foreColor value="White" />
<backColor value="Yellow" />
</mapping>
<mapping>
<level value="INFO" />
<foreColor value="White" />
</mapping>
<mapping>
<level value="DEBUG" />
<backColor value="Green" />
</mapping>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
</layout>
</appender>
<root>
<level value="ALL" />
<appender-ref ref="ConsoleAppender" />
<appender-ref ref="FileAppender" />
</root>
</log4net>
And in my console app I have this class to run
public class SchedulerService
{
private static readonly ILog _log = LogManager.GetLogger(typeof(SchedulerService));
private readonly SchedulerRegistry _registry;
public SchedulerService(SchedulerRegistry schedulerRegistry)
{
_registry = schedulerRegistry;
}
public void Start()
{
JobManager.Initialize(_registry);
JobManager.JobException += JobManager_JobException;
_log.Info("SchedulerService is started");
}
private void JobManager_JobException(JobExceptionInfo info)
{
Console.WriteLine("An error just happened with a scheduled job: " + info.Exception);
_log.Error("An error just happened with a scheduled job: " + info.Exception);
}
public void Stop()
{
Console.WriteLine("SchedulerService is stopped");
}
}
As a result log.txt file is created but its size is zero, its empty, nothing is logged into that files and nothing is logged to console.
What am I doing wrong?
Thanks a lot.
Your log4net.config is correct.
Make sure:
The Copy to Output Directory property of the log4net.config file is set to Copy Always. This is important because you need the config file to be copied to the bin folder when you build and run your application. Do this by right clicking the config file and select Properties. Then set the value of the Copy to Output Directory property to Copy Always.
You tell log4net to load your config. One way to achieve this is to add the following line to the bottom of your AssemblyInfo file:
[assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4net.config")]
Found the problem :)
Looks like its a new feature of VS 2017 that I haven't noticed before.
Previously you could resolve namespace only if you added corresponding components yourself manually via Add Reference or via NuGet Package Manager.
With VS 2017 when you try to resolve a namespace, it actually installs these packages for you. This maybe convenient, but also frustrating, like in my case.
Don't know why but VS decided to include this Common.Logging & Common.Logging.Core packages instead of log4net that was already in my solution.
Probably I trusted blindly and didn't notice that these packages have nothing to do with the library I wanted to use. The weird thing is that the code compiled just fine :)
So that was the reason why the code wasn't working. Be aware.
Try this method. You have to name it ColoredConsoleAppender instead of ConsoleAppender.Hope it works.
<appender name="FileAppender" type="log4net.Appender.FileAppender">
<file value="log.txt" />
<appendToFile value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
</layout>
</appender>
<appender name="ColoredConsoleAppender" type="log4net.Appender.ColoredConsoleAppender">
<mapping>
<level value="ERROR"/>
<foreColor value="Red"/>
</mapping>
<mapping>
<level value="INFO"/>
<foreColor value="White"/>
</mapping>
<mapping>
<level value="DEBUG"/>
<foreColor value="Green"/>
</mapping>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%message%newline"/>
</layout>
</appender>
<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date %-5level %logger - %message%newline"/>
</layout>
</appender>
<root>
<priority value="ALL"/>
<appender-ref ref="FileAppender"/>
<appender-ref ref="ColoredConsoleAppender"/>
</root>
I created a a file called log4net.config in my project and added the following configuration:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" />
</configSections>
<log4net>
<root>
<level value="ALL" />
<appender-ref ref="console" />
<appender-ref ref="RollingFileAppender" />
</root>
<appender name="console" type="log4net.Appender.ConsoleAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date %level %logger - %message%newline" />
</layout>
</appender>
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
<param name="File" value="${LOCALAPPDATA}\MyApp\LogFile.log" />
<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="%-5level [%d{yyyy-MM-dd hh:mm:ss}] [%thread] (Line:%line) %M: - %m%n" />
</layout>
</appender>
</log4net>
</configuration>
After that, I added the line below to my AssemblyInfo.cs file:
[assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4net.config", Watch = true)]
In the application, I have the following static class:
public static class Logger
{
private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
public static void LogInfo(string msg)
{
log.Info(msg);
}
public static void LogDebug(string msg)
{
log.Debug(msg);
}
public static void LogWarn(string msg, Exception e)
{
log.Warn(msg, e);
}
public static void LogError(string msg, Exception e)
{
log.Error(msg, e);
}
}
Then I'm trying to log somewhere in the application in another class using Logger.LogDebug("Error logger working.");
However, I can't see any log file being created or written to it. What am I doing wrong?
UPDATE:
I also added the following in my app.config file but I see nothing at all on my Output console...
<appSettings>
<add key="log4net.Internal.Debug" value="true"/>
</appSettings>
If you have the log4net configuration in a log4net logging configuration file, you do not have to add the configuration of the web.config (configuration tag and sections). Just add the log4net tags:
<log4net>
<root>
<level value="ALL" />
<appender-ref ref="console" />
<appender-ref ref="RollingFileAppender" />
</root>
<appender name="console" type="log4net.Appender.ConsoleAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date %level %logger - %message%newline" />
</layout>
</appender>
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
<param name="File" value="${LOCALAPPDATA}\MyApp\LogFile.log" />
<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="%-5level [%d{yyyy-MM-dd hh:mm:ss}] [%thread] (Line:%line) %M: - %m%n" />
</layout>
</appender>
</log4net>
I could not reproduce your mistake. Configure log4net in AssemblyInfo works fine. maybe the problem in configuration. let me show you another implementation
private static readonly ILog log = LogManager.GetLogger("myLogger");
private static string configFile = "log4net.config";
static Logger()
{
XmlConfigurator.Configure(new FileInfo(configFile));
}
log4net.config:
<log4net>
<logger name="myLogger">
<level value="ALL" />
<appender-ref ref="console" />
<appender-ref ref="RollingFileAppender" />
</logger>
<appender name="console" type="log4net.Appender.ConsoleAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date %level %logger - %message%newline" />
</layout>
</appender>
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
<param name="File" value="${LOCALAPPDATA}\MyApp\LogFile.log" />
<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="%-5level [%d{yyyy-MM-dd hh:mm:ss}] [%thread] (Line:%line) %M: - %m%n" />
</layout>
</appender>
</log4net>
Managed to find out the issue thanks to stuartd's comment. My problem was, my full solution had 2 projects. I had only configured one project (which is not the start-up project) for log4net.
My original log4net configuration did not have any mistake. I simply added log4net reference to my start up project and added log4net configuration to that project as well and it started logging.
Many thanks to everyone who tested my config.
log file is not getting created,
using below call to get logger and config file.
is it required to give full path for file?
private static readonly log4net.ILog logger = log4net.LogManager.GetLogger
(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net, Version=1.2.10.0, Culture=neutral, PublicKeyToken=1b44e1d426115821" requirePermission="false"/>
</configSections>
<!-- Log4net Logging Setup -->
<log4net>
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="log.txt" />
<appendToFile value="true" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="50" />
<maximumFileSize value="50MB" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />
</layout>
</appender>
<root>
<level value="ALL" />
<appender-ref ref="RollingFileAppender" />
</root>
</log4net>
</configuration>
Does your code call
log4net.Config.XmlConfigurator.Configure();
on startup?
The <root> section I use has priority, not level:
<root>
<priority value="ALL" />
<appender-ref ref="LogFileAppender" />
</root>
(Apparently, that's not the issue https://stackoverflow.com/a/24188507/21336)
after adding below line in AssemblyInfo.cs, could see log file getting created and logs coming.
[assembly: log4net.Config.XmlConfigurator(Watch = true)]
I have a DLL class that create log4net log:
[SetUpFixture]
public class Application
{
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
[SetUp]
private Application()
{
log4net.Config.BasicConfigurator.Configure();
ILog log = log4net.LogManager.GetLogger(typeof(Application));
log.Debug("This is a debug message");
log.Warn("This is a warn message");
}
}
and Log4Net.config:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net, Version=1.2.10.0, Culture=neutral, PublicKeyToken=1b44e1d426115821" />
</configSections>
<!-- Log4net Logging Setup -->
<log4net>
<appender name="FileAppender" type="log4net.Appender.FileAppender,log4net">
<file value="c:\\mylogfile.txt" />
<appendToFile value="true" />
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %level %logger - %message%newline" />
</layout>
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="INFO" />
<levelMax value="FATAL" />
</filter>
</appender>
<root>
<level value="DEBUG"/>
<appender-ref ref="FileAppender"/>
</root>
</log4net>
</configuration>
My program starts the nunit.exe by:
string nunitAppPath = #"C:\Program Files (x86)\NUnit 2.6.4\bin\nunit.exe";
Process.Start(new ProcessStartInfo(nunitAppPath));
and have a reference to DLL.
I have a text file in c name :mylogfile.txt, but it's always null.
I am trying to use basic logging for a windows service.
I added the reference to log4net.
I added the following in AssemblyInfo.cs:
[assembly: log4net.Config.XmlConfigurator(Watch = true)]
I added the following to my App.config:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net, Version=1.2.10.0, Culture=neutral, PublicKeyToken=1b44e1d426115821" requirePermission="false" />
</configSections>
<!-- Log4net Logging Setup -->
<log4net>
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender,log4net">
<file value="c:\\CGSD\\log\\logfile.txt" />
<appendToFile value="true" />
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %level %logger - %message%newline" />
</layout>
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="INFO" />
<levelMax value="FATAL" />
</filter>
</appender>
<root>
<level value="ALL"/>
<appender-ref ref="RollingFileAppender"/>
</root>
</log4net>
</configuration>
I have the following code in my service:
log4net.Config.XmlConfigurator.Configure();
log4net.ILog log = log4net.LogManager.GetLogger(typeof(Program));
log.Debug("test");
The file c:\CGSD\log\logfile.txt is created but nothing is ever written to it.
I've been through the forums all day trying to track this one down, but if I overlooked an already posted solution I apologize.
Your filter level looks to be configured at <levelMin value="INFO" /> but you are testing a log.Debug message. Change your configuration to have <levelMin value="DEBUG" /> and try again. If that doesn't fix it, there may be other config problems also.
You require a minimum level INFO and are trying to log a message with level DEBUG. As you can see in the documentation (http://logging.apache.org/log4net/release/manual/introduction.html), the priority of DEBUG is lower than INFO so your message is filtered out.