### Install lunet tool Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/AGENTS.md Install the lunet dotnet tool globally. Run once before building the site. ```bash dotnet tool install -g lunet ``` -------------------------------- ### Default style example output Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/terminal-visuals.md Example log output with default styling, showing Info, Warning, and Error levels with timestamps and exception details. ```text 2026-02-09 18:21:04.7253194 INF Sample.App: Service started 2026-02-09 18:21:04.7319831 WRN Sample.App: Queue latency above threshold 2026-02-09 18:21:04.7424107 ERR Sample.App [42]: Failed to process request System.InvalidOperationException: boom ``` -------------------------------- ### Configure and use TerminalLogWriter Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/terminal.md Shows how to initialize XenoAtom.Logging with a TerminalLogWriter, set the minimum log level to Info, and log a message. The example includes creating a LogManagerConfig, initializing the LogManager, getting a logger, and shutting down. ```csharp using XenoAtom.Logging; using XenoAtom.Logging.Writers; var config = new LogManagerConfig { RootLogger = { MinimumLevel = LogLevel.Info, Writers = { new TerminalLogWriter() } } }; LogManager.Initialize(config); var logger = LogManager.GetLogger("Sample.Terminal"); logger.Info("Hello terminal"); LogManager.Shutdown(); ``` -------------------------------- ### Alignment example with [LogFormatter] Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/log-formatter.md Example formatter using alignment specifiers for Level and LoggerName. Demonstrates that values longer than alignment width are not truncated. ```csharp [LogFormatter("{Level,-5} {LoggerName,30} {Text}")] public sealed partial record Example : LogFormatter; ``` -------------------------------- ### Markup message example output Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/terminal-visuals.md Example log output with markup tags in messages, rendered when EnableMarkupMessages is enabled. ```text 2026-02-09 18:21:04.7501062 INF Sample.Terminal: ready worker=api-1 2026-02-09 18:21:04.7529450 ERR Sample.Terminal: failed request=REQ-0042 ``` -------------------------------- ### Minimal synchronous logging setup Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/getting-started.md Initializes XenoAtom.Logging with synchronous processing, writes to standard output, and logs an info and warning message. Shutdown flushes and disposes writers. ```csharp 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(); ``` -------------------------------- ### Asynchronous logging setup with FileLogWriter Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/getting-started.md Initializes logging for asynchronous processing with a queue capacity of 4096 and an error handler. Uses a file writer and Block overflow mode to preserve correctness. ```csharp 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); ``` -------------------------------- ### Install XenoAtom.Logging core package Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/packages.md Adds the core XenoAtom.Logging package to a project. Includes LogManager, Logger, scopes, processors, formatters, writers, and source generators. ```sh dotnet add package XenoAtom.Logging ``` -------------------------------- ### Install XenoAtom.Logging.Terminal package Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/packages.md Adds the terminal sink package for CLI/console apps. Provides TerminalLogWriter and markup logging extensions. ```sh dotnet add package XenoAtom.Logging.Terminal ``` -------------------------------- ### HTML banner structure Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/banner.md Banner markup with project logo, title, description, feature pills, install command, and links. ```html ``` -------------------------------- ### Rendered output of visual attachment Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/terminal-visuals.md Example terminal output showing the rendered table with the log message. ```text 2026-02-09 18:21:04.7604120 INF Sample.Terminal: Run summary ┌───────────────┬────────┬───────────┐ │ Step │ Status │ Duration │ ├───────────────┼────────┼───────────┤ │ Initialize │ OK │ 00:00.045 │ │ ProcessRequest│ FAILED │ 00:00.003 │ └───────────────┴────────┴───────────┘ ``` -------------------------------- ### Add reject and accept filters to a writer Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/filtering.md Adds a reject filter to suppress loggers whose name starts with 'App.Noisy' and an accept filter to only allow log entries with level Warn or higher. ```csharp fileWriter.RejectFilters.Add(static m => m.Logger.Name.StartsWith("App.Noisy", StringComparison.Ordinal)); fileWriter.AcceptFilters.Add(static m => m.Level >= LogLevel.Warn); ``` -------------------------------- ### Conditional sections example with [LogFormatter] Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/log-formatter.md Shows conditional sections that emit content only when referenced emptyable fields are non-empty. Here, [{EventId}] appears only when EventId is present, and | {Exception} only when an exception is attached. ```csharp [LogFormatter("{Timestamp} {Level} {LoggerName}{? [{EventId}]?} {Text}{? | {Exception}?}")] public sealed partial record Standardish : LogFormatter; ``` -------------------------------- ### Build the website with lunet Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/AGENTS.md Build the site using lunet. Always run this after changing files under site/**. Execute from the site folder. ```bash lunet build ``` -------------------------------- ### Run HelloLogControl sample Source: https://github.com/xenoatom/xenoatom.logging/blob/main/samples/readme.md Command to run the HelloLogControl sample project from the repository root. Demonstrates writing logs to a LogControl in a fullscreen UI with rich formatting and background-thread marshaling. ```sh dotnet run --project samples/HelloLogControl/HelloLogControl.csproj -c Release ``` -------------------------------- ### Build and test commands Source: https://github.com/xenoatom/xenoatom.logging/blob/main/AGENTS.md Commands to build, test, and build the documentation site from the project root. Run from the project root folder. ```sh # from the project root (this folder) cd src dotnet build -c Release dotnet test -c Release cd ../site lunet build ``` -------------------------------- ### Run HelloLogging sample Source: https://github.com/xenoatom/xenoatom.logging/blob/main/samples/readme.md Command to run the HelloLogging sample project from the repository root. Demonstrates rich terminal styling, markup logging, visual attachments, scoped properties, and exception logging. ```sh dotnet run --project samples/HelloLogging/HelloLogging.csproj -c Release ``` -------------------------------- ### Run all benchmarks Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/benchmarks.md Runs the full benchmark suite from the repository root in Release configuration. ```sh dotnet run --project src/XenoAtom.Logging.Benchmark/XenoAtom.Logging.Benchmark.csproj -c Release ``` -------------------------------- ### Run preset suites Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/benchmarks.md Runs the predefined benchmark suites 'comparison' and 'async' as implemented in Program.cs. ```sh dotnet run --project src/XenoAtom.Logging.Benchmark/XenoAtom.Logging.Benchmark.csproj -c Release -- --suite comparison ``` ```sh dotnet run --project src/XenoAtom.Logging.Benchmark/XenoAtom.Logging.Benchmark.csproj -c Release -- --suite async ``` -------------------------------- ### List available suites Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/benchmarks.md Lists all available preset suites and their aliases. ```sh dotnet run --project src/XenoAtom.Logging.Benchmark/XenoAtom.Logging.Benchmark.csproj -c Release -- --list-suites ``` -------------------------------- ### Run FileJsonLogging sample Source: https://github.com/xenoatom/xenoatom.logging/blob/main/samples/readme.md Command to run the FileJsonLogging sample project from the repository root. Demonstrates text and JSON lines logging with rolling and retention options, structured properties, scopes, event IDs, and exception logging. ```sh dotnet run --project samples/FileJsonLogging/FileJsonLogging.csproj -c Release ``` -------------------------------- ### Configure and initialize XenoAtom.Logging with file writer Source: https://github.com/xenoatom/xenoatom.logging/blob/main/readme.md Creates a LogManagerConfig with a FileLogWriter that rolls daily, limits file size to 10 MB, rolls on startup, and retains 7 files. Initializes the logger, logs a message, and shuts down. The default processor is synchronous. ```csharp using XenoAtom.Logging; using XenoAtom.Logging.Writers; var config = new LogManagerConfig { RootLogger = { MinimumLevel = LogLevel.Info, Writers = { new FileLogWriter( new FileLogWriterOptions("logs/app.log") { FileSizeLimitBytes = 10 * 1024 * 1024, RollingInterval = FileRollingInterval.Daily, RollOnStartup = true, RetainedFileCountLimit = 7 }) } } }; LogManager.Initialize(config); // sync processor by default var logger = LogManager.GetLogger("Sample"); logger.Info($"Hello {42}"); LogManager.Shutdown(); ``` -------------------------------- ### XenoAtom.Logging minimal configuration Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/microsoft-extensions-logging.md Initializes XenoAtom.Logging with a LogManagerConfig that sets minimum level to Info and uses a StreamLogWriter writing to standard output. ```csharp using XenoAtom.Logging; using XenoAtom.Logging.Writers; var config = new LogManagerConfig { RootLogger = { MinimumLevel = LogLevel.Info, Writers = { new StreamLogWriter(Console.OpenStandardOutput()) } } }; LogManager.Initialize(config); ``` -------------------------------- ### Configure rolling and retention for FileLogWriter Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/file-writer.md Creates a FileLogWriter with a 10 MB size limit, daily rolling, retention of 14 archives, and startup rollover. Archived files are named app..log using UTC timestamps. Set RetainedFileCountLimit to null to disable cleanup; FlushToDisk forces durable writes. ```csharp var writer = new FileLogWriter( new FileLogWriterOptions("logs/app.log") { FileSizeLimitBytes = 10 * 1024 * 1024, // 10 MB RollingInterval = FileRollingInterval.Daily, RetainedFileCountLimit = 14, // defaults to 31; set null to keep indefinitely RollOnStartup = true, AutoFlush = false, ArchiveTimestampMode = FileArchiveTimestampMode.Utc, FlushToDisk = false }); ``` -------------------------------- ### Basic file logging with FileLogWriter Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/file-writer.md Configures the root logger to write to logs/app.log at Info level. If the file already contains data, it is archived and a fresh file is created on startup. ```csharp using XenoAtom.Logging; using XenoAtom.Logging.Writers; var config = new LogManagerConfig { RootLogger = { MinimumLevel = LogLevel.Info, Writers = { new FileLogWriter("logs/app.log") } } }; LogManager.Initialize(config); ``` -------------------------------- ### Add XenoAtom.Logging NuGet packages Source: https://github.com/xenoatom/xenoatom.logging/blob/main/readme.md Use these dotnet CLI commands to add the core and terminal packages to your project. ```sh dotnet add package XenoAtom.Logging dotnet add package XenoAtom.Logging.Terminal ``` -------------------------------- ### Recommended usage for service/hosted apps Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/shutdown.md Wrap the application run in a try-finally block to ensure LogManager.Shutdown() is called, guaranteeing a coordinated stop and resource cleanup. ```csharp try { RunApplication(); } finally { LogManager.Shutdown(); } ``` -------------------------------- ### Run async-consumer scenarios Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/benchmarks.md Runs only benchmarks in the AsyncEnabledStructured or AsyncEnabledException categories. ```sh dotnet run --project src/XenoAtom.Logging.Benchmark/XenoAtom.Logging.Benchmark.csproj -c Release -- --anyCategories AsyncEnabledStructured AsyncEnabledException ``` -------------------------------- ### Configure logger hierarchy with RootLogger and Loggers Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/filtering.md Sets up a root logger with a file writer and adds a named logger config for 'App.Http' with Debug level and both file and JSON writers, with includeParents set to true. ```csharp using XenoAtom.Logging; using XenoAtom.Logging.Writers; var fileWriter = new FileLogWriter("logs/app.log"); var jsonWriter = new JsonFileLogWriter("logs/app.jsonl"); var config = new LogManagerConfig { RootLogger = { MinimumLevel = LogLevel.Info, Writers = { fileWriter } } }; // "App.Http" and children become Debug and fan out to both writers. config.Loggers.Add("App.Http", LogLevel.Debug, [fileWriter, jsonWriter], includeParents: true); ``` -------------------------------- ### MEL minimal logging configuration Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/microsoft-extensions-logging.md Configures logging with Microsoft.Extensions.Logging, setting minimum level to Information and adding a console provider. ```csharp builder.Services.AddLogging(logging => { logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Information); logging.AddConsole(); }); ``` -------------------------------- ### Configure StreamLogWriter with CompactLogFormatter Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/log-formatter.md Sets a CompactLogFormatter on a StreamLogWriter writing to standard output. Requires the XenoAtom.Logging, XenoAtom.Logging.Formatters, and XenoAtom.Logging.Writers namespaces. ```csharp using XenoAtom.Logging; using XenoAtom.Logging.Formatters; using XenoAtom.Logging.Writers; var config = new LogManagerConfig { RootLogger = { Writers = { new StreamLogWriter(Console.OpenStandardOutput()) { Formatter = CompactLogFormatter.Instance } } } }; LogManager.Initialize(config); ``` -------------------------------- ### Add XenoAtom.Logging package reference Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/log-formatter.md Adds the XenoAtom.Logging NuGet package to enable the generator/analyzer. A single package reference is sufficient. ```xml ``` -------------------------------- ### Terminal output with markup Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/getting-started.md Initializes logging with a TerminalLogWriter and logs a message with markup formatting. Requires the XenoAtom.Logging.Terminal package. ```csharp 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(); ``` -------------------------------- ### Use markup logging methods Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/terminal.md Calls InfoMarkup and ErrorMarkup with markup tags to render colored messages. ```csharp logger.InfoMarkup("[green]ready[/] [gray]service started[/]"); logger.ErrorMarkup($"[red]failed[/] request={requestId}"); ``` -------------------------------- ### Configure FileLogWriter with DetailedLogFormatter via options Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/log-formatter.md Creates a FileLogWriter with a DetailedLogFormatter using FileLogWriterOptions. The log file path is 'logs/app.log'. ```csharp using XenoAtom.Logging.Formatters; using XenoAtom.Logging.Writers; var writer = new FileLogWriter( new FileLogWriterOptions("logs/app.log") { Formatter = DetailedLogFormatter.Instance }); ``` -------------------------------- ### Enable async processing in XenoAtom.Logging Source: https://github.com/xenoatom/xenoatom.logging/blob/main/readme.md Sets an async error handler and initializes the logger with an async processor. Use this instead of the default synchronous Initialize when you need asynchronous logging. ```csharp config.AsyncErrorHandler = exception => { Console.Error.WriteLine($"[logging async error] {exception}"); }; LogManager.InitializeForAsync(config); ``` -------------------------------- ### dotnet publish command for Native AOT Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/aot.md Recommended publish command for Native AOT and trimming. Replace win-x64 with your runtime identifier. ```sh dotnet publish -c Release -r win-x64 -p:PublishAot=true -p:PublishTrimmed=true ``` -------------------------------- ### Access generated Instance property Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/log-formatter.md Retrieves the singleton instance of a template-generated formatter. ```csharp var formatter = MyLogFormatter.Instance; ``` -------------------------------- ### Run a single benchmark method Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/benchmarks.md Runs only the benchmark method matching the given filter pattern, e.g., *XenoAtom_Enabled_Structured*. ```sh dotnet run --project src/XenoAtom.Logging.Benchmark/XenoAtom.Logging.Benchmark.csproj -c Release -- --filter *XenoAtom_Enabled_Structured* ``` -------------------------------- ### Run benchmarks by category Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/benchmarks.md Runs only benchmarks matching the specified category, e.g., EnabledStructured. ```sh dotnet run --project src/XenoAtom.Logging.Benchmark/XenoAtom.Logging.Benchmark.csproj -c Release -- --anyCategories EnabledStructured ``` -------------------------------- ### Configure styles by segment kind and log level Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/terminal.md Clears existing styles and sets styles for timestamp, logger name, and log levels. Use during startup; avoid concurrent mutation without synchronization. ```csharp writer.Styles.Clear(); writer.Styles.SetStyle(LogMessageFormatSegmentKind.Timestamp, "dim"); writer.Styles.SetStyle(LogMessageFormatSegmentKind.LoggerName, "blue"); writer.Styles.SetLevelStyle(LogLevel.Info, "green"); writer.Styles.SetLevelStyle(LogLevel.Error, "bold white on red"); ``` -------------------------------- ### Configure failure handling with Retry mode Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/file-writer.md Sets FailureMode to Retry with 5 retries and a 100ms delay, and defines a FailureHandler that logs failure details. The handler receives context with FilePath, Attempt, WillRetry, and Exception.Message. ```csharp var options = new FileLogWriterOptions("logs/app.log") { FailureMode = FileLogWriterFailureMode.Retry, RetryCount = 5, RetryDelay = TimeSpan.FromMilliseconds(100), FailureHandler = context => { Console.WriteLine( $"File log failure on {context.FilePath}. " + $"Attempt={context.Attempt} Retry={context.WillRetry} " + $"Error={context.Exception.Message}"); } }; ``` -------------------------------- ### Attach Visual table to log messages Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/terminal.md Creates a Table visual and attaches it to log messages using logger.Info and logger.InfoMarkup. Requires XenoAtom.Terminal.UI and XenoAtom.Terminal.UI.Controls namespaces. ```csharp using XenoAtom.Terminal.UI; using XenoAtom.Terminal.UI.Controls; var table = new Table() .Headers("Step", "Status") .AddRow("Build", "OK") .AddRow("Deploy", "Done"); logger.Info(table, "Deployment summary"); logger.InfoMarkup(table, "[bold]Deployment report[/]"); ``` -------------------------------- ### Configure FileLogWriter with StandardLogFormatter Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/log-formatter.md Creates a FileLogWriter with a formatter that sets timestamp format to "HH:mm:ss" and level format to Tri. Use this when writing to a file sink. ```csharp var writer = new FileLogWriter( new FileLogWriterOptions("logs/app.log") { Formatter = StandardLogFormatter.Instance with { TimestampFormat = "HH:mm:ss", LevelFormat = LogLevelFormat.Tri } }); ``` -------------------------------- ### XenoAtom.Logging per-message properties Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/microsoft-extensions-logging.md Logs a message with explicit properties using LogProperties, demonstrating allocation-aware structured logging. ```csharp logger.Info( properties: new LogProperties { ("UserId", 42), ("Feature", "checkout") }, msg: "Validation failed"); ``` -------------------------------- ### Add logger config with includeParents false Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/filtering.md Adds a logger config for 'App.Audit' with Info level and only the JSON writer, with includeParents set to false, so that App.Audit.* writes only to jsonWriter. ```csharp config.Loggers.Add("App.Audit", LogLevel.Info, [jsonWriter], includeParents: false); ``` -------------------------------- ### Custom archive file names with FileArchiveFileNameFormatters.DateTime Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/file-writer.md Configures a FileLogWriter with daily rolling and a DateTime archive file name formatter, producing names like output.2026-02-19-19_16_03.txt. ```csharp var writer = new FileLogWriter( new FileLogWriterOptions("logs/output.txt") { RollingInterval = FileRollingInterval.Daily, ArchiveFileNameFormatter = FileArchiveFileNameFormatters.DateTime }); ``` -------------------------------- ### Attach visual table to log entries with TerminalLogWriter Source: https://github.com/xenoatom/xenoatom.logging/blob/main/readme.md Creates a Table control from XenoAtom.Terminal.UI and attaches it to log entries. The table is rendered under the log line by TerminalLogWriter. Requires the XenoAtom.Terminal.UI package. ```csharp using XenoAtom.Terminal.UI; using XenoAtom.Terminal.UI.Controls; var table = new Table() .Headers("Step", "Status", "Duration") .AddRow("Initialize", "OK", "00:00.045") .AddRow("ProcessRequest", "FAILED", "00:00.003"); logger.Info(table, "Run summary"); logger.InfoMarkup(table, "[bold]Run summary (styled)[/]"); ``` -------------------------------- ### XenoAtom.Logging LogMethod source generator Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/microsoft-extensions-logging.md Defines a partial method with LogMethod attribute for source-generated logging in XenoAtom.Logging. ```csharp using XenoAtom.Logging; public static partial class AppLog { [LogMethod(LogLevel.Info, "Processing item {itemId}", EventId = 1)] public static partial void ProcessingItem(Logger logger, int itemId); } ``` -------------------------------- ### Attach visual object to log call Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/terminal-visuals.md C# code showing how to attach a Table visual to log calls using Info and InfoMarkup methods. ```csharp var table = new Table() .Headers("Step", "Status", "Duration") .AddRow("Initialize", "OK", "00:00.045") .AddRow("ProcessRequest", "FAILED", "00:00.003"); logger.Info(table, "Run summary"); logger.InfoMarkup(table, "[bold]Run summary (styled)[/]"); ``` -------------------------------- ### XenoAtom.Logging scope with LogProperties Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/microsoft-extensions-logging.md Uses BeginScope with LogProperties to add structured data to a log scope. ```csharp using (logger.BeginScope(new LogProperties { ("RequestId", requestId) })) { logger.Info("Handling request"); } ``` -------------------------------- ### Apply runtime configuration changes Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/filtering.md Calls ApplyChanges() on the LogManagerConfig to apply runtime updates to the configuration collections. ```csharp config.ApplyChanges(); ``` -------------------------------- ### Create custom text formatter with [LogFormatter] Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/source-generator.md Declares a partial record inheriting LogFormatter with [LogFormatter] to generate a high-performance text formatter. The template uses placeholders like {Timestamp:HH:mm:ss} and conditional sections. See the Log Formatters page for usage and template reference. ```csharp using XenoAtom.Logging; [LogFormatter("{Timestamp:HH:mm:ss} {Level,-5} {LoggerName} {Text}{? | {Exception}?}")] public sealed partial record MyFormatter : LogFormatter; ``` -------------------------------- ### Declare markup-aware logging methods with [LogMethodMarkup] Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/source-generator.md Declares static partial methods with [LogMethodMarkup] to generate markup-aware logging methods. Requires the XenoAtom.Logging.Terminal package. Generated code routes through terminal markup APIs and sets LogMessage.IsMarkup = true. ```csharp using XenoAtom.Logging; public static partial class AppLogs { [LogMethodMarkup(LogLevel.Info, "[green]User {userId} connected[/]")] public static partial void UserConnectedMarkup(Logger logger, int userId); } ``` -------------------------------- ### Declare logging methods with [LogMethod] Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/source-generator.md Declares static partial methods with [LogMethod] to generate strongly-typed logging methods. The generator emits level checks, optional LogEventId, and calls to LoggerExtensions methods. Placeholder names must match method parameter names. ```csharp using XenoAtom.Logging; public static partial class AppLogs { [LogMethod(LogLevel.Info, "User {userId} connected from {ip}")] public static partial void UserConnected(Logger logger, int userId, string ip); [LogMethod(LogLevel.Error, "Request {requestId} failed", EventId = 42, EventName = "RequestFailed")] public static partial void RequestFailed(Logger logger, Exception exception, LogProperties properties, int requestId); } ``` -------------------------------- ### CSS for banner links and icons Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/banner.md Styles for hover effects on banner links and spacing for Bootstrap icons. ```css .banner-links a:hover { color: rgba(220, 216, 228, 1); border-bottom-color: rgba(220, 216, 228, 0.75); } .banner-links i.bi { margin-right: 0.35rem; } ``` -------------------------------- ### Create TerminalLogControlWriter with LogControl Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/terminal.md Shows how to instantiate a TerminalLogControlWriter with a LogControl, enabling rich formatting and markup messages. This writer marshals background thread writes to the UI thread and does not render attachments by default. ```csharp using XenoAtom.Logging.Writers; using XenoAtom.Terminal.UI.Controls; var logControl = new LogControl(); var writer = new TerminalLogControlWriter(logControl) { EnableRichFormatting = true, EnableMarkupMessages = true }; ``` -------------------------------- ### Reset styles to defaults Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/terminal.md Restores default styles on the writer's Styles configuration. ```csharp writer.Styles.ResetToDefaults(); ``` -------------------------------- ### MEL scope with BeginScope Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/microsoft-extensions-logging.md Uses BeginScope with a message template to add structured data to a log scope. ```csharp using (_logger.BeginScope("Request {RequestId}", requestId)) { _logger.LogInformation("Handling request"); } ``` -------------------------------- ### JSON-lines logging with JsonFileLogWriter Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/file-writer.md Creates a JsonFileLogWriter with daily rolling and a retained file count limit of 7, emitting one JSON object per line. ```csharp var writer = new JsonFileLogWriter( new FileLogWriterOptions("logs/app.jsonl") { RollingInterval = FileRollingInterval.Daily, RetainedFileCountLimit = 7 }); ``` -------------------------------- ### Define custom formatter with [LogFormatter] attribute Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/log-formatter.md Declares a partial record inheriting LogFormatter and decorated with [LogFormatter]. The generator emits a TryFormat implementation and a singleton Instance property. ```csharp using XenoAtom.Logging; namespace MyApp.Logging; [LogFormatter("{Timestamp:HH:mm:ss} {Level,-5} {LoggerName} {Text}{? | {Exception}?}")] public sealed partial record MyLogFormatter : LogFormatter; ``` -------------------------------- ### Log structured properties Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/getting-started.md Logs a message with structured properties using LogProperties, including requestId and tenant. ```csharp var properties = new LogProperties { ("requestId", 1423), ("tenant", "alpha") }; logger.Info(properties: properties, msg: "Processing request"); ``` -------------------------------- ### Log with scoped context Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/getting-started.md Uses BeginScope to add contextual data (traceId) to all log messages within the scope. ```csharp using (logger.BeginScope(new LogProperties { ("traceId", "abc-123") })) { logger.Info("Inside request scope"); } ``` -------------------------------- ### Configure TerminalLogWriter with StandardLogFormatter Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/log-formatter.md Sets a StandardLogFormatter on a TerminalLogWriter for terminal output. ```csharp var terminalWriter = new TerminalLogWriter() { Formatter = StandardLogFormatter.Instance }; ``` -------------------------------- ### Enable rich formatting and markup messages on TerminalLogWriter Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/terminal.md Creates a TerminalLogWriter with EnableRichFormatting and EnableMarkupMessages set to true, enabling rich formatting by default. ```csharp var writer = new TerminalLogWriter() { EnableRichFormatting = true, EnableMarkupMessages = true, }; ``` -------------------------------- ### Log markup messages with InfoMarkup and ErrorMarkup Source: https://github.com/xenoatom/xenoatom.logging/blob/main/readme.md Logs markup-formatted messages to the terminal sink. InfoMarkup writes an informational message, ErrorMarkup writes an error message with an interpolated request ID. ```csharp logger.InfoMarkup("[green]ready[/]"); logger.ErrorMarkup($"[bold red]failed[/] id={requestId}"); ``` -------------------------------- ### Custom archive file name callback Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/file-writer.md Provides a custom callback for ArchiveFileNameFormatter that formats the timestamp and includes base file name and extension. ```csharp ArchiveFileNameFormatter = context => $"{context.BaseFileName}.{context.Timestamp:yyyy-MM-dd-HH_mm_ss}{context.Extension}"; ``` -------------------------------- ### Log markup message with InfoMarkup Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/log-formatter.md Logs a message containing markup tags. The [green] and [/] tags are rendered by terminal writers or stripped by text-based writers. ```csharp logger.InfoMarkup("[green]ready[/]"); ``` -------------------------------- ### Style customization with TerminalLogWriter Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/terminal-visuals.md C# code configuring TerminalLogWriter with rich formatting, markup messages, and custom styles for log segments and levels. ```csharp var writer = new TerminalLogWriter() { EnableRichFormatting = true, EnableMarkupMessages = true, }; writer.Styles.Clear(); writer.Styles.SetStyle(LogMessageFormatSegmentKind.Timestamp, "dim"); writer.Styles.SetStyle(LogMessageFormatSegmentKind.LoggerName, "blue"); writer.Styles.SetLevelStyle(LogLevel.Info, "green"); writer.Styles.SetLevelStyle(LogLevel.Warn, "bold yellow"); writer.Styles.SetLevelStyle(LogLevel.Error, "bold white on red"); ``` -------------------------------- ### JSON-lines logging with JsonLogFormatterOptions Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/file-writer.md Passes JsonLogFormatterOptions to JsonFileLogWriter to use the Elastic Common Schema profile, include exceptions, and disable scopes. ```csharp using XenoAtom.Logging.Formatters; var writer = new JsonFileLogWriter( new FileLogWriterOptions("logs/app.jsonl") { RollingInterval = FileRollingInterval.Daily }, new JsonLogFormatterOptions { SchemaProfile = JsonLogSchemaProfile.ElasticCommonSchema, IncludeException = true, IncludeScopes = false }); ``` -------------------------------- ### Replace default formatter with JsonLogFormatter Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/file-writer.md Configures FileLogWriterOptions with a JsonLogFormatter that includes properties and scopes. Use this to change the default StandardLogFormatter to JSON output. ```csharp var options = new FileLogWriterOptions("logs/app.log") { Formatter = new JsonLogFormatter(includeProperties: true, includeScopes: true) }; var writer = new FileLogWriter(options); ``` -------------------------------- ### Field placeholder syntax Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/log-formatter.md Shows the general shape of a field placeholder: {FieldName[,alignment][:format]}. Field names are case-insensitive, whitespace is trimmed, and values are not truncated when longer than alignment width. ```text {FieldName[,alignment][:format]} ``` -------------------------------- ### MEL LoggerMessageAttribute source generator Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/microsoft-extensions-logging.md Defines a partial method with LoggerMessageAttribute for source-generated logging in MEL. ```csharp [LoggerMessage(EventId = 1, Level = LogLevel.Information, Message = "Processing item {ItemId}")] public static partial void ProcessingItem(ILogger logger, int itemId); ``` -------------------------------- ### Override TimestampFormat and LevelFormat with with expression Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/log-formatter.md Creates a StandardLogFormatter instance with a custom timestamp format and long level format. Defaults are Tri for LevelFormat and "yyyy-MM-dd HH:mm:ss.fffffff" for TimestampFormat unless overridden. ```csharp using XenoAtom.Logging; using XenoAtom.Logging.Formatters; var formatter = StandardLogFormatter.Instance with { TimestampFormat = "HH:mm:ss", LevelFormat = LogLevelFormat.Long }; ``` -------------------------------- ### Configure terminal writer styles for segments Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/log-formatter.md Clears existing styles and sets styles for timestamp and error level. TerminalLogWriter uses these segment kinds to apply styling. ```csharp terminalWriter.Styles.Clear(); terminalWriter.Styles.SetStyle(LogMessageFormatSegmentKind.Timestamp, "dim"); terminalWriter.Styles.SetLevelStyle(LogLevel.Error, "bold white on red"); ``` -------------------------------- ### Override styles with SegmentStyleResolver Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/terminal.md Sets a SegmentStyleResolver that returns a style for EventId segments, otherwise null to fall back to Styles. ```csharp writer.SegmentStyleResolver = (kind, level) => kind == LogMessageFormatSegmentKind.EventId ? "bold magenta" : null; ``` -------------------------------- ### Interpolated markup messages escape formatted values Source: https://github.com/xenoatom/xenoatom.logging/blob/main/site/docs/terminal.md Shows that interpolated values in markup messages are escaped, so user input is rendered literally. ```csharp var userInput = "[red]not a tag[/]"; logger.InfoMarkup($"User input: {userInput}"); ```