Pudu programming language
Menu
Package

@chrismichaelps / pudu-lang-log

Structured event logging for Pudu: message templates, enrichment, filtering, formatting, and sinks

0.1.0Apache-2.01

InstallClose

Bridge.pudu

Pudu63 lines2.2 KB

GitHub ↗
1/** @Log.Bridge.Adapter — standard library log lines written as events */2module PuduLangLog.Bridge34import Std.Log as Standard5import Std.Option as Option6import Std.Out as Out7import PuduLangLog.Constants.Names as Names8import PuduLangLog.Domain.Parser as Parser9import PuduLangLog as Log10import PuduLangLog.Logger as Logger11import PuduLangLog.Pipeline as Pipeline1213/// A `Std.Log` logger whose lines become events of this logger: `Debug` through `Fatal` keep their14/// meaning, the logger's name becomes `SourceContext`, each field a text property, and the message15/// the event's text with its braces escaped. The standard logger prints nothing itself; which lines16/// are kept is this logger's decision.17export fn standard(logger: &Logger.Logger) -> Standard.Logger {18  let shared = *logger19  Standard.Logger {20    least: Standard.Debug,21    name: "",22    fields: [],23    format: fn(line: Standard.Line) -> Str {24      forward(&shared, &line)25      ""26    },27    printer: Out.bare()28  }29}3031/// The level of a standard line; `Silent` lines are never formatted.32export fn levelOf(level: Standard.Level) -> Log.Level {33  match level {34    case Standard.Debug => Log.Debug35    case Standard.Info => Log.Information36    case Standard.Warn => Log.Warning37    case Standard.Error => Log.Error38    case _ => Log.Fatal39  }40}4142/// Writes a standard line as an event.43fn forward(logger: &Logger.Logger, line: &Standard.Line) -> () {44  let named = if line.name.isEmpty() { *logger } else { logger.forSource(line.name) }45  let level = levelOf(line.level)46  if !named.isEnabled(level) { return () }47  let pipeline = Logger.pipelineOf(&named)48  var properties: Array[Log.Property] = []49  for field in line.fields {50    if Parser.isValidName(field.key) && field.key != Names.SOURCE_CONTEXT { properties = properties.push(Log.Property{name: field.key, value: Log.Scalar(Log.Text(field.value))}) }51  }52  let text = line.message.replace("\{", "\{\{").replace("\}", "\}\}")53  let _written = named.emit(Log.Event {54      timestamp: (pipeline.clock)(),55      level: level,56      template: Pipeline.templateOf(&pipeline, text),57      properties: properties,58      failure: None,59      traceId: Option.map(named.trace, |pair: (Str, Str)| pair[0]),60      spanId: Option.map(named.trace, |pair: (Str, Str)| pair[1])61    })62}63