Skip to main content

api_monitoring/
api_monitoring.rs

1//! API response monitoring: detect correlations and conservation laws in endpoint metrics.
2
3use 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    // /api/users — fast, small responses
36    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    // /api/reports — slow, large responses (correlated with bytes)
41    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    // /api/health — tiny, always fast (conservation candidate)
45    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    // Highlight correlations between latency and response size
63    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}