Allows to configure Log4net as Microsoft Extensions Logging handler on any ASP.NET Core application.
Thanks to @anuraj for this original blog post.
Install the package or reference the project into your asp.net core application.
Add the AddLog4Net()
call into your Configure
method of the Startup
class.
using Microsoft.Extensions.Logging;
public class Startup
{
//...
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
//...
loggerFactory.AddLog4Net(); // << Add this line
app.UseMvc();
//...
}
}
For dotnet 6.0 and later add builder.Logging.AddLog4Net();
call in your Program.cs
file.
Add a log4net.config
file with the content:
<?xml version="1.0" encoding="utf-8" ?>
<log4net>
<appender name="DebugAppender" type="log4net.Appender.DebugAppender" >
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
</layout>
</appender>
<root>
<level value="ALL"/>
<appender-ref ref="DebugAppender" />
</root>
</log4net>
You can found more configuration examples on configuration documentation.
Associated issues #45
From version 2.2.7, this nuget allow to use the BeginScope
method from Log4NetLogger
.
var dictionary = new Dictionary<string, string>() { { "test", "SCOPED_VALUE" } };
using (var scope = logger.BeginScope(dictionary))
{
logger.LogCritical(message);
}
The BeginScope
method allow any object, but only some of types are handled in an special way. Those types are:
string
IEnumerable<KeyValuePair<string, string>>
IEnumerable<KeyValuePair<string, object>>
ValueTuple<string, T>
where T
is string
, any numeric type or object
By default, any other type will be managed as a conventional object
.
When you use any of the IEnumerable<KeyValuePair<,>>
allowed types, the collection will be processed and every item from this collection should be introduced to the LogicalThreadContext
managed by the log4net library using the Key
as the property name and the Value
as the value to replace the placeholder on the Pattern Layout defined.
This example shows how the log4net.config pattern layout could include a %property{}
placeholder that will be matched within the corresponding scoped value from the collection argument.
<layout type="log4net.Layout.PatternLayout">
<!-- Print the date in ISO 8601 format -->
<conversionPattern value="%date [%thread] %-5level %logger %ndc - scope=%property{scope} - %property{custom_name} - %message%newline" />
</layout>
When you use the BeginScope
method passing a collection that contains a KeyValuePair within the key custom_name
, the logged message will contain the SCOPED_VALUE
text on it.
var dictionary = new Dictionary<string, string>() { { "custom_name", "SCOPED_VALUE" } };
using (var scope = logger.BeginScope(dictionary))
{
logger.LogCritical(message); // SCOPED_VALUE will replace the %property{custom_name} placeholder
}
At the other hand, if the argument is not from the given IEnumerable<KeyValuePair<,>>
, the value will be logged on the default scope
property.
using (var scope = logger.BeginScope("SCOPED_VALUE"))
{
logger.LogCritical(message); // SCOPED_VALUE will replace the %property{scope} placeholder
}
using (var scope = logger.BeginScope(Guid.NewGuid()))
{
logger.LogCritical(message); // Guid value will replace the %property{scope} placeholder
}
And, when you use two chained BeginScope
calls...
using (var scope = logger.BeginScope("SCOPED_VALUE"))
{
using (var scope = logger.BeginScope(Guid.NewGuid()))
{
logger.LogCritical(message); // SCOPED_VALUE and Guid value (both) will replace the %property{scope} placeholder
}
}
For additional information about how the LogicalThreadContext
works, please visit the official documentation
Associated issues #34 & #41
In order to be able to register Debug level messages in any of your configured log4net appenders, you should change the ASP .NET Core 2 configuration when you build your IWebHost
instance as follows.
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureLogging((hostingContext, logging) =>
{
// The ILoggingBuilder minimum level determines the
// the lowest possible level for logging. The log4net
// level then sets the level that we actually log at.
logging.AddLog4Net();
logging.SetMinimumLevel(LogLevel.Debug);
})
.Build();
Associated issues #85
Also note that when trying to allow for levels messages below the Information level for a development build you must make allowances for it in the appsettings.Development.json
as specified in the documentation and illustrated below:
{
"Logging": {
"LogLevel": {
"Default": "Debug",
"...":"..."
}
}
}
In many cases you can modfiy the logging behaviour of the provider to fit your own needs. See modifying logging behaviour for more information.
Thank you very much to all contributors & users by its collaboration, and specially to:
Log4NetScopeFactory
usage when provided in Log4NetProviderOptions
.IExternalScope
provider implementation.ValueTuple
mapping in scopes.