gemini_genai_rs/telemetry/
spans.rs

1//! OpenTelemetry span definitions for session operations.
2//!
3//! Each span carries `session_id` for turn-level correlation.
4//! Always compiled: the `tracing` facade is an unconditional dependency;
5//! spans are no-ops unless a subscriber is installed.
6
7/// Create a span for the entire session lifecycle.
8pub fn session_span(session_id: &str) -> tracing::Span {
9    tracing::info_span!("gemini_genai_rs.session", session_id = session_id)
10}
11
12/// Create a span for WebSocket connection.
13pub fn connect_span(url: &str) -> tracing::Span {
14    tracing::info_span!("gemini_genai_rs.connect", url = url)
15}
16
17/// Create a span for the setup handshake.
18pub fn setup_span(session_id: &str) -> tracing::Span {
19    tracing::info_span!("gemini_genai_rs.setup", session_id = session_id)
20}
21
22/// Create a span for audio chunk transmission.
23pub fn send_audio_span(chunk_size: usize, session_id: &str) -> tracing::Span {
24    tracing::info_span!(
25        "gemini_genai_rs.send_audio",
26        chunk_size = chunk_size,
27        session_id = session_id,
28    )
29}
30
31/// Create a span for receiving server content.
32pub fn receive_content_span(session_id: &str) -> tracing::Span {
33    tracing::info_span!("gemini_genai_rs.receive_content", session_id = session_id)
34}
35
36/// Create a span for tool call execution.
37pub fn tool_call_span(function_name: &str, session_id: &str) -> tracing::Span {
38    tracing::info_span!(
39        "gemini_genai_rs.tool_call",
40        function_name = function_name,
41        session_id = session_id,
42    )
43}
44
45/// Create a span for tool response transmission.
46pub fn tool_response_span(session_id: &str) -> tracing::Span {
47    tracing::info_span!("gemini_genai_rs.tool_response", session_id = session_id)
48}
49
50/// Create a span for session disconnect.
51pub fn disconnect_span(session_id: &str, reason: &str) -> tracing::Span {
52    tracing::info_span!(
53        "gemini_genai_rs.disconnect",
54        session_id = session_id,
55        reason = reason,
56    )
57}
58
59/// Create a span for an HTTP REST API request.
60pub fn http_request_span(method: &str, url: &str) -> tracing::Span {
61    tracing::info_span!(
62        "gemini_genai_rs.http_request",
63        http.method = method,
64        http.url = url,
65    )
66}
67
68// No-op stubs when tracing is disabled — these compile to nothing.
69
70#[cfg(test)]
71mod tests {
72    use super::*;
73
74    #[test]
75    fn noop_span_functions_compile() {
76        // All span functions should compile and not panic as no-ops.
77        session_span("sess-1");
78        connect_span("wss://example.com");
79        setup_span("sess-1");
80        send_audio_span(1024, "sess-1");
81        receive_content_span("sess-1");
82        tool_call_span("get_weather", "sess-1");
83        tool_response_span("sess-1");
84        disconnect_span("sess-1", "user requested");
85        http_request_span("GET", "https://example.com");
86    }
87
88    #[test]
89    fn session_span_noop() {
90        session_span("test-session");
91    }
92
93    #[test]
94    fn connect_span_noop() {
95        connect_span("wss://example.com/ws");
96    }
97
98    #[test]
99    fn setup_span_noop() {
100        setup_span("test-session");
101    }
102
103    #[test]
104    fn send_audio_span_noop() {
105        send_audio_span(4096, "test-session");
106    }
107
108    #[test]
109    fn receive_content_span_noop() {
110        receive_content_span("test-session");
111    }
112
113    #[test]
114    fn tool_call_span_noop() {
115        tool_call_span("my_tool", "test-session");
116    }
117
118    #[test]
119    fn tool_response_span_noop() {
120        tool_response_span("test-session");
121    }
122
123    #[test]
124    fn disconnect_span_noop() {
125        disconnect_span("test-session", "shutdown");
126    }
127
128    #[test]
129    fn http_request_span_noop() {
130        http_request_span("POST", "https://api.example.com/v1");
131    }
132}