use std::borrow::Cow;
use std::future::Future;
use std::sync::Arc;
use ::fastrace::collector::{Reporter, SpanContext};
use ::fastrace::{Event, Span};
pub use ::fastrace::collector::{Config, ConsoleReporter};
#[derive(Clone)]
pub struct Root {
span: Arc<Span>,
}
impl Root {
pub(crate) fn noop() -> Self {
Self {
span: Arc::new(Span::noop()),
}
}
pub fn start(name: impl Into<Cow<'static, str>>) -> Self {
Self {
span: Arc::new(Span::root(name, SpanContext::random())),
}
}
pub fn child(&self, name: impl Into<Cow<'static, str>>) -> SpanScope {
SpanScope {
span: Span::enter_with_parent(name, &self.span),
}
}
pub(crate) fn child_root(&self, name: impl Into<Cow<'static, str>>) -> Self {
Self {
span: Arc::new(Span::enter_with_parent(name, &self.span)),
}
}
pub fn event(&self, name: impl Into<Cow<'static, str>>) {
self.span.add_event(Event::new(name));
}
pub fn event_properties(
&self,
name: impl Into<Cow<'static, str>>,
properties: Vec<(String, String)>,
) {
self.span
.add_event(Event::new(name).with_properties(|| properties));
}
pub fn property<K, V>(&self, key: K, value: V)
where
K: Into<Cow<'static, str>>,
V: Into<Cow<'static, str>>,
{
self.span.add_property(|| (key, value));
}
pub fn in_span<F>(
&self,
name: impl Into<Cow<'static, str>>,
future: F,
) -> impl Future<Output = F::Output> + 'static
where
F: Future + 'static,
{
use ::fastrace::future::FutureExt as _;
let span = Span::enter_with_parent(name, &self.span);
future.in_span(span)
}
}
pub struct SpanScope {
span: Span,
}
impl SpanScope {
pub fn child(&self, name: impl Into<Cow<'static, str>>) -> SpanScope {
SpanScope {
span: Span::enter_with_parent(name, &self.span),
}
}
pub fn event(&self, name: impl Into<Cow<'static, str>>) {
self.span.add_event(Event::new(name));
}
pub fn property<K, V>(&self, key: K, value: V)
where
K: Into<Cow<'static, str>>,
V: Into<Cow<'static, str>>,
{
self.span.add_property(|| (key, value));
}
pub fn in_span<F>(
self,
name: impl Into<Cow<'static, str>>,
future: F,
) -> impl Future<Output = F::Output> + 'static
where
F: Future + 'static,
{
use ::fastrace::future::FutureExt as _;
let span = Span::enter_with_parent(name, &self.span);
future.in_span(span)
}
pub fn in_span_ref<'a, F>(
&'a self,
name: impl Into<Cow<'static, str>>,
future: F,
) -> impl Future<Output = F::Output> + 'a
where
F: Future + 'a,
{
use ::fastrace::future::FutureExt as _;
let span = Span::enter_with_parent(name, &self.span);
future.in_span(span)
}
}
pub fn flush() {
::fastrace::flush();
}
pub fn set_reporter<R>(reporter: R, config: Config)
where
R: Reporter,
{
::fastrace::set_reporter(reporter, config);
}
#[cfg(test)]
mod tests {
use super::Root;
#[test]
fn builds_explicit_parent_child_spans() {
let root = Root::start("heart.test.run");
root.property("chat_id", "1");
root.event("run.started");
let node = root.child("heart.test.node");
node.property("node_id", "answer");
node.event("node.completed");
let model = node.child("heart.test.model");
model.property("provider", "test");
model.event("model.completed");
}
}