Skip to main content

mockforge_observability/
lib.rs

1//! MockForge Observability
2//!
3//! Provides comprehensive observability features including:
4//! - Structured logging with JSON support
5//! - Prometheus metrics export
6//! - OpenTelemetry distributed tracing
7//! - Request/response recording (flight recorder)
8//! - Scenario control and chaos engineering
9//! - System metrics collection (CPU, memory, threads)
10//!
11//! # Example
12//!
13//! ```rust
14//! use mockforge_observability::prometheus::MetricsRegistry;
15//!
16//! let registry = MetricsRegistry::new();
17//! registry.record_http_request("GET", 200, 0.045);
18//! ```
19
20pub mod logging;
21pub mod prometheus;
22pub mod protocol_metrics;
23pub mod system_metrics;
24pub mod tracing_integration;
25
26// Re-export commonly used items
27pub use logging::{init_logging, init_logging_with_otel, LoggingConfig};
28pub use prometheus::{get_global_registry, MetricsRegistry};
29pub use protocol_metrics::{ProtocolMetrics, ProtocolMetricsSnapshot};
30pub use system_metrics::{start_system_metrics_collector, SystemMetricsConfig};
31pub use tracing_integration::{init_with_otel, shutdown_otel, OtelTracingConfig};
32
33/// Protocol types for metrics tracking
34#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
35pub enum Protocol {
36    Http,
37    Grpc,
38    WebSocket,
39    GraphQL,
40}
41
42impl Protocol {
43    pub fn as_str(&self) -> &'static str {
44        match self {
45            Protocol::Http => "http",
46            Protocol::Grpc => "grpc",
47            Protocol::WebSocket => "websocket",
48            Protocol::GraphQL => "graphql",
49        }
50    }
51}
52
53impl std::fmt::Display for Protocol {
54    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
55        write!(f, "{}", self.as_str())
56    }
57}
58
59#[cfg(test)]
60mod tests {
61    use super::*;
62    use std::collections::HashSet;
63
64    #[test]
65    fn test_protocol_display() {
66        assert_eq!(Protocol::Http.to_string(), "http");
67        assert_eq!(Protocol::Grpc.to_string(), "grpc");
68        assert_eq!(Protocol::WebSocket.to_string(), "websocket");
69        assert_eq!(Protocol::GraphQL.to_string(), "graphql");
70    }
71
72    #[test]
73    fn test_protocol_as_str() {
74        assert_eq!(Protocol::Http.as_str(), "http");
75        assert_eq!(Protocol::Grpc.as_str(), "grpc");
76        assert_eq!(Protocol::WebSocket.as_str(), "websocket");
77        assert_eq!(Protocol::GraphQL.as_str(), "graphql");
78    }
79
80    #[test]
81    fn test_protocol_debug() {
82        assert_eq!(format!("{:?}", Protocol::Http), "Http");
83        assert_eq!(format!("{:?}", Protocol::Grpc), "Grpc");
84        assert_eq!(format!("{:?}", Protocol::WebSocket), "WebSocket");
85        assert_eq!(format!("{:?}", Protocol::GraphQL), "GraphQL");
86    }
87
88    #[test]
89    fn test_protocol_clone() {
90        let proto = Protocol::Http;
91        let cloned = Clone::clone(&proto);
92        assert_eq!(proto, cloned);
93    }
94
95    #[test]
96    fn test_protocol_copy() {
97        let proto = Protocol::Grpc;
98        let copied = proto;
99        assert_eq!(Protocol::Grpc, copied);
100        assert_eq!(proto, Protocol::Grpc); // proto still accessible
101    }
102
103    #[test]
104    fn test_protocol_eq() {
105        assert_eq!(Protocol::Http, Protocol::Http);
106        assert_eq!(Protocol::Grpc, Protocol::Grpc);
107        assert_ne!(Protocol::Http, Protocol::Grpc);
108        assert_ne!(Protocol::WebSocket, Protocol::GraphQL);
109    }
110
111    #[test]
112    fn test_protocol_hash() {
113        let mut set = HashSet::new();
114        set.insert(Protocol::Http);
115        set.insert(Protocol::Grpc);
116        set.insert(Protocol::WebSocket);
117        set.insert(Protocol::GraphQL);
118
119        assert_eq!(set.len(), 4);
120        assert!(set.contains(&Protocol::Http));
121        assert!(set.contains(&Protocol::Grpc));
122        assert!(set.contains(&Protocol::WebSocket));
123        assert!(set.contains(&Protocol::GraphQL));
124
125        // Duplicate insertion shouldn't increase size
126        set.insert(Protocol::Http);
127        assert_eq!(set.len(), 4);
128    }
129
130    #[test]
131    fn test_protocol_all_variants() {
132        let protocols = [
133            Protocol::Http,
134            Protocol::Grpc,
135            Protocol::WebSocket,
136            Protocol::GraphQL,
137        ];
138
139        for proto in protocols {
140            let str_repr = proto.as_str();
141            assert!(!str_repr.is_empty());
142            assert_eq!(proto.to_string(), str_repr);
143        }
144    }
145}