Logger: JSON
The JsonExporter in TriFrost outputs logs as pure JSON — making it ideal for structured logging pipelines, file sinks, or log aggregation systems that expect newline-delimited JSON (NDJSON).
It supports:
- JSON-formatted log output
- Optional custom sink function
- Field redaction (
omit)
It's especially useful when:
- You’re running in a container and want to
stdoutto a JSON collector - You want logs to be testable/assertable in memory
- You’re building your own log ingestion flow
It's the default exporter in production for the Workerd runtime.
📥 Import and Use
import {App, JsonExporter} from '@trifrost/core';
new App({
...
tracing: {
exporters: ({env}) => [
new JsonExporter({
omit: [...], // see below
sink: log => process.stdout.write(JSON.stringify(log) + '\n')
}),
],
}
...
})You provide this when configuring your App setup, there's sensible defaults at play so in most cases new JsonExporter() will be enough.
Note: If no sink is provided, logs are written to console[log.level].
⚙️ Available Options
omit: TriFrostLogScramblerValue[]
Keys to redact from data/ctx/global payloads. Learn more here
default:OMIT_PRESETS.defaultsink: (entry:JsonExporterEntry) => void
Custom log writer — lets you pipe logs to a file, socket, or in-memory store.
JsonExporterEntry
The JsonExporterEntry object looks like this:
{
"time": "2025-06-06T10:30:00.000Z",
"level": "info",
"message": "User logged in",
"trace_id": "3c51d...",
"span_id": "a1b2c3d4",
"ctx": {...},
"data": {...},
"global": {...}
}This shape is structured and predictable, making it ideal for ingestion by:
- Datadog
- Vector.dev
- FluentBit
- Loki
- CloudFlare observability (TriFrost is using this)
- ...
Examples
Sink
import {JsonExporter} from '@trifrost/core';
import {LogService} from './LogService'; /* eg: singleton instance which pushes to file */
new JsonExporter({
sink: log => LogService.push(JSON.stringify(log)),
});Override Defaults
new JsonExporter({
omit: [{global: 'ssn'}] // Only redact 'ssn', not full default list
});Note: ⚠️ Be very careful, you dont want to leak secrets, our advice is to always do something akin to
omit: [...OMIT_PRESETS.default, (your own expansion)]
👉 See Scrambling Hygiene for full explanation
Best Practices
- ✅ Use in CI, production, or custom log sinks
- ✅ Pipe output to file or stream sinks (via
sink) - ✅ Keep one exporter per format — don’t double-format
- 💡 You can use this exporter in tandem with
JsonExporterorOtelHttpExporter - 💡 Want to go fancy? Make use of TriFrost's isDevMode function to refine between dev and prod