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

Context.pudu

Pudu81 lines2.9 KB

GitHub ↗
1/** @Log.Context.Ambient — properties pushed for a stretch of work */2module PuduLangLog.Context34import Std.Sync as Sync5import PuduLangLog.Domain.Capture as Capture6import PuduLangLog.Enricher as Enricher7import PuduLangLog as Log89/** @Log.Context.Stack — enrichers pushed and not yet popped */10export type Context = { frames: Sync.Cell[Array[Enricher.Enricher]] }1112/** @Log.Context.Bookmark — the stack as it was before a push */13export type Bookmark = { frames: Array[Enricher.Enricher] }1415/// An empty context. Give each thread of work its own, or a clone of its parent's.16export fn create() -> Context {17  let none: Array[Enricher.Enricher] = []18  Context{frames: Sync.cell(none)}19}2021/// The enrichers currently pushed, oldest first.22fn framesOf(context: &Context) -> Array[Enricher.Enricher] {23  match Sync.get(&context.frames) {24    case Ok(frames) => frames25    case Err(_) => []26  }27}2829/// Pushes an enricher and answers the bookmark that pops it.30export fn push(context: &Context, frame: Enricher.Enricher) -> Bookmark {31  let before = framesOf(context)32  let _stored = Sync.set(&context.frames, before.push(frame))33  Bookmark{frames: before}34}3536/// Pushes a property and answers the bookmark that pops it.37export fn pushProperty(context: &Context, name: Str, held: Log.Value) -> Bookmark { push(context, Enricher.property(name, held)) }3839/// Pushes a destructured property and answers the bookmark that pops it.40export fn pushDestructured(context: &Context, name: Str, held: Log.Value) -> Bookmark { push(context, Enricher.destructured(name, held)) }4142/// Puts the stack back as it was when the bookmark was taken.43export fn restore(context: &Context, bookmark: Bookmark) -> () {44  let _stored = Sync.set(&context.frames, bookmark.frames)45}4647/// Runs an action with a property pushed, popping it afterwards.48export fn using[T](context: &Context, name: Str, held: Log.Value, action: fn() -> T) -> T {49  let bookmark = pushProperty(context, name, held)50  let result = action()51  restore(context, bookmark)52  result53}5455/// An independent context holding the same enrichers, for work started on another thread.56export fn clone(context: &Context) -> Context { Context{frames: Sync.cell(framesOf(context))} }5758/// Empties the stack until the bookmark is restored.59export fn suspend(context: &Context) -> Bookmark {60  let before = framesOf(context)61  let none: Array[Enricher.Enricher] = []62  let _stored = Sync.set(&context.frames, none)63  Bookmark{frames: before}64}6566/// Empties the stack.67export fn reset(context: &Context) -> () {68  let _suspended = suspend(context)69}7071/// The enricher that applies the context's properties, the most recent first, so an inner push72/// wins over an outer one of the same name.73export fn enricher(context: &Context) -> Enricher.Enricher {74  let shared = *context75  fn(event: Log.Event, policy: &Capture.Policy) -> Log.Event {76    var current = event77    for frame in framesOf(&shared).reverse() { current = frame(current, policy) }78    current79  }80}81