Configuring log4net without code in Rider for dotnet 2.1 project - c#

I'm working on a pet .netcore2.1 project using Rider IDE. I'm currently trying to add log4net support for the project, and trying to do it the "proper way" (separate config file, automatically configure log4net without having to write code for intialization etc.). So far all tutorials (ex1, ex2) I've found suggest configuring it by adding assembly property
[assembly: log4net.Config.XmlConfigurator(Watch=true)]
to AssemblyInfo.cs file. However I seem to fail to find the file, and it looks from other questions (e.g. this) that it might not be used with .netcore at all, in favor of doing configuration via other means (e.g. .csproj file).
So far I've found a workaround here, which works, but it uses explicit configuration via code, which looks like a step backwards compared to assembly-level configuration.
Is there a way of doing this in a more static way (e.g. using some ItemGroup in .csproj)?
Upd: for future reference - this is just a custom case of https://learn.microsoft.com/en-us/dotnet/standard/assembly/set-attributes , so it just goes to .cs file directly.

Easy example using log4net for .net core in console:
[assembly: XmlConfigurator(Watch = true)]
namespace ConsoleApp
{
class Program
{
private static readonly ILog log = LogManager.GetLogger(typeof(Program));
static void Main(string[] args)
{
var logRepository = LogManager.GetRepository(Assembly.GetEntryAssembly());
XmlConfigurator.Configure(logRepository, new FileInfo("log4net.config"));
log.Info("Entering application.");
log.Error("Error application.");
}
}
}
You need to add file with settings log4net to your project: log4net.config, and don't forget chnage it options "Copy to output directory" to "Copy if newer" or "Copy always"
Example of log4net.config:
<?xml version="1.0" encoding="utf-8" ?>
<log4net>
<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender" >
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger [%ndc] - %message%newline" />
</layout>
</appender>
<appender name="FileAppender" type="log4net.Appender.RollingFileAppender">
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<file value="logs/" />
<datePattern value="yyyy-MM-dd'.log'" />
<staticLogFileName value="false" />
<appendToFile value="true" />
<rollingStyle value="Composite" />
<layout type="log4net.Layout.PatternLayout">
<IgnoresException value="False" />
<conversionPattern value="%date [%thread] %-5level %logger [%ndc] - %message%newline" />
</layout>
<filter type="log4net.Filter.LevelRangeFilter">
<param name="LevelMin" value="INFO"/>
</filter>
</appender>
<root>
<level value="ALL" />
<appender-ref ref="FileAppender" />
<appender-ref ref="ConsoleAppender" />
</root>
</log4net>
By the way: log4net don't supporting for 1 april 2020: http://logging.apache.org/log4net/

Related

Log4net - How to get calling method name when using wrapper

I have a log4net wrapper for logging error messages in web api application. It is working fine but i am not able to log calling method name. It only display's top level method name. Lets say, i have a method a of class A which calls method b of a class B and b logs error message. Log4net only displays Class A and method a but i want to display either full calling chain A-a-B-b or at least B-b
private static readonly ILog LoggerObject = LogManager.GetLogger("ErrorLog");
log4net config
<log4net>
<appender name="ErrorLog" type="log4net.Appender.RollingFileAppender">
<file value="LogBackUp2.log" />
<staticLogFileName value="false" />
<appendToFile value="true" />
<rollingStyle value="Date" />
<datePattern value="yyyy-MM-dd.'Err'" />
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger [%M %C] - %message%newline" />
</layout>
</appender>
<logger name="ErrorLog">
<maximumFileSize value="15MB" />
<appender-ref ref="ErrorLog" />
</logger>
</log4net>
If i use this then log4net doesn't create any log file.
LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType)
use %stacktrace{5} to show 5 levels of the stacktrace which lead to the call of the log method. Replace the 5 with the level you want to have. example:
<conversionPattern value="%date [%thread] %-5level %logger [%stacktrace{5}] - %message%newline" />
When you use a log4net wrapper you may want to apply this to get rid of the wrapper in the stacktrace

How to configure logging via log4net in an UWP App

I have an UWP app that uses some of my libraries.
Such libraries use log4net for logging purpose, and are shared across a number of projects, not only UWP.
I'd like to configure log4net via the usual confi section in the XML config file, but I cannot find a way to do this in an UWP project, since there isn't an app.config file.
Where should I put the following section?
<log4net>
<appender name="Console" type="log4net.Appender.ConsoleAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date - %message%newline" />
</layout>
</appender>
<appender name="RollingFile" type="log4net.Appender.RollingFileAppender">
<file value="log\mylog.log" />
<appendToFile value="true" />
<maximumFileSize value="2000KB" />
<maxSizeRollBackups value="20" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date - %message%newline" />
</layout>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="Console" />
<appender-ref ref="RollingFile" />
</root>
</log4net>
Thank you!
To complete pfx answer, if you are using netStandard, you will have to use Configure overloads with an additional parameter log4net.Repository.ILoggerRepository.
I haven't been able to use the ConsoleAppender and switch to the DebugAppender.
You cannot use relative path in UWP with RollingFileAppender since log4net will not have permission to create file in the install location of your application. I think it could work with a full path but I have seen some permissions issues (you should activate debug mode of log4net for this).
Finally, I also made a Custom Appender which writes file in the Local Storage of your application. Here is the code which should be enhanced for production use.
namespace AppWithLog4net
{
public class LocalStorageFileAppender : log4net.Appender.TextWriterAppender
{
private Stream m_stream;
public LocalStorageFileAppender() : base() { }
protected override void PrepareWriter()
{
IAsyncOperation<Windows.Storage.StorageFile> task = Windows.Storage.ApplicationData.Current.LocalCacheFolder.CreateFileAsync("localStorage.log",
Windows.Storage.CreationCollisionOption.GenerateUniqueName);
Windows.Storage.StorageFile file = task.GetAwaiter().GetResult();
m_stream = file.OpenStreamForWriteAsync().Result;
QuietWriter = new log4net.Util.QuietTextWriter(new StreamWriter(m_stream, Encoding.UTF8), ErrorHandler);
WriteHeader();
}
protected override void Reset()
{
m_stream.Dispose();
m_stream = null;
base.Reset();
}
}
}
With the following config file:
<log4net debug="true">
<appender name="Console" type="log4net.Appender.DebugAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date - %message%newline" />
</layout>
</appender>
<appender name="LocalStorageFile" type="AppWithLog4net.LocalStorageFileAppender, AppWithLog4net">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date - %message%newline" />
</layout>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="Console" />
<appender-ref ref="LocalStorageFile" />
</root>
</log4net>
Because there is no App.config file, you are going to have to configure Log4net programmatically.
You can store the settings in a local file (or embedded resource) and read these at application startup; reference: Create and read a local file.
Log4net's XmlConfigurator class can accept these settings as a Stream, FileInfo or XmlElement via one of its Configure overloads.
log4net.Config.XmlConfigurator.Configure(XmlElement config);
log4net.Config.XmlConfigurator.Configure(Stream config);
log4net.Config.XmlConfigurator.Configure(FileInfo config);

Log4net not logging on Azure Webapp

For a web service, I have log4net configured and working fine locally but not when the webapp is deployed on Azure Webapp. The directory is created but there is nothing logged at the file..
Here is my config:
<log4net>
<appender name="RollingFile" type="log4net.Appender.RollingFileAppender">
<file value="log/sms.log" />
<appendToFile value="true" />
<maximumFileSize value="10MB" />
<maxSizeRollBackups value="10" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date %level - %message%newline" />
</layout>
</appender>
<logger name="TheLogger">
<appender-ref ref="RollingFile" />
</logger>
Within my AssemblyInfo.cs I have:
[assembly: XmlConfigurator(Watch = true)]
At the Startup class i have :
public static ILog Logger { get; private set; }
public void Configuration(IAppBuilder appBuilder)
{
Logger = LogManager.GetLogger("TheLogger");
Logger.Info("Application start...");
}
Clearly my configuration is being picked up because in my log file is written the hour/date format and also Application start... but not the logging information.
What am i missing?
Make sure you don't forget to add the root configuration.
Are compiling for Debug and deploying in Azure in Release mode?
<log4net>
<root>
<level value="INFO" />
<appender-ref ref="RollingFile" />
</root>
<appender name="RollingFile" type="log4net.Appender.RollingFileAppender">
<!-- ... -->
</appender>
</log4net>
I had the same problem and found a solution. I had to replace these 2 lines of code in the Program class of the .Net Core API:
XmlDocument log4netConfig = new XmlDocument();
log4netConfig.Load(File.OpenRead("log4net.config"));
With this:
var logRepository = LogManager.GetRepository(Assembly.GetEntryAssembly());
XmlConfigurator.Configure(logRepository, new FileInfo("log4net.config"));
The reason is because in .Net Framework API's I used the assembly attribute to set this, now I need to do it like this.

Log4Net not working in Selenium Framework when Running SpecFlow Tests

I'm struggling with Log4Net for a good while now. I have followed this post
as an example. The difference is, in my case, I have two separate projects, one with all objects that interacts with WebDriver and web elements (FrameworkProject), second is actual test project(TestProject). I have read a lot and I'm almost sure I have set it correctly...
FrameworkProject assembly file includes [assembly: log4net.Config.XmlConfigurator(Watch = true)]
My Log4Net.config file is as follow:
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
</configSections>
<log4net>
<root>
<level value="ALL" />
<appender-ref ref="MyAppender" />
<appender-ref ref="MyFileAppender" />
</root>
<appender name="MyAppender" type="log4net.Appender.ConsoleAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date %level %logger - %message%newline" />
</layout>
</appender>
<appender name="MyFileAppender" type="log4net.Appender.FileAppender">
<file value="application.log" />
<appendToFile value="true" />
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date %level %logger - %message%newline" />
</layout>
</appender>
</log4net>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
</configuration>
When I debug my SpecFlow tests and I reach the line XmlConfigurator.Configure(); (look example above) I'm still getting
log4net:ERROR Failed to find configuration section 'log4net' in the application's.
This drops me mad now and I have no clue of what might be wrong. Could this be the cause of running test?? Note: I have log4net set up ONLY in FrameworkProject
I have log4net set up ONLY in FrameworkProject
That's the problem. Roughly speaking, your "entry point" during test execution is your Test Project, hence it's looking for log4net configuration section inside of "entry point's" application configuration file (Test Project's app.config). Thus you should move your log4net configuration to Test Project's application configuration file.
On a second notice, it looks like you don't need to call XmlConfigurator.Configure if you use assembly level attribute: 1, 2.

log4net BasicConfigurator is not printing on console

I decided to use log4net to handle all the logging activities for the application I am working on... after reading through documentation, I decided to start making experiments, but failed miserably at the very first attempt
The application is being developed with c# using MonoDevelop 3.0.3.2 in a fairly standard Debian 7 distribution, in order to later be deployed on Linux machines.
The code is trivial so far and follows the very early steps in the log4net documentation, and is quoted at the end of the post.
The problem is that the logger does not print anything to console; while trying to understand what's going wrong, I looked intoo it with the debugger; I see that the log reference contains the AppendersCollection, which unfortunately is empty I guess that something is not working properly during configuration and I have no appenders, hence there is no log output.
What am I missing? any suggestion? Is there some sort of a known issue for the combination of MonoDevelop-Linux-log4net I am not aware of?
using System;
using log4net;
using log4net.Config;
namespace TestLog4Net
{
class MainClass
{
private static readonly ILog log = LogManager.GetLogger(typeof(MainClass));
public static void Main (string[] args)
{
BasicConfigurator.Configure();
Console.WriteLine ("Hello World!");
log.Info("Hello World!");
}
}
}
UPDATE
I did some tests loading the configuration file.
I created 3 loggers each with its own appender, two are rolling file appenders, and one is the console appender.
Then I log "Hello World!" on each logger.
The rolling file loggers work as expected, while the output from the ConsoleLogger is nowhere to be found. I checked with the Debugger and the clogger object does NOT display an empty AppenderCollection, but there no output anyway. Below you can find the updated code along with the configuration file.
using System;
using log4net;
using log4net.Config;
namespace TestLog4Net
{
class MainClass
{
public static void Main (string[] args)
{
XmlConfigurator.Configure(new System.IO.FileInfo("app.config"));
ILog rflogger1 = LogManager.GetLogger("RFLoggerOne");
ILog rflogger2 = LogManager.GetLogger("RFLoggerTwo");
ILog clogger = LogManager.GetLogger("CLogger");
rflogger1.Info("Hello World!");
rflogger2.Info("Hello World!");
clogger.Info("Hello World!");
Console.WriteLine ("Hello World!");
}
}
}
<log4net>
<appender name="CAppender" type="log4net.Appender.AnsiColorTerminalAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />
</layout>
</appender>
<appender name="RFAppender1" type="log4net.Appender.RollingFileAppender">
<file value="rf1.log"/>
<appendToFile value="true"/>
<rollingStyle value="Composite"/>
<datePattern value="yyyyMMdd"/>
<maxSizeRollBackups value="10"/>
<maximumFileSize value="1000000"/>
<staticLogFileName value="true"/>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %level %logger - %message%newline"/>
</layout>
</appender>
<appender name="RFAppender2" type="log4net.Appender.RollingFileAppender">
<file value="rf2.log" />
<appendToFile value="true" />
<maximumFileSize value="100KB" />
<maxSizeRollBackups value="2" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%level %thread %logger - %message%newline" />
</layout>
</appender>
<logger name="CLogger">
<level value="ALL"/>
<appender-ref ref="CAppender"/>
</logger>
<logger name="RFLoggerOne">
<level value="ALL"/>
<appender-ref ref="RFAppender1"/>
</logger>
<logger name="RFLoggerTwo">
<level value="ALL"/>
<appender-ref ref="RFAppender2"/>
</logger>
<root>
<level value="ALL"/>
</root>
</log4net>
Which kind of project do you use? A Console Application?
There are several cases you wont see any output on std::out or std::err on your console.
Have a look at this post:
Can one executable be both a console and GUI application?

Categories