RunLog 3.3.0
dotnet add package RunLog --version 3.3.0
NuGet\Install-Package RunLog -Version 3.3.0
<PackageReference Include="RunLog" Version="3.3.0" />
<PackageVersion Include="RunLog" Version="3.3.0" />
<PackageReference Include="RunLog" />
paket add RunLog --version 3.3.0
#r "nuget: RunLog, 3.3.0"
#addin nuget:?package=RunLog&version=3.3.0
#tool nuget:?package=RunLog&version=3.3.0
RunLog
RunLog is a lightweight, customizable logging framework inspired by Serilog. It provides a fluent API for configuring loggers with various sinks, enrichers, and minimum log levels. The framework supports both contextual logging and structured log templates.
Features
- Fluent configuration API
- Multiple log levels (Verbose, Debug, Information, Warning, Error, Fatal)
- Multiple built-in sink types (Console, File)
- File sinks are buffered by default for better performance
- Customizable minimum log levels per sink
- File rolling capabilities (by time interval or size)
- Structured logging with property value capturing
- Thread-safe operation
- Exception logging
- Custom formatters support
- Enrichers for adding custom properties
- Named logger support for component-specific logging
Installation
Install the RunLog package from NuGet:
Install-Package RunLog
# or
dotnet add package RunLog
Package URL: NuGet Gallery
Quick Start
Important: You must configure the logger by setting Log.Logger
before using any logging methods. If you attempt to use logging methods before setting Log.Logger
, an InvalidOperationException
will be thrown.
Here's a simple example to get you started:
using RunLog;
// Configure the logger (this step is required)
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.WriteTo.Console()
.WriteTo.File("logs/app.log", rollingInterval: RollingInterval.Day)
.Enrich("ApplicationName", "MyApp")
.Enrich("Version", "1.0.0")
.CreateLogger();
// Log some messages
Log.Information("Application {AppName} starting up", "MyApp");
Log.Debug("Processing item {ItemId}", 42);
try
{
// Some operation that might throw
throw new System.InvalidOperationException("Something went wrong");
}
catch (Exception ex)
{
Log.Error(ex, "Error processing request");
}
// Optional: You can manually flush logs at any point if needed
// Log.CloseAndFlush();
When you set Log.Logger
, RunLog automatically registers shutdown handlers to ensure logs are properly flushed when your application exits, so you typically don't need to call Log.CloseAndFlush()
explicitly.
Configuration
RunLog uses a fluent configuration API to set up logging:
Setting Minimum Level
// Set minimum level for all sinks
var config = new LoggerConfiguration()
.MinimumLevel.Information(); // Only Information and above will be logged
// Other available levels:
// .MinimumLevel.Verbose()
// .MinimumLevel.Debug()
// .MinimumLevel.Warning()
// .MinimumLevel.Error()
// .MinimumLevel.Fatal()
Console Sink
var config = new LoggerConfiguration()
.WriteTo.Console(); // Uses the global minimum level
// Or specify a minimum level for this sink only
var config = new LoggerConfiguration()
.WriteTo.Console(LogLevel.Warning); // Only Warning and above will go to console
File Sink
File sinks are buffered by default for improved performance.
// Basic file sink (buffered by default)
var config = new LoggerConfiguration()
.WriteTo.File("logs/app.log");
// File sink with custom settings
var config = new LoggerConfiguration()
.WriteTo.File(
path: "logs/app.log",
restrictedToMinimumLevel: LogLevel.Information,
rollingInterval: RollingInterval.Day,
fileSizeLimitBytes: 10 * 1024 * 1024, // 10 MB
retainedFileCountLimit: 31); // Keep last 31 files
// File sink with custom buffering settings
var config = new LoggerConfiguration()
.WriteTo.File(
path: "logs/app.log",
restrictedToMinimumLevel: LogLevel.Debug,
enableBuffering: true, // Enabled by default
bufferSize: 500, // Custom buffer size
flushInterval: TimeSpan.FromSeconds(3)); // Custom flush interval
// Disable buffering for immediate writes (may impact performance)
var config = new LoggerConfiguration()
.WriteTo.File(
path: "logs/app.log",
enableBuffering: false); // Disable buffering for immediate writes
Multiple Sinks
var config = new LoggerConfiguration()
.MinimumLevel.Debug() // Global minimum
.WriteTo.Console(LogLevel.Information) // Console shows Info+
.WriteTo.File("logs/app.log", LogLevel.Debug) // File includes Debug+
.WriteTo.File("logs/errors.log", LogLevel.Error); // Only Error+
Enriching Log Events
Add custom properties to all log events:
var config = new LoggerConfiguration()
.Enrich("ApplicationName", "MyApp")
.Enrich("Environment", "Production")
.Enrich("Version", "1.0.0");
Logging Examples
Basic Logging
Log.Verbose("This is a verbose message");
Log.Debug("This is a debug message");
Log.Information("This is an information message");
Log.Warning("This is a warning message");
Log.Error("This is an error message");
Log.Fatal("This is a fatal error message");
Structured Logging
// Log with named properties
Log.Information("User {UserId} logged in from {IpAddress}", 123, "192.168.1.1");
// Multiple properties
Log.Information(
"Order {OrderId} placed for {Amount} items by customer {CustomerId}",
"ORD-12345",
42,
"CUST-789");
Logging Exceptions
try
{
// Code that might throw
throw new InvalidOperationException("Something went wrong");
}
catch (Exception ex)
{
// Log with the exception
Log.Error(ex, "Failed to process transaction {TransactionId}", "TXN-123");
}
Formatted Values
// Formatting numbers
Log.Information("Amount: {Amount:C}", 123.45); // Currency
Log.Information("Percentage: {Percent:P}", 0.75); // Percentage
Log.Information("Hex value: {Value:X}", 255); // Hex
// Formatting dates
Log.Information("Date: {Date:yyyy-MM-dd}", DateTime.Now);
Log.Information("Time: {Time:HH:mm:ss}", DateTime.Now);
Advanced Usage
Using Named Loggers
RunLog 3.3.0 adds support for named loggers, which allows you to register and retrieve specific logger instances:
// Create a specialized logger for a component
var paymentLogger = new LoggerConfiguration()
.MinimumLevel.Debug()
.WriteTo.File("logs/payments.log")
.Enrich("Component", "PaymentProcessor")
.CreateLogger();
// Register the logger with a name
Log.RegisterLogger("Payments", paymentLogger);
// Later, in payment processing code:
var logger = Log.GetLogger("Payments");
logger.Information("Processing payment for {OrderId}", "ORD-123");
// Check if a specific logger exists
if (Log.LoggerExists("Payments"))
{
// Use the logger
}
Creating a Custom Instance
If you need a separate logger instance with different configuration:
// Create a specific logger for a component
var componentLogger = new LoggerConfiguration()
.MinimumLevel.Debug()
.WriteTo.File("logs/component.log")
.Enrich("Component", "PaymentProcessor")
.CreateLogger();
// Use the component-specific logger
componentLogger.Information("Payment processed for {OrderId}", "ORD-123");
Changing Logger at Runtime
You can replace the global logger at runtime:
// Initial configuration
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Information()
.WriteTo.Console()
.CreateLogger();
// Later, change to a different configuration
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug() // More verbose
.WriteTo.Console()
.WriteTo.File("logs/app.log") // Add file logging
.CreateLogger();
Manual Flushing
While RunLog automatically registers shutdown handlers to flush logs when the application exits, you can manually flush logs at any time if needed:
// Force immediate flush of any buffered logs
Log.CloseAndFlush();
File Rolling Options
RunLog supports various file rolling strategies:
// Roll by time interval
var config = new LoggerConfiguration()
.WriteTo.File("logs/app.log", rollingInterval: RollingInterval.Day); // _yyyyMMdd suffix
// Available intervals:
// RollingInterval.Infinite - no rolling
// RollingInterval.Year - _yyyy suffix
// RollingInterval.Month - _yyyyMM suffix
// RollingInterval.Week - _yyyyWww suffix (ISO week)
// RollingInterval.Day - _yyyyMMdd suffix
// RollingInterval.Hour - _yyyyMMddHH suffix
// RollingInterval.Minute - _yyyyMMddHHmm suffix
// Roll by file size (creates numerical sequence)
var config = new LoggerConfiguration()
.WriteTo.File(
path: "logs/app.log",
fileSizeLimitBytes: 1024 * 1024); // Roll at 1 MB
Combining Size and Time-Based Rolling
var config = new LoggerConfiguration()
.WriteTo.File(
path: "logs/app.log",
rollingInterval: RollingInterval.Day,
fileSizeLimitBytes: 10 * 1024 * 1024, // 10 MB
retainedFileCountLimit: 7); // Keep 7 files
Performance Considerations
File sinks are now buffered by default for better performance, but you can still adjust the buffering settings:
// High-performance configuration with custom buffer settings
var config = new LoggerConfiguration()
.MinimumLevel.Information() // Filter out Debug and Verbose
.WriteTo.File(
path: "logs/app.log",
bufferSize: 1000, // Buffer up to 1000 log events
flushInterval: TimeSpan.FromSeconds(2)); // Flush every 2 seconds
For scenarios requiring immediate writes regardless of performance impact:
// Disable buffering for immediate writes
var config = new LoggerConfiguration()
.WriteTo.File(
path: "logs/app.log",
enableBuffering: false); // Immediate writes
Error Handling
RunLog includes built-in error handling with retry mechanisms and fallback logging:
// The File sink will automatically:
// - Retry file writes up to 3 times with increasing delay
// - Fall back to temporary directory logging if the target location is inaccessible
// - Handle transient file access issues gracefully
Thread Safety
All logging operations in RunLog are thread-safe by default. In version 3.3.0, thread safety has been enhanced with comprehensive synchronization locks:
// These operations can be safely called from multiple threads
Log.Information("Processing request from thread {ThreadId}", Thread.CurrentThread.ManagedThreadId);
Full Example
Here's a comprehensive example showcasing multiple features:
using System;
using System.Threading;
using RunLog;
namespace LoggingDemo
{
class Program
{
static void Main(string[] args)
{
// Configure the logging system
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.Enrich("Application", "LoggingDemo")
.Enrich("Environment", "Development")
.Enrich("Version", "1.0.0")
.WriteTo.Console(LogLevel.Information)
.WriteTo.File(
path: "logs/app.log",
restrictedToMinimumLevel: LogLevel.Information,
rollingInterval: RollingInterval.Day,
fileSizeLimitBytes: 10 * 1024 * 1024,
retainedFileCountLimit: 7)
.WriteTo.File(
path: "logs/debug.log",
restrictedToMinimumLevel: LogLevel.Debug,
rollingInterval: RollingInterval.Day,
bufferSize: 100,
flushInterval: TimeSpan.FromSeconds(5))
.CreateLogger();
// Create and register a component-specific logger
var orderLogger = new LoggerConfiguration()
.MinimumLevel.Debug()
.WriteTo.File("logs/orders.log")
.Enrich("Component", "OrderProcessor")
.CreateLogger();
Log.RegisterLogger("Orders", orderLogger);
try
{
Log.Information("Application starting up");
// Simulating application activity
for (int i = 0; i < 5; i++)
{
Log.Debug("Processing item {ItemIndex}", i);
// Use the component-specific logger
if (i % 2 == 0)
{
Log.GetLogger("Orders").Information("Creating order for item {ItemIndex}", i);
Log.Information("Successfully processed item {ItemIndex}", i);
}
else
{
Log.Warning("Item {ItemIndex} had issues during processing", i);
}
Thread.Sleep(100); // Simulate work
}
// Simulate an error
try
{
throw new InvalidOperationException("Simulated error for demonstration");
}
catch (Exception ex)
{
Log.Error(ex, "Error occurred during processing of {Operation}", "DemoOperation");
}
Log.Information("Application shutting down normally");
}
catch (Exception ex)
{
Log.Fatal(ex, "Unexpected error caused application to terminate");
throw;
}
// No need to call Log.CloseAndFlush() as it's automatically handled on application exit
}
}
}
Dependencies
RunLog 3.3.0 has no external dependencies. All necessary functionality for date/time calculations, file operations, and thread synchronization is implemented directly within the package.
Changes in 3.3.0
- Added named logger functionality (RegisterLogger, GetLogger, LoggerExists)
- Enhanced thread safety with comprehensive synchronization locks
- Added public Sinks property to Logger class for inspection
- Improved buffering support with background thread processing
- Better error handling in FileSink with retry logic for transient IO issues
- Enhanced message rendering with improved format specifier handling
- Added fallback error handling for file write operations
- Improved shutdown handling with enhanced resource disposal
- Added comprehensive XML documentation comments
Changes in 3.2.0
- Removed dependency on AaTurpin.Utilities package
- Implemented internal versions of date/time utilities and file path handling
- Maintained compatibility with all core logging features
License
MIT
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET Framework | net472 is compatible. net48 was computed. net481 was computed. |
-
.NETFramework 4.7.2
- No dependencies.
NuGet packages (4)
Showing the top 4 NuGet packages that depend on RunLog:
Package | Downloads |
---|---|
AaTurpin.SleepManager
AaTurpin.SleepManager is a .NET NuGet package that provides a simple interface to control the Windows system's sleep behavior. It allows your applications to temporarily prevent the system from entering sleep mode or turning off the display, which is particularly useful for long-running operations, presentations, or media playback scenarios. |
|
AaTurpin.NetworkFileManager
A robust, high-performance file management library for .NET Framework 4.7.2 applications, specifically designed for reliable file operations across network locations and local storage. |
|
AaTurpin.ConfigManager
A comprehensive .NET library for managing application configuration with support for type-safe settings, directory entries, and network drive mappings. ConfigManager simplifies reading and writing app.config values, handling directories with exclusion paths, and maintaining drive mappings with integrated logging via RunLog. |
|
AaTurpin.NamedPipes
A lightweight, robust .NET Framework library for inter-process communication using Windows named pipes. Simplifies creation of named pipe servers and clients with features including automatic reconnection, thread-safe operations, comprehensive logging integration, and proper resource management. Ideal for building reliable inter-process communication in desktop applications and Windows services. |
GitHub repositories
This package is not used by any popular GitHub repositories.
RunLog 3.3.0 Release Notes
New Features:
* Added named logger functionality (RegisterLogger, GetLogger, LoggerExists)
* Enhanced thread safety with synchronization locks in Logger class
* Added public Sinks property to Logger class for inspection
* Improved buffering support with optional background thread processing
Improvements:
Better error handling in FileSink with retry logic for transient IO issues
Enhanced message rendering with improved format specifier handling
Added fallback error handling for file write operations
Improved shutdown handling with enhanced resource disposal
Added comprehensive XML documentation comments
Bug Fixes:
Fixed issues with initialization of collection properties
Enhanced error handling in CloseAndFlush operations
Resolved thread safety issues in logging operations
Compatible:
Maintains compatibility with .NET Framework 4.7.2
No breaking changes to core API
Backward compatible with applications using RunLog 3.2.0