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 system_metrics;
23pub mod tracing_integration;
24
25// Re-export commonly used items
26pub use logging::{init_logging, init_logging_with_otel, LoggingConfig};
27pub use prometheus::{get_global_registry, MetricsRegistry};
28pub use system_metrics::{start_system_metrics_collector, SystemMetricsConfig};
29pub use tracing_integration::{init_with_otel, shutdown_otel, OtelTracingConfig};
30
31/// Protocol types for metrics tracking
32#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
33pub enum Protocol {
34    Http,
35    Grpc,
36    WebSocket,
37    GraphQL,
38}
39
40impl Protocol {
41    pub fn as_str(&self) -> &'static str {
42        match self {
43            Protocol::Http => "http",
44            Protocol::Grpc => "grpc",
45            Protocol::WebSocket => "websocket",
46            Protocol::GraphQL => "graphql",
47        }
48    }
49}
50
51impl std::fmt::Display for Protocol {
52    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
53        write!(f, "{}", self.as_str())
54    }
55}
56
57#[cfg(test)]
58mod tests {
59    use super::*;
60    use std::collections::HashSet;
61
62    #[test]
63    fn test_protocol_display() {
64        assert_eq!(Protocol::Http.to_string(), "http");
65        assert_eq!(Protocol::Grpc.to_string(), "grpc");
66        assert_eq!(Protocol::WebSocket.to_string(), "websocket");
67        assert_eq!(Protocol::GraphQL.to_string(), "graphql");
68    }
69
70    #[test]
71    fn test_protocol_as_str() {
72        assert_eq!(Protocol::Http.as_str(), "http");
73        assert_eq!(Protocol::Grpc.as_str(), "grpc");
74        assert_eq!(Protocol::WebSocket.as_str(), "websocket");
75        assert_eq!(Protocol::GraphQL.as_str(), "graphql");
76    }
77
78    #[test]
79    fn test_protocol_debug() {
80        assert_eq!(format!("{:?}", Protocol::Http), "Http");
81        assert_eq!(format!("{:?}", Protocol::Grpc), "Grpc");
82        assert_eq!(format!("{:?}", Protocol::WebSocket), "WebSocket");
83        assert_eq!(format!("{:?}", Protocol::GraphQL), "GraphQL");
84    }
85
86    #[test]
87    fn test_protocol_clone() {
88        let proto = Protocol::Http;
89        let cloned = proto.clone();
90        assert_eq!(proto, cloned);
91    }
92
93    #[test]
94    fn test_protocol_copy() {
95        let proto = Protocol::Grpc;
96        let copied = proto;
97        assert_eq!(Protocol::Grpc, copied);
98        assert_eq!(proto, Protocol::Grpc); // proto still accessible
99    }
100
101    #[test]
102    fn test_protocol_eq() {
103        assert_eq!(Protocol::Http, Protocol::Http);
104        assert_eq!(Protocol::Grpc, Protocol::Grpc);
105        assert_ne!(Protocol::Http, Protocol::Grpc);
106        assert_ne!(Protocol::WebSocket, Protocol::GraphQL);
107    }
108
109    #[test]
110    fn test_protocol_hash() {
111        let mut set = HashSet::new();
112        set.insert(Protocol::Http);
113        set.insert(Protocol::Grpc);
114        set.insert(Protocol::WebSocket);
115        set.insert(Protocol::GraphQL);
116
117        assert_eq!(set.len(), 4);
118        assert!(set.contains(&Protocol::Http));
119        assert!(set.contains(&Protocol::Grpc));
120        assert!(set.contains(&Protocol::WebSocket));
121        assert!(set.contains(&Protocol::GraphQL));
122
123        // Duplicate insertion shouldn't increase size
124        set.insert(Protocol::Http);
125        assert_eq!(set.len(), 4);
126    }
127
128    #[test]
129    fn test_protocol_all_variants() {
130        let protocols = [
131            Protocol::Http,
132            Protocol::Grpc,
133            Protocol::WebSocket,
134            Protocol::GraphQL,
135        ];
136
137        for proto in protocols {
138            let str_repr = proto.as_str();
139            assert!(!str_repr.is_empty());
140            assert_eq!(proto.to_string(), str_repr);
141        }
142    }
143}