-
-
Notifications
You must be signed in to change notification settings - Fork 0
Filtering And Expressions
Chris Michael edited this page Sep 29, 2026
·
1 revision
A filter decides whether an event continues; every filter must keep it. PuduLangLog.Filter offers byExcluding, byIncludingOnly, and predicates: fromSource, withProperty, withPropertyValue, withPropertyWhere, atLeast, withFailure, allOf, anyOf, and not.
Expressions.compile reads an expression once; evaluate runs it against an event and answers a value, or none when it is undefined. predicate is true only for the boolean true; computed adds a property; template builds a formatter.
| Kind | Syntax |
|---|---|
| Names | properties, Cart.Items[0].Price, Meta['region'], and built-ins @t, @m, @mt, @l, @x, @p, @i, @r, @tr, @sp
|
| Operators |
and, or, not, =, <>, <, <=, >, >=, like, not like, in, not in, is null, is not null, +, -, *, /, %, ^
|
| Case |
ci after a comparison or call ignores case |
| Wildcards |
Items[?] any element, Items[*] every element |
| Literals | numbers, 0xFF, 'text', true, false, null, [1, ..rest], {a: 1, ..other}
|
| Conditionals | if … then … else … |
| Functions |
Coalesce, Concat, Contains, ElementAt, EndsWith, IndexOf, IndexOfMatch, Inspect, IsDefined, IsMatch, LastIndexOf, Length, Nest, Now, Replace, Rest, Round, StartsWith, Substring, TagOf, ToString, TypeOf, Undefined, UtcDateTime
|
module Ex05Filtering
import Std.Io as Io
import PuduLangLog.Configuration as Configuration
import PuduLangLog.Event as Event
import PuduLangLog.Expressions as Expressions
import PuduLangLog.Filter as Filter
import PuduLangLog as Log
import PuduLangLog.Logger as Logger
import PuduLangLog.Sinks.Memory as Memory
import PuduLangLog.Value as Value
export fn main() -> Int {
let health = match Expressions.predicate("RequestPath like '/health%'") {
case Ok(test) => test
case Err(problem) => panic(problem)
}
let memory = Memory.create()
let logger = Configuration.create()
.filterExcluding(health)
.filterExcluding(Filter.allOf([Filter.fromSource("Shop.Cache"), Filter.not(Filter.atLeast(Log.Warning))]))
.writeTo(Memory.sink(&memory))
.createLogger()
logger.information("GET \{RequestPath\}", [Value.text("/health/ready")])
logger.information("GET \{RequestPath\}", [Value.text("/orders")])
logger.forSource("Shop.Cache").information("cache hit", [])
logger.forSource("Shop.Cache").warning("cache full", [])
let _kept = Io.writeLine("kept: " + Memory.messages(&memory).join(" | "))
let order = Event.create(Log.Timestamp{millis: 0, offset: 0}, Log.Information, "Order \{Id\}", [
Value.property("Id", Value.int(7)),
Value.property("Items", Value.list([Value.object([("Sku", Value.text("tea")), ("Price", Value.int(4))]), Value.object([("Sku", Value.text("pot")), ("Price", Value.int(30))])])),
Value.property("SourceContext", Value.text("Shop.Orders.Api"))
])
for text in ["Items[?].Price > 20", "Items[*].Price > 20", "Length(Items)", "IsDefined(Sum)", "Sum + 1", "if Id > 5 then 'big' else 'small'", "Substring(SourceContext, LastIndexOf(SourceContext, '.') + 1)", "ElementAt(Items, 1).Sku", "@l = 'information' ci", "Frob(Id)"] {
let answer = match Expressions.compile(text) {
case Ok(compiled) => match Expressions.evaluate(&compiled, &order) {
case Some(held) => Value.render(&held)
case None => "undefined"
}
case Err(problem) => "refused: " + problem
}
let _line = Io.writeLine(text + " => " + answer)
}
Logger.close(&logger)
0
}
Check it and run it:
pudu check src/Ex05Filtering.pudu
pudu run src/Ex05Filtering.puduOutput:
kept: GET "/orders" | cache full
Items[?].Price > 20 => true
Items[*].Price > 20 => false
Length(Items) => 2
IsDefined(Sum) => false
Sum + 1 => undefined
if Id > 5 then 'big' else 'small' => "big"
Substring(SourceContext, LastIndexOf(SourceContext, '.') + 1) => "Api"
ElementAt(Items, 1).Sku => "pot"
@l = 'information' ci => true
Frob(Id) => refused: unknown function `frob`
An undefined operand makes most expressions undefined rather than failing. A call to an unknown function is refused when compiling, so a typo fails at startup.