use std::time::{Duration, UNIX_EPOCH};
use metrique::emf::Emf;
use metrique::timers::{EpochMicros, Stopwatch, Timer, Timestamp, TimestampOnClose};
use metrique::unit::Microsecond;
use metrique::unit_of_work::metrics;
use metrique::writer::{AttachGlobalEntrySinkExt, EntryIoStreamExt, FormatExt};
use metrique::writer::{BoxEntrySink, Entry, GlobalEntrySink};
use metrique::{LazySlot, OnParentDrop, ServiceMetrics, SlotGuard};
use metrique_timesource::{TimeSource, set_time_source};
#[metrics(rename_all = "PascalCase")]
#[derive(Default)]
struct RequestMetrics {
operation: &'static str,
#[metrics(timestamp)]
timestamp: Timestamp,
time: Timer,
#[metrics(unit = Microsecond)]
load_data_time: Stopwatch,
#[metrics(format = EpochMicros)]
start_ts: Timestamp,
#[metrics(format = EpochMicros)]
end_ts: TimestampOnClose,
#[metrics(flatten)]
subevent: LazySlot<Subevent>,
}
type DefaultTimestampFormat = EpochMicros;
#[metrics(prefix = "subevent_", subfield_owned)]
#[derive(Default)]
struct Subevent {
#[metrics(format = DefaultTimestampFormat)]
start_ts: Timestamp,
#[metrics(format = DefaultTimestampFormat)]
end_ts: TimestampOnClose,
}
impl RequestMetrics {
fn init(operation: &'static str, sink: BoxEntrySink) -> RequestMetricsGuard {
RequestMetrics {
operation,
..Default::default()
}
.append_on_drop(sink)
}
}
#[derive(Entry)]
#[entry(rename_all = "PascalCase")]
struct Globals {
region: String,
}
#[tokio::main]
async fn main() {
let _ts = set_time_source(TimeSource::tokio(UNIX_EPOCH));
tracing_subscriber::fmt::init();
let _handler = ServiceMetrics::attach_to_stream(
Emf::all_validations("MyApp".into(), vec![vec![]])
.output_to_makewriter(|| std::io::stdout().lock())
.merge_globals(Globals {
region: "us-east-1".into(),
}),
);
handle_request(ServiceMetrics::sink()).await
}
async fn handle_request(sink: BoxEntrySink) {
let mut metrics = RequestMetrics::init("GoFishing", sink);
tokio::time::sleep(Duration::from_millis(10)).await;
{
let _load_data = metrics.load_data_time.start();
load_data().await;
}
process_subevent(
metrics
.subevent
.open(Subevent::default(), OnParentDrop::Discard)
.unwrap(),
)
.await;
}
async fn process_subevent(_submetrics: SlotGuard<Subevent>) {
tokio::time::sleep(Duration::from_millis(123)).await;
}
async fn load_data() {
tokio::time::sleep(Duration::from_millis(45)).await;
}