log4net print DateTime/calling class/function on each line - c#

Is there any way using log4net to automatically write date/time and class name/function name to the start of each logged line?

In the log4net configuration file modify Appender section by adding a PatternLayout with custom format. Following pattern will output DateTime ClassName.MethodName
<appender name="DebugOut"
type="log4net.Appender.OutputDebugStringAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date{MM/dd/yy HH:mm} %C{1}.%M" />
</layout>
</appender>
You can output fully qualified name of class by changing %C{1} to %C

Related

Configuring log4net without code in Rider for dotnet 2.1 project

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/

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);

How to shorten log4net logger path

my log4net conversionpattern displays full path to class:
11:40:11,209 [C:\Users\martin\Documents\Visual Studio 2015\Projects\MyProject\MyProject\ViewModels\MainViewModel.cs] DEBUG - Test log
Is there a way how to shorten path to class name only?
11:40:11,209 [MainViewModel.cs] DEBUG - Test log
It's also my typical experience to have trouble with the odd conversion nomenclature and the scant levels of documentation that seems to be available in a central location.
I have adapted the conversion pattern I normally use to get you something similar to what you requested:
<conversionPattern value="%d %-22.22c{1} %-5p - %m%n"/>
The %-22.22c{1} bit is the shortened class name (I guess) :)
The above will result in something like:
2015-12-28 11:11:26,892 MyClass DEBUG - Test log
in the log4net configuration try using
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%-4thread] %-5level %logger{1} - %message%newline"/>
</layout>
use conversion pattern value like following
<conversionPattern value="[%d{yyyy-MM-dd HH:mm:ss}] [%t] %-5p %c - %m%n" />
See more in about conversionPattern

Retrieving file value from log4net's config file

I'm stuck in a situation where I believe I need to know the name of the log file that the user has specified in logging.xml. Specifically, I am trying to retrieve the value of the value attribute in the file element, as shown below (taken from the log4net docs)
For full details see the SDK Reference entry:
log4net.Appender.FileAppender.
The following example shows how to configure the FileAppender to write messages to a file. The file specified is log-file.txt. The file
will be appended to rather than overwritten each time the logging
process starts.
<appender name="FileAppender" type="log4net.Appender.FileAppender">
<file value="log-file.txt" />
<appendToFile value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />
</layout>
</appender>
When I loop over the appenders with the following code:
log4net.Repository.ILoggerRepository repo = LogManager.GetRepository();
foreach (log4net.Appender.IAppender appender in repo.GetAppenders())
{
FileAppender fa = appender as FileAppender;
}
I am unable to find the value "log-file.txt" anywhere in the fa object. Perhaps I have missed it since there are a lot of members and data exposed in the debugger.
Can anyone suggest a way to get at this value?
FileAppender has property File which contains path to the file that logging will be written to. But before you start looking for this property, verify Name of appender - you can have several FileAppenders configured.
Also keep in mind that RollingFileAppender also matches condition appender is FileAppender, because it is derived from FileAppender.
string file = repo.GetAppenders()
.OfType<FileAppender>()
.Where(fa => fa.Name == "FileAppender")
.Single()
.Name;

Setting up Log4Net to log output from a Class Library

I'm trying to setup Log4Net (this is my first time using Log4Net) to log to a text file in an assembly. I'm not getting any errors, but it's also not working. I can breakpoint the lines where I am logging my output and see that they are reached, but like I say nothing happens.
Where am I going wrong?
I have added the following to my packages.config file, inside the <packages> attribute:
<log4net>
<appender name="FileAppender" type="log4net.Appender.FileAppender,log4net">
<file value="c:\CTI\log.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>
I have added the following line to AssemblyInfo.cs:
[assembly: log4net.Config.XmlConfigurator(Watch=true)]
I added the Log4Net assembly using NuGet and I am logging like this:
private log4net.ILog _Log;
_Log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
_Log.Debug("FooBar");
Like I say, no errors but nothing happens either.
What am I missing?
One thing that is wrong is that you are adding the log4net configuration section to the nuget config file (packages.config).
You can have the configuration in the app/web config or in a separate file to which you point from the appSettings, e.g.
configuration is in a file called config.log4net (the copy to output directory attribute of the file is set to copy always) and you add the following entry in app/web.config:
<add key="log4net.config" value="config.log4net"/>
If you don't want to depend on a web/app configuration, you can set the ConfigFileExtension property of the XmlConfiguratorAttribute attribute in AssemblyInfo.cs:
[assembly: log4net.Config.XmlConfigurator(ConfigFileExtension = "log4net", Watch = true)]
Then name the log4net configuration file the same as your exe/assembly plus the configured extension, e.g. MyApplication.exe.log4net or MyLibrary.dll.log4net
Another thing that is wrong is your appender filter. The range that you have set excludes DEBUG level, which you expect to log. Here are all logging levels:
ALL
DEBUG
INFO
WARN
ERROR
FATAL
OFF
As you can see, DEBUG is not between INFO and FATAL.

Categories