XenoAtom.Logging.Terminal provides terminal output for XenoAtom.Logging using XenoAtom.Terminal and XenoAtom.Terminal.UI.
It supports:
Logger.*Markup(...) extension methodsXenoAtom.Terminal.UI.Visual) rendered under the log lineLogControl sink integration for fullscreen UI appsAnsiMarkupInterpolatedStringHandlerFor details on template-based text formatting and segment kinds, see Log Formatters.
For terminal primitives, capabilities, and runtime behavior, see the XenoAtom.Terminal docs: https://xenoatom.github.io/terminal/docs/terminal/
XenoAtom.Logging stays dependency-minimal and does not use System.Console.XenoAtom.Terminal.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();
TerminalLogWriterTerminalInstanceVisual attachments after the log lineTerminalLogControlWriterLogControl (XenoAtom.Terminal.UI.Controls)TerminalLogWriterlogControl.App.Post(...) when available)using XenoAtom.Logging.Writers;
using XenoAtom.Terminal.UI.Controls;
var logControl = new LogControl();
var writer = new TerminalLogControlWriter(logControl)
{
EnableRichFormatting = true,
EnableMarkupMessages = true
};
TerminalLogWriter enables rich formatting by default:
var writer = new TerminalLogWriter()
{
EnableRichFormatting = true,
EnableMarkupMessages = true,
};
TerminalLogWriter.Styles lets you configure styles by segment kind and by log level:
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");
TerminalLogStyleConfiguration is intended to be configured during startup; avoid mutating Styles concurrently with active logging unless you provide your own synchronization.
You can restore defaults at any time:
writer.Styles.ResetToDefaults();
For advanced scenarios, use SegmentStyleResolver as an override hook. If it returns null/empty, the writer falls back to Styles:
writer.SegmentStyleResolver = (kind, level) =>
kind == LogMessageFormatSegmentKind.EventId ? "bold magenta" : null;
Use *Markup level methods to opt-in to markup message rendering:
logger.InfoMarkup("[green]ready[/] [gray]service started[/]");
logger.ErrorMarkup($"[red]failed[/] request={requestId}");
When using interpolated markup messages, formatted values are escaped:
var userInput = "[red]not a tag[/]";
logger.InfoMarkup($"User input: {userInput}");
The rendered text includes the literal [red]not a tag[/] value instead of interpreting it as markup tags.
TerminalLogWriter renders Visual attachments (from XenoAtom.Terminal.UI) after the formatted message line:
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[/]");
Behavior by sink:
TerminalLogWriter: renders the text line, then renders the attached VisualFileLogWriter / StreamLogWriter: write only text payloadJsonLogFormatter: writes message/fields, attachment visuals are not serializedUse InMemoryTerminalBackend to assert output deterministically in tests.
See samples/HelloLogging/Program.cs for a complete terminal demo with rich styling, markup logs, scopes, event IDs, and exception output.
See samples/HelloLogControl/Program.cs for a fullscreen LogControl demo with:
Markup + TextBlock contentFor a quick rendered-output walkthrough, see Terminal Visual Examples.