// Copyright 2026 Leo Cheng
// SPDX-License-Identifier: Apache-2.0
///|
/// A tracer, a root span, a child span, some attributes and an event, and the two
/// spans as a sink receives them.
///
/// moon run src/examples/00-hello
#coverage.skip
fn main {
let recorder = @trace.Recorder::new()
let tracer = @trace.Tracer::new(
rand=random_bytes,
sink=recorder,
sampler=@trace.parent_based(root=@trace.always),
)
// Times are handed in: this library never reads a clock, so a batch job
// replaying yesterday's events and a server under load use the same code.
let started = 1_700_000_000_000_000_000L
let root = tracer.start("GET /orders/{id}", kind=@trace.Server, at=started, attributes=[
("http.request.method", @trace.Str("GET")),
]) catch {
_ => abort("the platform has no entropy source")
}
let child = tracer.start(
"SELECT orders",
parent=root.context(),
kind=@trace.Client,
at=started + 1_000_000L,
) catch {
_ => abort("the platform has no entropy source")
}
child.set_attribute("db.rows", @trace.Int(3L))
child.set_status(@trace.Ok)
child.finish(at=started + 2_000_000L)
root.add_event("cache.miss", at=started + 3_000_000L)
root.set_attribute("http.response.status_code", @trace.Int(200L))
root.finish(at=started + 4_000_000L)
for span in recorder.spans() {
println(
"\{span.name} \{span.context.to_traceparent()} \{span.duration()} ns",
)
for pair in span.attributes {
println(" \{pair.0} = \{pair.1}")
}
for event in span.events {
println(" event \{event.name} at \{event.at}")
}
}
}
///|
/// Eight or sixteen octets from the platform's entropy source. A caller this close
/// to the edge is the one that knows what to do when there is none; here that is to
/// stop rather than to trace with predictable ids.
fn random_bytes(width : Int32) -> Bytes {
@moonseed.bytes(width, @system.source) catch {
_ => abort("the platform has no entropy source")
}
}