Formatters
Comprehensive guide to MagicLogger output formatters. These control how each log entry is serialized before being written by a transport.
Available Formattersβ
- PlainTextFormatter (human-friendly text, configurable fields, templates, presets)
- JSONFormatter (structured JSON / NDJSON, field filtering, flattening presets)
- XMLFormatter (hierarchical XML document or single log element)
- CSVFormatter (tabular CSV with stable column set; good for spreadsheet / BI ingestion)
- CustomFormatter base (abstract class to implement new structured formats)
- FunctionFormatter (pass a function instead of subclassing for quick custom output)
Quick custom formatting: Use
FunctionFormatter
if you just need to map a log entry to a string/Buffer inline without creating a subclass.
PlainTextFormatterβ
Best for console / file readability.
Key options:
- timestampFormat: 'ISO' | 'unix' | 'locale' | 'custom'
- includeTimestamp / includeLevel / includeLoggerId / includeTags
- includeContext / includeMetadata / includeStack
- maxLineLength + truncationIndicator
- template string with placeholders like
{timestamp}
,{level}
,{message}
,{context.user}
.
Example:
import { PlainTextFormatter } from 'magiclogger/transports/console';
const f = new PlainTextFormatter({ template: '[{timestamp}] [{level}] {message}', includeStack: false });
transport.setFormatter(f);
Presets (PlainTextFormatters
): simple(), detailed(), syslog(), apache(), minimal().
JSONFormatterβ
Structured output for ingestion by log processors.
Features:
- includeFields / excludeFields (exclude wins)
- flatten + maxFlattenDepth (convert shallow nested objects to dotted keys)
- includeSchema (emit
$schema
object once or per batch depending on transport usage) - replacer for custom serialization (e.g. redacting secrets)
- format() returns a single JSON line; formatBatch() joins with
\n
;formatStream()
(if present in transport integration) may append\n
for NDJSON.
Example NDJSON stream:
const f = new JSONFormatter({ includeSchema: false });
entries.forEach(e => stream.write(f.format(e) + '\n'));
Presets (JSONFormatters
): compact(), pretty(), flat(), minimal(), extended().
XMLFormatterβ
Produces XML for interoperability with systems expecting hierarchical or verbose structured logs.
- format(entry) =>
<log ...>...</log>
- formatBatch(entries) => XML document with declaration and
<logs>
root. - Escapes XML entities and nests context / metadata / error.
Example:
import { XMLFormatter } from 'magiclogger/transports/formatters';
const xf = new XMLFormatter();
const xmlDoc = xf.formatBatch(entries);
CSVFormatterβ
Tabular output ideal for spreadsheets, Athena, BigQuery (after external load), or ad-hoc analysis.
Columns (fixed order): timestamp,level,message,loggerId,tags,error.name,error.message,context,metadata
.
- context & metadata columns are JSON-serialized objects
- tags joined by
;
- Error name/message isolated for easy filtering
- RFC 4180 escaping (quotes doubled, fields wrapped if containing comma, quote, CR/LF)
- formatBatch adds header row when includeHeaders = true (default) and appends trailing
\n
.
Example:
import { CSVFormatter } from 'magiclogger/transports/formatters';
const cf = new CSVFormatter();
fs.writeFileSync('logs.csv', cf.formatBatch(entries));
Implementing a Custom Formatterβ
Extend the abstract base:
import { CustomFormatter } from 'magiclogger/transports/formatters';
class LineFormatter extends CustomFormatter {
format(entry) { return `${entry.timestamp} ${entry.level} ${entry.message}`; }
}
Or wrap it in a transport:
transport.setFormatter(new LineFormatter());
Choosing a Formatβ
Use Case | Recommended |
---|---|
Human debugging | PlainText (simple/detailed) |
Structured ingestion (ELK, Datadog) | JSON (compact/extended) |
XML pipeline interoperability | XMLFormatter |
Spreadsheet / CSV loader | CSVFormatter |
Highly specialized legacy schema | CustomFormatter subclass |
Converting Between Formatsβ
Because entries retain full structured data until formatting, you can:
- Capture structured logs with JSONFormatter into a file.
- Later transform JSON to CSV: parse each line and re-render with CSVFormatter.
Sketch:
import { CSVFormatter } from 'magiclogger/transports/formatters';
const cf = new CSVFormatter();
const rows = jsonLines.map(line => cf.format(JSON.parse(line))); // if shape aligns with LogEntry
For lossless conversion, prefer re-logging original LogEntry objects rather than parsing formatted text.
Console styling and angle-bracket tagsβ
When logging to the browser console, MagicLogger supports simple inline styling using angle-bracket tags that map to CSS via the console "%c" token. For example, the message "<red>Error</red> while loading <bold>config</bold>"
will be transformed to console arguments like ['%cError%c while loading %cconfig%c', 'color:red;', '', 'font-weight:bold;', '']
, producing colored/bold output in Chrome/Firefox devtools. This transformation happens at the logger/Printer layer and remains transparent to formatters.
Notes:
- Tags are validated against the active theme and supported styles; unsupported tags are ignored safely.
- In Node, ANSI styles are used instead; the same logical tags map to terminal color sequences via the Colorizer.
- Parsing is lightweight and skips work when styling is disabled or unsupported.
Printer delegation (Node and Browser)β
To keep behavior consistent across environments, higher-level console features are routed through a unified Printer abstraction:
- Tables:
logger.table(rows, columns?)
uses Printer to render either console.table (browser) or an aligned table (Node) with theme-aware styling. - Progress bars/spinners:
logger.progressBar(opts)
uses Printer to update output efficiently and degrade gracefully when not supported. - Links:
logger.link(text, url)
leverages platform-specific capabilities (clickable links in terminals that support it; styled links in browser consoles).
This separation keeps formatters focused on transforming LogEntry objects, while visual concerns and platform quirks live in the Printer and Colorizer.
Stream & Batch Behaviorβ
- PlainTextFormatter.formatBatch joins lines and appends EOL.
- JSONFormatter.formatBatch joins JSON strings with
\n
(no trailing by default) for NDJSON-like blocks. - XMLFormatter.formatBatch produces full XML document with declaration.
- CSVFormatter.formatBatch prepends header (optional) and always appends trailing newline.
Future Extensionsβ
Potential additions (not yet implemented):
- YAMLFormatter
- ParquetFormatter (offloaded via worker & dependency opt-in)
- HTMLFormatter (interactive log report)
Contributions welcomeβextend CustomFormatter
and open a PR.