acta_maker_sdk/
io_observer.rs1use std::sync::OnceLock;
3
4pub enum Event<'a> {
5 HttpRequest {
6 venue: &'a str,
7 endpoint: &'a str,
8 },
9 HttpStatus {
10 venue: &'a str,
11 endpoint: &'a str,
12 status: u16,
13 },
14 HttpBytes {
15 venue: &'a str,
16 endpoint: &'a str,
17 bytes: usize,
18 },
19 Ws {
20 venue: &'a str,
21 stream: &'a str,
22 bytes: usize,
23 },
24 Rpc {
25 method: &'a str,
26 },
27}
28static OBSERVER: OnceLock<fn(Event<'_>)> = OnceLock::new();
29pub fn install(observer: fn(Event<'_>)) {
30 let _ = OBSERVER.set(observer);
31}
32pub fn record(event: Event<'_>) {
33 if let Some(observer) = OBSERVER.get() {
34 observer(event);
35 }
36}
37
38#[cfg(feature = "http")]
39pub async fn send(
40 request: reqwest::RequestBuilder,
41 venue: &str,
42 endpoint: &str,
43) -> Result<reqwest::Response, reqwest::Error> {
44 record(Event::HttpRequest { venue, endpoint });
45 let response = request.send().await;
46 record(Event::HttpStatus {
47 venue,
48 endpoint,
49 status: response.as_ref().map_or(0, |r| r.status().as_u16()),
50 });
51 response
52}
53#[cfg(feature = "http")]
54pub async fn bytes(
55 mut response: reqwest::Response,
56 venue: &str,
57 endpoint: &str,
58) -> Result<Vec<u8>, reqwest::Error> {
59 let mut count = BodyCount {
60 venue,
61 endpoint,
62 bytes: 0,
63 };
64 let mut body = Vec::new();
65 while let Some(chunk) = response.chunk().await? {
66 count.bytes += chunk.len();
67 body.extend_from_slice(&chunk);
68 }
69 Ok(body)
70}
71
72#[cfg(feature = "http")]
73struct BodyCount<'a> {
74 venue: &'a str,
75 endpoint: &'a str,
76 bytes: usize,
77}
78#[cfg(feature = "http")]
79impl Drop for BodyCount<'_> {
80 fn drop(&mut self) {
81 record(Event::HttpBytes {
82 venue: self.venue,
83 endpoint: self.endpoint,
84 bytes: self.bytes,
85 });
86 }
87}