api_monitoring/
api_monitoring.rs1use crackle_runtime::{CrackleTask, Kiln, ThermalProfile, TaskOutput};
4
5struct ApiRequest {
6 endpoint: String,
7 latency_ms: f64,
8 status: u16,
9 response_bytes: f64,
10}
11
12impl CrackleTask for ApiRequest {
13 type Output = f64;
14
15 fn fire(&self) -> TaskOutput<Self::Output> {
16 TaskOutput::new(
17 self.latency_ms,
18 vec![
19 ("latency_ms".into(), self.latency_ms),
20 ("response_bytes".into(), self.response_bytes),
21 ("is_error".into(), if self.status >= 400 { 1.0 } else { 0.0 }),
22 ("is_slow".into(), if self.latency_ms > 200.0 { 1.0 } else { 0.0 }),
23 ],
24 )
25 }
26
27 fn label(&self) -> String {
28 self.endpoint.clone()
29 }
30}
31
32fn main() {
33 let mut kiln = Kiln::new(ThermalProfile::default());
34
35 kiln.fire_and_record(ApiRequest { endpoint: "GET /api/users".into(), latency_ms: 45.0, status: 200, response_bytes: 1200.0 }).unwrap();
37 kiln.fire_and_record(ApiRequest { endpoint: "GET /api/users".into(), latency_ms: 48.0, status: 200, response_bytes: 1150.0 }).unwrap();
38 kiln.fire_and_record(ApiRequest { endpoint: "GET /api/users".into(), latency_ms: 52.0, status: 200, response_bytes: 1300.0 }).unwrap();
39
40 kiln.fire_and_record(ApiRequest { endpoint: "GET /api/reports".into(), latency_ms: 350.0, status: 200, response_bytes: 55000.0 }).unwrap();
42 kiln.fire_and_record(ApiRequest { endpoint: "GET /api/reports".into(), latency_ms: 380.0, status: 200, response_bytes: 62000.0 }).unwrap();
43
44 kiln.fire_and_record(ApiRequest { endpoint: "GET /api/health".into(), latency_ms: 3.0, status: 200, response_bytes: 15.0 }).unwrap();
46 kiln.fire_and_record(ApiRequest { endpoint: "GET /api/health".into(), latency_ms: 4.0, status: 200, response_bytes: 15.0 }).unwrap();
47
48 let patterns = kiln.cool();
49 println!("API Monitoring — Pattern Report");
50 println!("================================\n");
51 println!("{} patterns detected:\n", patterns.len());
52
53 for p in &patterns {
54 println!("[{}] {}", p.kind(), p.description());
55 println!(" confidence: {:.2}", p.confidence());
56 if !p.involved_tasks().is_empty() {
57 println!(" endpoints: {:?}", p.involved_tasks());
58 }
59 println!();
60 }
61
62 let correlations: Vec<_> = patterns.iter()
64 .filter(|p| format!("{}", p.kind()) == "correlation")
65 .collect();
66
67 if !correlations.is_empty() {
68 println!("📊 Latency and response size are correlated — consider pagination or caching.");
69 }
70}