mockforge_ws/
ws_tracing.rs1use mockforge_tracing::{create_request_span, record_error, record_success, Protocol};
4use opentelemetry::{global::BoxedSpan, trace::Span, KeyValue};
5use std::collections::HashMap;
6use tracing::debug;
7
8pub fn create_ws_connection_span(path: &str) -> BoxedSpan {
10 create_request_span(
11 Protocol::WebSocket,
12 &format!("WS Connect {}", path),
13 vec![
14 KeyValue::new("ws.path", path.to_string()),
15 KeyValue::new("network.protocol.name", "websocket"),
16 ],
17 )
18}
19
20pub fn create_ws_message_span(direction: &str, message_type: &str, size: usize) -> BoxedSpan {
22 create_request_span(
23 Protocol::WebSocket,
24 &format!("WS Message {}", direction),
25 vec![
26 KeyValue::new("ws.direction", direction.to_string()),
27 KeyValue::new("ws.message.type", message_type.to_string()),
28 KeyValue::new("ws.message.size", size as i64),
29 ],
30 )
31}
32
33pub fn record_ws_connection_success(
35 span: &mut BoxedSpan,
36 duration_ms: u64,
37 messages_sent: usize,
38 messages_received: usize,
39) {
40 let attributes = vec![
41 KeyValue::new("ws.duration_ms", duration_ms as i64),
42 KeyValue::new("ws.messages.sent", messages_sent as i64),
43 KeyValue::new("ws.messages.received", messages_received as i64),
44 ];
45
46 record_success(span, attributes);
47
48 debug!(
49 duration_ms = duration_ms,
50 messages_sent = messages_sent,
51 messages_received = messages_received,
52 "WebSocket connection completed"
53 );
54}
55
56pub fn record_ws_error(span: &mut BoxedSpan, error_message: &str, duration_ms: u64) {
58 span.set_attribute(KeyValue::new("ws.duration_ms", duration_ms as i64));
59 record_error(span, error_message);
60
61 debug!(
62 error_message = error_message,
63 duration_ms = duration_ms,
64 "WebSocket connection failed"
65 );
66}
67
68pub fn record_ws_message_success(span: &mut BoxedSpan, processing_time_us: u64) {
70 let attributes = vec![KeyValue::new(
71 "ws.processing_time_us",
72 processing_time_us as i64,
73 )];
74
75 record_success(span, attributes);
76}
77
78pub fn extract_ws_trace_context(headers: &HashMap<String, String>) -> opentelemetry::Context {
80 mockforge_tracing::extract_trace_context(headers)
81}
82
83pub fn inject_ws_trace_context(
85 ctx: &opentelemetry::Context,
86 headers: &mut HashMap<String, String>,
87) {
88 mockforge_tracing::inject_trace_context(ctx, headers);
89}
90
91#[cfg(test)]
92mod tests {
93 use super::*;
94 use opentelemetry::global;
95 use opentelemetry_sdk::propagation::TraceContextPropagator;
96
97 #[test]
98 fn test_create_ws_connection_span() {
99 global::set_text_map_propagator(TraceContextPropagator::new());
100
101 let mut span = create_ws_connection_span("/ws/chat");
102 record_ws_connection_success(&mut span, 5000, 10, 12);
103 }
104
105 #[test]
106 fn test_create_ws_message_span() {
107 global::set_text_map_propagator(TraceContextPropagator::new());
108
109 let mut span = create_ws_message_span("inbound", "text", 256);
110 record_ws_message_success(&mut span, 150);
111 }
112
113 #[test]
114 fn test_ws_trace_context_propagation() {
115 global::set_text_map_propagator(TraceContextPropagator::new());
116
117 let mut headers = HashMap::new();
118 headers.insert(
119 "traceparent".to_string(),
120 "00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01".to_string(),
121 );
122
123 let ctx = extract_ws_trace_context(&headers);
124
125 let mut output_headers = HashMap::new();
126 inject_ws_trace_context(&ctx, &mut output_headers);
127
128 assert!(output_headers.contains_key("traceparent"));
129 }
130}