In this post, you’ll learn how to integrate log4net into a C# project using a thread-safe Singleton logger class. This design ensures that your application uses a single, centralized logger instance, improving performance and maintaining consistency throughout the application lifecycle. We’ll walk through each step from installation and configuration to full implementation and usage.
How to Implement log4net in C# Using a Singleton Class
Getting Started
Logging is a critical part of any application’s architecture. Whether you're diagnosing production issues, tracking application behavior, or monitoring performance, a reliable logging system saves time and helps maintain system stability. One of the most widely adopted logging frameworks in the .NET ecosystem is log4net, known for its flexibility, performance, and ease of configuration.
Why Use log4net
log4net is a powerful, open-source logging library for .NET applications. It supports:- Multiple output targets (file, console, database, event log, email)
- Flexible formatting and filtering
- Rolling logs (daily, size-based, or composite)
- Easy configuration through XML
Benefits of Using a Singleton Logger
Using a Singleton pattern for logging provides several advantages:- Single shared logger instance: Avoids redundant logger creation and ensures consistent configuration.
- Thread-safe logging: Ensures concurrent logging does not cause race conditions.
- Centralized control: All logs originate from a unified logging class.
- Improved performance: Reduces memory overhead and object creation.
Implement log4net Using a Singleton Class
Here are the steps to integrate log4Net with code examples
Prerequisites Before implementing log4net, ensure that you have:- Visual Studio / Rider / VS Code
- .NET Framework or .NET Core project
- Basic understanding of C# classes and XML configuration
Install log4net
You can install log4net via NuGet Package Manager in Visual Studio or via the .NET CLI. If you want to know how to install NuGet package, then visit this post "Installing NuGet Packages: A Beginner's Guide".
Add log4net Appenders
An log4net appender is a name for what logs the information. It specifies where the information will be logged, how it will be logged, and under what circumstances the information will be logged. There are various log4net appenders are available, to know more the appenders visit this post "How to use log4net in C#"
<log4net>
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="Logs/application.log" />
<appendToFile value="true" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="5" />
<maximumFileSize value="5MB" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
</layout>
</appender>
<root>
<level value="ALL" />
<appender-ref ref="RollingFileAppender" />
</root>
</log4net>
Find the </configuration> tag and paste below code just before the </configuration> tag. This is the log level and appender setting in config for log4net, The code should place between <configuration> and </configuration> tag.
Create a Thread-Safe Singleton Class
using log4net;
using log4net.Config;
using System;
using System.IO;
public sealed class LogManagerSingleton
{
private static readonly Lazy<LogManagerSingleton> _instance =
new Lazy<LogManagerSingleton>(() => new LogManagerSingleton());
private readonly ILog _logger;
public static LogManagerSingleton Instance => _instance.Value;
private LogManagerSingleton()
{
// Load log4net configuration
var logRepository = log4net.LogManager.GetRepository();
XmlConfigurator.Configure(logRepository, new FileInfo("log4net.config"));
_logger = LogManager.GetLogger(typeof(LogManagerSingleton));
}
public void Info(string message) => _logger.Info(message);
public void Debug(string message) => _logger.Debug(message);
public void Error(string message, Exception ex = null)
{
if (ex == null)
_logger.Error(message);
else
_logger.Error(message, ex);
}
public void Warn(string message) => _logger.Warn(message);
public void Fatal(string message) => _logger.Fatal(message);
}
Using the Singleton Logger
class Program
{
static void Main(string[] args)
{
LogManagerSingleton.Instance.Info("Application started.");
try
{
throw new Exception("Test exception");
}
catch (Exception ex)
{
LogManagerSingleton.Instance.Error("An error occurred", ex);
}
}
}
Best Practices
- Log only meaningful information.
- Avoid logging sensitive data (passwords, tokens).
- Use log levels appropriately.
- Monitor file size and storage usage.
Summary
Thanks