use std::convert::Infallible;
use std::future::{Future, ready};
use std::process::ExitCode;
use opentelemetry::KeyValue;
use opentelemetry::global;
use opentelemetry::metrics::Counter;
use ruststream::memory::prelude::*;
use ruststream::otel::Otel;
use ruststream::runtime::cli::run_main;
use serde::Deserialize;
#[derive(Debug, Deserialize, schemars::JsonSchema)]
struct Order {
id: u64,
}
#[derive(Clone)]
struct OrderMetrics {
accepted: Counter<u64>,
}
#[derive(Clone)]
struct AppState {
metrics: OrderMetrics,
}
struct Accept;
impl Handle<Order, (), (), (), AppState> for Accept {
fn handle(
&self,
order: &Order,
_outs: &(),
ctx: &mut Context<'_, (), AppState>,
) -> impl Future<Output = Result<(), HandlerOutcome>> {
ctx.state()
.metrics
.accepted
.add(1, &[KeyValue::new("region", "eu")]);
let _ = order.id;
ready(Ok(()))
}
}
fn app(otel: &Otel) -> impl App + use<> {
RustStream::new(AppInfo::new("orders-svc", "0.1.0"))
.layer(otel.consume_layer())
.publish_layer(otel.publish_layer())
.on_startup(async move |()| {
Ok::<_, Infallible>(AppState {
metrics: OrderMetrics {
accepted: global::meter("orders-svc")
.u64_counter("orders_accepted")
.build(),
},
})
})
.with_broker(MemoryBroker::new(), |b| {
b.include(subscriber("orders", Accept).build());
})
}
fn main() -> ExitCode {
let otel = Otel::builder()
.service_name("orders-svc")
.otlp_endpoint("http://localhost:4317")
.messaging_system("memory")
.attribute("deployment.environment", "dev")
.init()
.expect("otel init failed");
let code = run_main(|| app(&otel));
otel.shutdown().expect("otel shutdown failed");
code
}