event 教程
本教程展示基准测试事件的去向:进入内存用于分析,进入 JSONL 作为记录,同时进入两者,或者进入你自己的接收器。每个示例都是一个完整的测试。
快速上手
moon add Luna-Flow/mare_mark@0.3.0
import {
"Luna-Flow/mare_mark/model",
"Luna-Flow/mare_mark/event",
}
fn sample_observation(implementation : String, block : Int, elapsed : Double) -> @model.Observation {
@model.Observation::new(
"sum", implementation, "1", 0, block, block, Confirmatory, elapsed, 100, Kept, ExcludedFromMeasurement, true,
)
}
test "keep events in memory" {
let memory = @event.InMemorySink::new()
let sink = memory.as_sink()
(sink.emit_observation)(sample_observation("loop", 0, 3.5))
(sink.emit_observation)(sample_observation("formula", 0, 0.2))
inspect(memory.observations.length(), content="2")
inspect(memory.observations[1].raw_elapsed_us, content="0.2")
}
在实际使用中,你把 memory.as_sink() 传给 @runner.RunContext::new,由运行器调用这些回调。
日常任务
写出审计记录
test "JSONL record" {
let jsonl = @event.JsonlSink::new()
let sink = jsonl.as_sink()
(sink.emit_observation)(sample_observation("loop", 0, 3.5))
let location = (sink.finish)(@model.RunSummary::new("sum-run", 1, 0, 0, true, None))
inspect(location, content="jsonl://memory/sum-run")
let lines = jsonl.to_jsonl().split("\n").to_array()
inspect(lines.length(), content="2")
inspect(lines[0].contains("\"elapsed_us\":3.5"), content="true")
}
把 jsonl.to_jsonl() 写入报告旁边的文件;报告随时可以从它重新生成。
运行时流式写出
对于长时间的运行,每一行一产生就写出:
test "streaming" {
let file : Array[String] = []
let sink = @event.streaming_jsonl(line => file.push(line + "\n"), "events.jsonl")
(sink.emit_observation)(sample_observation("loop", 0, 3.5))
(sink.emit_observation)(sample_observation("loop", 1, 3.6))
inspect(file.length(), content="2")
inspect(file[1].has_suffix("\n"), content="true")
}
把 file.push 替换为向真实文件的追加。
两者兼得
test "tee" {
let memory = @event.InMemorySink::new()
let jsonl = @event.JsonlSink::new()
let sink = @event.tee(memory.as_sink(), jsonl.as_sink())
(sink.emit_observation)(sample_observation("loop", 0, 3.5))
inspect(memory.observations.length(), content="1")
inspect(jsonl.lines.length(), content="1")
inspect((sink.finish)(@model.RunSummary::new("r", 1, 0, 0, true, None)), content="jsonl://memory/r")
}
编写你自己的接收器
一个只为每个实现保留当前最小值的接收器,用于实时仪表盘:
test "a custom sink" {
let best : Map[String, Double] = Map([])
let sink = @event.ObservationSink::new(
observation => {
if observation.valid {
let current = best.get(observation.implementation_id).unwrap_or(observation.raw_elapsed_us)
best[observation.implementation_id] = current.min(observation.raw_elapsed_us)
}
},
_ => (),
_ => (),
summary => "dashboard://" + summary.run_id,
)
(sink.emit_observation)(sample_observation("loop", 0, 3.5))
(sink.emit_observation)(sample_observation("loop", 1, 3.1))
inspect(best.get("loop").unwrap(), content="3.1")
}
更进一步
@ir_sink以更短的名称提供相同的构造函数(in_memory、jsonl、jsonl_stream、tee);参见 ir_sink API。- 记录格式列于 event API 中。
常见陷阱
- 忘记失败回调。 除非你传入
emit_failure=,否则ObservationSink::new会忽略验证失败。 - 以为
InMemorySink会保存摘要。 请使用run返回的值。 - 把
seed解析为数字。 它是一个十进制字符串。