Table of Contents

Configuration Reference

LogManager initialization

Log.Initialize(config =>
{
    // Global minimum level (default: Information)
    config.MinimumLevel = LogLevel.Debug;

    // Per-category minimum level override
    config.SetMinimumLevel("Renderer", LogLevel.Trace);         // by string
    config.SetMinimumLevel<NetworkLog>(LogLevel.Warning);       // by type (recommended)

    // Internal error handler for sink exceptions
    config.InternalErrorHandler = ex => Console.Error.WriteLine($"Logging error: {ex}");

    // Add sinks (all accept optional ILogFormatter parameter)
    config.AddConsoleSink();
    config.AddConsoleSink(colored: false, formatter: NullLogFormatter.Instance);
    config.AddFileSink("logs/app.log");
    config.AddFileSink("logs/app.log", rollingInterval: RollingInterval.Daily);
    config.AddFileSink("logs/app.log", rollingInterval: RollingInterval.Hourly,
                       maxFileSizeBytes: 50_000_000);
    config.AddFileSink("logs/app.log", shared: true);  // multi-process safe
    config.AddStreamSink(networkStream, leaveOpen: true);
    config.AddDebugSink();
    config.AddSink(new CustomSink());

    // Dynamic level switching (optional)
    config.WatchEnvironmentVariable("MY_LOG_LEVEL");
    config.WatchEnvironmentVariable("MY_LOG_LEVEL", pollInterval: TimeSpan.FromSeconds(10));
    config.WatchConfigFile("logsmith.json");
});

Runtime reconfiguration

LogManager.Reconfigure(config =>
{
    config.ClearSinks();
    config.MinimumLevel = LogLevel.Warning;
    config.AddConsoleSink();
});

The configuration object is immutable. Reconfiguration builds a new config and swaps it atomically via a volatile write. The hot path reads the config through a single volatile read with no locking. Active monitors from the previous config are disposed.

Flushing and shutdown

Sinks that implement IFlushableLogSink (including FileSink, StreamSink, and BufferedLogSink subclasses) support explicit flushing:

// Flush all buffered sinks
await LogManager.FlushAsync();
await LogManager.FlushAsync(timeout: TimeSpan.FromSeconds(5));

// Graceful shutdown: flush all sinks, then dispose
await LogManager.ShutdownAsync();
await LogManager.ShutdownAsync(timeout: TimeSpan.FromSeconds(10));

// Synchronous shutdown (blocks)
LogManager.Shutdown();

BufferedLogSink tracks dropped messages when its bounded channel is full. The DroppedCount property reports the total, and drops are reported via the errorHandler callback (as LogDroppedException).

Global exception handler

LogManager.Initialize(cfg =>
{
    cfg.InternalErrorHandler = ex => Console.Error.WriteLine(ex);
    cfg.CaptureUnhandledExceptions(observeTaskExceptions: false); // true to call SetObserved()
    // ...
});
// Automatically unsubscribed on Reconfigure() or Shutdown()

MSBuild properties

<PropertyGroup>
    <!-- Operating mode: Shared, Standalone, or Abstraction -->
    <!-- Default: Shared (Logsmith package) or Standalone (Logsmith.Generator package) -->
    <LogsmithMode>Shared</LogsmithMode>

    <!-- Conditional compilation threshold (default: Debug) -->
    <LogsmithConditionalLevel>Debug</LogsmithConditionalLevel>

    <!-- Namespace for abstraction mode public types (default: {RootNamespace}.Logging) -->
    <LogsmithNamespace>MyLib.Logging</LogsmithNamespace>
</PropertyGroup>