This guide starts with a minimal setup, then covers async mode and terminal output.
Core runtime:
dotnet add package XenoAtom.Logging
Optional terminal integration:
dotnet add package XenoAtom.Logging.Terminal
using XenoAtom.Logging;
using XenoAtom.Logging.Writers;
var config = new LogManagerConfig
{
RootLogger =
{
MinimumLevel = LogLevel.Info,
Writers =
{
new StreamLogWriter(Console.OpenStandardOutput())
}
}
};
LogManager.Initialize(config);
var logger = LogManager.GetLogger("App");
logger.Info("Application started");
logger.Warn($"Retry attempt = {3}");
LogManager.Shutdown();
Key points:
Initialize defaults to synchronous processing.GetLogger("App") resolves a logger category.Shutdown() flushes and disposes writers.When throughput is high, initialize for async processing:
var config = new LogManagerConfig
{
AsyncLogMessageQueueCapacity = 4096,
AsyncErrorHandler = exception =>
{
Console.Error.WriteLine($"[async logging error] {exception.Message}");
},
RootLogger =
{
MinimumLevel = LogLevel.Info,
OverflowMode = LoggerOverflowMode.Block,
Writers =
{
new FileLogWriter("logs/app.log")
}
}
};
LogManager.InitializeForAsync(config);
OverflowMode behavior:
Block (recommended default): preserve correctness and backpressure producers.Drop / DropAndNotify: prioritize producer latency, but allow loss.Allocate: temporarily exceed configured queue capacity.Per-message structured data:
var properties = new LogProperties
{
("requestId", 1423),
("tenant", "alpha")
};
logger.Info(properties: properties, msg: "Processing request");
Scoped contextual data:
using (logger.BeginScope(new LogProperties { ("traceId", "abc-123") }))
{
logger.Info("Inside request scope");
}
using XenoAtom.Logging;
using XenoAtom.Logging.Writers;
var config = new LogManagerConfig
{
RootLogger =
{
Writers =
{
new TerminalLogWriter()
}
}
};
LogManager.Initialize(config);
LogManager.GetLogger("App").InfoMarkup("[green]ready[/]");
LogManager.Shutdown();
See Terminal Integration for styling, markup, and LogControl.