async_graphql_dataloader/
metrics.rs

1// src/metrics.rs
2use serde::Serialize;
3use std::sync::Arc;
4use tokio::sync::RwLock;
5
6#[derive(Debug, Clone, Serialize)]
7pub struct DataLoaderMetrics {
8    pub total_requests: u64,
9    pub batch_requests: u64,
10    pub cache_hits: u64,
11    pub cache_misses: u64,
12    pub average_batch_size: f64,
13    pub error_count: u64,
14    pub success_rate: f64,
15}
16
17#[derive(Clone)]
18pub struct TelemetryCollector {
19    metrics: Arc<RwLock<InternalMetrics>>,
20}
21
22struct InternalMetrics {
23    total_requests: u64,
24    batch_requests: u64,
25    cache_hits: u64,
26    cache_misses: u64,
27    batch_sizes: Vec<usize>,
28    errors: u64,
29}
30
31impl TelemetryCollector {
32    pub fn new() -> Self {
33        Self {
34            metrics: Arc::new(RwLock::new(InternalMetrics {
35                total_requests: 0,
36                batch_requests: 0,
37                cache_hits: 0,
38                cache_misses: 0,
39                batch_sizes: Vec::new(),
40                errors: 0,
41            })),
42        }
43    }
44
45    pub async fn record_request(&self) {
46        let mut metrics = self.metrics.write().await;
47        metrics.total_requests += 1;
48    }
49
50    pub async fn record_batch(&self, batch_size: usize) {
51        let mut metrics = self.metrics.write().await;
52        metrics.batch_requests += 1;
53        metrics.batch_sizes.push(batch_size);
54
55        if metrics.batch_sizes.len() > 1000 {
56            metrics.batch_sizes.remove(0);
57        }
58    }
59
60    pub async fn get_metrics(&self) -> DataLoaderMetrics {
61        let metrics = self.metrics.read().await;
62
63        let total_requests = metrics.total_requests;
64        let success_count = total_requests - metrics.errors;
65        let success_rate = if total_requests > 0 {
66            (success_count as f64 / total_requests as f64) * 100.0
67        } else {
68            0.0
69        };
70
71        let average_batch_size = if !metrics.batch_sizes.is_empty() {
72            metrics.batch_sizes.iter().sum::<usize>() as f64 / metrics.batch_sizes.len() as f64
73        } else {
74            0.0
75        };
76
77        DataLoaderMetrics {
78            total_requests,
79            batch_requests: metrics.batch_requests,
80            cache_hits: metrics.cache_hits,
81            cache_misses: metrics.cache_misses,
82            average_batch_size,
83            error_count: metrics.errors,
84            success_rate,
85        }
86    }
87}