﻿# Log4Net


> [!WARNING]
> NServiceBus.Log4Net is obsolete. NServiceBus now supports logging libraries through Microsoft.Extensions.Logging. See [Logging in .NET Core and ASP.NET Core](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/logging/) for details.

## Logging integration into the host

When using NServiceBus 10.2 or later with the [.NET Generic Host](/nservicebus/hosting/core-hosting.md), configure Log4Net directly on the host builder. The bridge package is not required:

```csharp
var builder = Host.CreateApplicationBuilder();

builder.Logging.AddLog4Net();

builder.Services.AddNServiceBusEndpoint(endpointConfiguration);
```

For more information, see [Hosting with Microsoft.Extensions.Hosting](/nservicebus/hosting/core-hosting.md).

## Usage

<!-- snippet: Log4NetInCode -->

```cs
var layout = new PatternLayout
{
    ConversionPattern = "%d [%t] %-5p %c [%x] - %m%n"
};
layout.ActivateOptions();
var consoleAppender = new ConsoleAppender
{
    Threshold = Level.Debug,
    Layout = layout
};
consoleAppender.ActivateOptions();

var executingAssembly = Assembly.GetExecutingAssembly();
var repository = log4net.LogManager.GetRepository(executingAssembly);
BasicConfigurator.Configure(repository, consoleAppender);

LogManager.Use<Log4NetFactory>();
```

<!-- endsnippet -->


## Filtering

NServiceBus can write a significant amount of information to the log. To limit this information, use the filtering features of the underlying logging framework.

For example, to limit log output to a specific namespace.

The following code example adds a [filter](https://logging.apache.org/log4net/manual/configuration.html#filters).

### The Filter

<!-- snippet: Log4NetFilter -->

```cs
public class NServiceBusLogFilter :
    FilterSkeleton
{
    public override FilterDecision Decide(LoggingEvent loggingEvent)
    {
        if (loggingEvent.LoggerName.StartsWith("NServiceBus."))
        {
            if (loggingEvent.Level < Level.Warn)
            {
                return FilterDecision.Deny;
            }
        }
        return FilterDecision.Neutral;
    }
}
```

<!-- endsnippet -->


### Using the Filter

<!-- snippet: Log4NetFilterUsage -->

```cs
var appender = new ConsoleAppender
{
    Threshold = Level.Debug,
    Layout = new SimpleLayout(),
};

appender.AddFilter(new NServiceBusLogFilter());
appender.ActivateOptions();

var executingAssembly = Assembly.GetExecutingAssembly();
var repository = log4net.LogManager.GetRepository(executingAssembly);
BasicConfigurator.Configure(repository, appender);

NServiceBus.Logging.LogManager.Use<Log4NetFactory>();
```

<!-- endsnippet -->


## Additional exception data

Starting with NServiceBus version 7.2, exceptions from failing message handlers might contain additional error information in the `Exception.Data` property. Log4Net does not log this information by default, but it can be configured to do so using a custom `PatternLayoutConverter`:

<!-- snippet: ExceptionDataConverter -->

```cs
class ExceptionDataConverter : PatternLayoutConverter
{
    protected override void Convert(TextWriter writer, LoggingEvent loggingEvent)
    {
        var exceptionData = loggingEvent.ExceptionObject?.Data;
        if (exceptionData != null)
        {
            foreach (var key in exceptionData.Keys)
            {
                writer.WriteLine("{0}: {1}", key, exceptionData[key]);
            }
        }
    }
}
```

<!-- endsnippet -->

The custom converter can then be registered and incorporated into the log layout:

<!-- snippet: RegisterConverter -->

```cs
var layout = new PatternLayout
{
    ConversionPattern = "%d %-5p %c - %m%n%exception_data"
};
layout.AddConverter("exception_data", typeof(ExceptionDataConverter));
layout.ActivateOptions();
```

<!-- endsnippet -->
