Skip to content

Formatting Output

Chris Michael edited this page Sep 29, 2026 · 1 revision

Pudu

Formatting Output

A formatter turns an event into text. Sinks take one as an option.

Formatter Module Output
Output templates Formatting.Text.template {Timestamp}, {UtcTimestamp}, {Level}, {Message}, {Exception}, {Properties}, {NewLine}, {TraceId}, {SpanId}, and any property such as {SourceContext}
JSON Formatting.Json.formatter one object with properties and renderings; renderMessage and closingDelimiter options
Compact JSON Formatting.Compact.compact, rendered newline-delimited objects with @t, @mt or @m, @r, @l, @x, @tr, @sp
Expression templates Expressions.template holes of expressions and #if, #else if, #else, #each, #delimit, #end

Level formats: u3 gives WRN, w3 gives wrn, t4 gives Warn. Message:l writes text without quotes and Message:j writes structures as JSON. Formatting.Reader reads compact JSON back into events with readLine, readAll, and readFile.

module Ex06Formatting

import Std.Io as Io
import Std.Option as Option
import PuduLangLog.Event as Event
import PuduLangLog.Expressions as Expressions
import PuduLangLog.Failure as Failure
import PuduLangLog.Formatting.Compact as Compact
import PuduLangLog.Formatting.Json as Json
import PuduLangLog.Formatting.Reader as Reader
import PuduLangLog.Formatting.Text as Text
import PuduLangLog as Log
import PuduLangLog.Value as Value

export fn main() -> Int {
  let base = Event.create(Log.Timestamp{millis: 1790604309123, offset: 120}, Log.Warning, "Disk \{Disk\} is \{Percent:0.0\}% full", [
      Value.property("Disk", Value.text("C")),
      Value.property("Percent", Value.decimal(93.25d)),
      Value.property("SourceContext", Value.text("Ops.Disks"))
    ])
  let event = Event.withFailure(&base, Failure.of("IoError", "no space left"))
  let text = Text.template("\{Timestamp:yyyy-MM-dd HH:mm:ss zzz\} [\{Level:u3\}] \{SourceContext\}: \{Message:lj\} \{Properties:j\}\{NewLine\}\{Exception\}")
  let _a = Io.writeLine(text(&event))
  let _b = Io.writeLine(Json.formatter(Json.Options{renderMessage: true, closingDelimiter: ""})(&event))
  let compact = Compact.compact()(&event)
  let _c = Io.writeLine(compact.trim())
  let _d = Io.writeLine(Compact.rendered()(&event).trim())
  let layout = match Expressions.template("\{@l:u3\} \{#if SourceContext is not null\}(\{SourceContext\}) \{#end\}\{@m\}\{#if @x is not null\} !! \{@x\}\{#end\}") {
    case Ok(formatter) => formatter
    case Err(problem) => panic(problem)
  }
  let _e = Io.writeLine(layout(&event))
  match Reader.readLine(compact) {
    case Ok(read) => { let _f = Io.writeLine("read back: " + show(read.level) + " " + Event.message(&read) + " / " + show(Option.map(read.failure, |problem: Log.Failure| problem.kind))) }
    case Err(problem) => { let _g = Io.writeErrorLine(problem) }
  }
  0
}

Check it and run it:

pudu check src/Ex06Formatting.pudu
pudu run src/Ex06Formatting.pudu

Output:

2026-09-28 16:05:09 +02:00 [WRN] Ops.Disks: Disk C is 93.3% full {}
IoError: no space left

{"Timestamp":"2026-09-28T16:05:09.1230000+02:00","Level":"Warning","MessageTemplate":"Disk {Disk} is {Percent:0.0}% full","RenderedMessage":"Disk \"C\" is 93.3% full","Exception":"IoError: no space left","Properties":{"Disk":"C","Percent":93.25,"SourceContext":"Ops.Disks"},"Renderings":{"Percent":[{"Format":"0.0","Rendering":"93.3"}]}}
{"@t":"2026-09-28T14:05:09.1230000Z","@mt":"Disk {Disk} is {Percent:0.0}% full","@r":["93.3"],"@l":"Warning","@x":"IoError: no space left","Disk":"C","Percent":93.25,"SourceContext":"Ops.Disks"}
{"@t":"2026-09-28T14:05:09.1230000Z","@m":"Disk \"C\" is 93.3% full","@i":"c9fb6c7e","@l":"Warning","@x":"IoError: no space left","Disk":"C","Percent":93.25,"SourceContext":"Ops.Disks"}
WRN (Ops.Disks) Disk C is 93.3% full !! IoError: no space left
read back: Warning Disk "C" is 93.3% full / Some("IoError")

{Properties} lists only the properties neither the message nor the output template names.

Related

Clone this wiki locally