Log4net is a reliable logging library with a long history. In modern .NET environments, you can use it through the standard Microsoft logging interface (ILogger). This is useful if you want to reuse existing assets or use specific features like log4net’s powerful rotation settings.
Implementation Sample: Daily Data Aggregation Batch
In this example, we create a setup where an “AggregationService” runs and records only important logs (Warning or higher) into a file named daily-batch.log.
1. Package Installation
Install the required adapter package:
dotnet add package Microsoft.Extensions.Logging.Log4Net.AspNetCore
2. Creating log4net.config
Create a log4net.config file in the project root. Note: In the file properties, ensure you set “Copy to Output Directory” to “Copy always”.
The following configuration splits the log file every 50MB and keeps up to 5 backup generations.
<?xml version="1.0" encoding="utf-8" ?>
<log4net>
<root>
<level value="ALL" />
<appender-ref ref="RollingFile" />
</root>
<appender name="RollingFile" type="log4net.Appender.RollingFileAppender">
<file value="logs/daily-batch.log" />
<appendToFile value="true" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="5" />
<maximumFileSize value="50MB" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%-5level] %logger - %message%newline" />
</layout>
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="WARN" />
<levelMax value="FATAL" />
</filter>
</appender>
</log4net>
3. Program.cs (Integrating log4net)
By adding .AddLog4Net() during host construction, log4net becomes the output destination for the entire application.
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.DependencyInjection;
namespace BatchSystem
{
class Program
{
static async Task Main(string[] args) =>
await CreateHostBuilder(args).Build().RunAsync();
private static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureLogging((context, logging) =>
{
// Clear standard log providers
logging.ClearProviders();
// Set minimum log level (allowing Trace and above)
logging.SetMinimumLevel(LogLevel.Trace);
// Add log4net (it loads log4net.config from the root by default)
logging.AddLog4Net();
})
.ConfigureServices((context, services) =>
{
// Register the aggregation service
services.AddHostedService<AggregationService>();
});
}
}
4. AggregationService.cs (Logging Implementation)
In the class that outputs logs, there is no dependency on log4net. You can write your code using the standard ILogger.
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System.Threading;
using System.Threading.Tasks;
namespace BatchSystem
{
public class AggregationService : BackgroundService
{
private readonly ILogger<AggregationService> _logger;
public AggregationService(ILogger<AggregationService> logger)
{
_logger = logger;
}
protected override Task ExecuteAsync(CancellationToken stoppingToken)
{
// --- These logs will not be written to the file due to settings (Information and below) ---
_logger.LogTrace("Detail: Starting memory usage measurement");
_logger.LogDebug("Debug: DB connection string parsed successfully");
_logger.LogInformation("Info: Daily aggregation process started");
// --- These logs will be recorded in the file (daily-batch.log) (Warning and above) ---
// Warning: Process continues, but needs attention
_logger.LogWarning("Warning: Some target data is missing (Date: 2025-01-10)");
// Error: Case where a process failed
_logger.LogError("Error: No write permission for the output directory");
// Critical: System must stop
_logger.LogCritical("Critical: Database connection lost. Terminating process.");
return Task.CompletedTask;
}
}
}
Explanation
Filtering Behavior
In this setup, even if you write LogInformation in your code, the filter <levelMin value="WARN" /> in log4net.config will block it. Therefore, it will not appear in the log file. This allows you to check everything in the console during development while keeping only errors in the production log file.
Config File Placement
Many issues where log4net.config is not loaded are caused by the file not being copied to the execution folder (bin/Debug/...) during the build. Always check that <CopyToOutputDirectory>Always</CopyToOutputDirectory> is set in the file properties or the .csproj file.
