1/** @Log.Expressions.Facade — filter expressions and expression templates */2modulePuduLangLog.Expressions34importPuduLangLog.ClockasClock5importPuduLangLog.Domain.CaptureasCapture6importPuduLangLog.Domain.PropertiesasProperties7importPuduLangLog.EnricherasEnricher8importPuduLangLog.Expressions.EvaluatorasEvaluator9importPuduLangLog.Expressions.FunctionsasFunctions10importPuduLangLog.Expressions.ParserasParser11importPuduLangLog.Expressions.SyntaxasSyntax12importPuduLangLog.Expressions.TemplateasTemplate13importPuduLangLog.Expressions.ValuesasValues14importPuduLangLogasLog1516/** @Log.Expressions.Compiled — a parsed expression and its text */17exporttypeCompiled = { text: Str, expression: Syntax.Expression }1819/// The expression the text denotes, or why it could not be read, including a call to an unknown20/// function.21exportfncompile(text: Str) -> Result[Compiled, Str] {22let expression = Parser.parse(text) ?23for name inSyntax.callsIn(&expression) {24if !Functions.isKnown(name) { returnErr("unknown function `" + name + "`") }25 }26Ok(Compiled{text: text, expression: expression})27}2829/// The value of a compiled expression for an event, or none when it is undefined.30exportfnevaluate(compiled: &Compiled, event: &Log.Event) -> Option[Log.Value] {31Evaluator.evaluate(&compiled.expression, &Evaluator.scopeOf(event, Clock.system()()))32}3334/// A predicate true for the events that make the expression the boolean `true`, for filters,35/// conditional sinks, and conditional enrichers.36exportfnpredicate(text: Str) -> Result[fn(&Log.Event) -> Bool, Str] {37let compiled = compile(text) ?38Ok(fn(event: &Log.Event) -> Bool { Values.isTrue(&evaluate(&compiled, event)) })39}4041/// An enricher adding a property whose value is the expression evaluated for each event, unless42/// the event already has the property or the expression is undefined for it.43exportfncomputed(name: Str, text: Str) -> Result[Enricher.Enricher, Str] {44let compiled = compile(text) ?45Ok(fn(event: Log.Event, policy: &Capture.Policy) -> Log.Event {46ifProperties.has(&event.properties, name) { return event }47match evaluate(&compiled, &event) {48caseSome(held) => Log.Event{..event, properties: event.properties.push(Log.Property{name: name, value: Capture.capture(policy, &held, Log.Destructure)})}49caseNone => event50 }51 })52}5354/// A formatter writing each event through an expression template of holes `{expression:format}`55/// and the directives `#if`, `#else if`, `#else`, `#each … in …`, `#delimit`, and `#end`.56exportfntemplate(text: Str) -> Result[Log.Formatter, Str] {57let nodes = Template.parse(text) ?58var referenced: Array[Str] = []59for expression inTemplate.expressionsIn(&nodes) {60for name inSyntax.callsIn(&expression) {61if !Functions.isKnown(name) { returnErr("unknown function `" + name + "`") }62 }63 referenced = referenced.concat(Syntax.namesIn(&expression))64 }65Ok(fn(event: &Log.Event) -> Str {66let within = Evaluator.Scope{..Evaluator.scopeOf(event, Clock.system()()), referenced: referenced}67Template.render(&nodes, &within)68 })69}70