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

LevelSwitch.pudu

Pudu51 lines1.9 KB

GitHub ↗
1/** @Log.LevelSwitch.Control — a minimum level changed while running */2module PuduLangLog.LevelSwitch34import Std.Sync as Sync5import PuduLangLog.Domain.Levels as Levels6import PuduLangLog as Log78/** @Log.LevelSwitch.Shared — the level every holder of the switch sees */9export type LevelSwitch = { current: Sync.Cell[Log.Level], lock: Sync.Mutex, listeners: Sync.Cell[Array[fn(Log.Level, Log.Level) -> ()]] }1011/// A switch starting at a level.12export fn create(initial: Log.Level) -> LevelSwitch {13  let none: Array[fn(Log.Level, Log.Level) -> ()] = []14  LevelSwitch{current: Sync.cell(initial), lock: Sync.mutex(), listeners: Sync.cell(none)}15}1617/// The switch's level.18export fn level(control: &LevelSwitch) -> Log.Level {19  match Sync.get(&control.current) {20    case Ok(found) => found21    case Err(_) => Log.Information22  }23}2425/// Whether an event at a level passes the switch.26export fn allows(control: &LevelSwitch, candidate: Log.Level) -> Bool { Levels.passes(candidate, level(control)) }2728/// Changes the level, calling each listener with the old and new levels when it differs.29export fn set(control: &LevelSwitch, next: Log.Level) -> () {30  let changed = Sync.withLock(&control.lock, fn() -> Option[Log.Level] {31      let previous = level(control)32      if previous == next { return None }33      let _stored = Sync.set(&control.current, next)34      Some(previous)35    })36  if let Ok(Some(previous)) = changed {37    if let Ok(listeners) = Sync.get(&control.listeners) {38      for listener in listeners { listener(previous, next) }39    }40  }41}4243/// Registers a listener called with the old and new levels after every change.44export fn onChange(control: &LevelSwitch, listener: fn(Log.Level, Log.Level) -> ()) -> () {45  let _registered = Sync.withLock(&control.lock, fn() -> () {46      if let Ok(listeners) = Sync.get(&control.listeners) {47        let _stored = Sync.set(&control.listeners, listeners.push(listener))48      }49    })50}51