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//! Feature-gated behind `tracing-support`.
5
6/// Create a span for the entire session lifecycle.
7#[cfg(feature = "tracing-support")]
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.
13#[cfg(feature = "tracing-support")]
14pub fn connect_span(url: &str) -> tracing::Span {
15    tracing::info_span!("gemini_genai_rs.connect", url = url)
16}
17
18/// Create a span for the setup handshake.
19#[cfg(feature = "tracing-support")]
20pub fn setup_span(session_id: &str) -> tracing::Span {
21    tracing::info_span!("gemini_genai_rs.setup", session_id = session_id)
22}
23
24/// Create a span for audio chunk transmission.
25#[cfg(feature = "tracing-support")]
26pub fn send_audio_span(chunk_size: usize, session_id: &str) -> tracing::Span {
27    tracing::info_span!(
28        "gemini_genai_rs.send_audio",
29        chunk_size = chunk_size,
30        session_id = session_id,
31    )
32}
33
34/// Create a span for receiving server content.
35#[cfg(feature = "tracing-support")]
36pub fn receive_content_span(session_id: &str) -> tracing::Span {
37    tracing::info_span!("gemini_genai_rs.receive_content", session_id = session_id)
38}
39
40/// Create a span for tool call execution.
41#[cfg(feature = "tracing-support")]
42pub fn tool_call_span(function_name: &str, session_id: &str) -> tracing::Span {
43    tracing::info_span!(
44        "gemini_genai_rs.tool_call",
45        function_name = function_name,
46        session_id = session_id,
47    )
48}
49
50/// Create a span for tool response transmission.
51#[cfg(feature = "tracing-support")]
52pub fn tool_response_span(session_id: &str) -> tracing::Span {
53    tracing::info_span!("gemini_genai_rs.tool_response", session_id = session_id)
54}
55
56/// Create a span for session disconnect.
57#[cfg(feature = "tracing-support")]
58pub fn disconnect_span(session_id: &str, reason: &str) -> tracing::Span {
59    tracing::info_span!(
60        "gemini_genai_rs.disconnect",
61        session_id = session_id,
62        reason = reason,
63    )
64}
65
66/// Create a span for an HTTP REST API request.
67#[cfg(feature = "tracing-support")]
68pub fn http_request_span(method: &str, url: &str) -> tracing::Span {
69    tracing::info_span!(
70        "gemini_genai_rs.http_request",
71        http.method = method,
72        http.url = url,
73    )
74}
75
76// No-op stubs when tracing is disabled — these compile to nothing.
77#[cfg(not(feature = "tracing-support"))]
78pub fn session_span(_: &str) {}
79#[cfg(not(feature = "tracing-support"))]
80pub fn connect_span(_: &str) {}
81#[cfg(not(feature = "tracing-support"))]
82pub fn setup_span(_: &str) {}
83#[cfg(not(feature = "tracing-support"))]
84pub fn send_audio_span(_: usize, _: &str) {}
85#[cfg(not(feature = "tracing-support"))]
86pub fn receive_content_span(_: &str) {}
87#[cfg(not(feature = "tracing-support"))]
88pub fn tool_call_span(_: &str, _: &str) {}
89#[cfg(not(feature = "tracing-support"))]
90pub fn tool_response_span(_: &str) {}
91#[cfg(not(feature = "tracing-support"))]
92pub fn disconnect_span(_: &str, _: &str) {}
93#[cfg(not(feature = "tracing-support"))]
94pub fn http_request_span(_: &str, _: &str) {}
95
96#[cfg(test)]
97mod tests {
98    use super::*;
99
100    #[test]
101    fn noop_span_functions_compile() {
102        // All span functions should compile and not panic as no-ops.
103        session_span("sess-1");
104        connect_span("wss://example.com");
105        setup_span("sess-1");
106        send_audio_span(1024, "sess-1");
107        receive_content_span("sess-1");
108        tool_call_span("get_weather", "sess-1");
109        tool_response_span("sess-1");
110        disconnect_span("sess-1", "user requested");
111        http_request_span("GET", "https://example.com");
112    }
113
114    #[test]
115    fn session_span_noop() {
116        session_span("test-session");
117    }
118
119    #[test]
120    fn connect_span_noop() {
121        connect_span("wss://example.com/ws");
122    }
123
124    #[test]
125    fn setup_span_noop() {
126        setup_span("test-session");
127    }
128
129    #[test]
130    fn send_audio_span_noop() {
131        send_audio_span(4096, "test-session");
132    }
133
134    #[test]
135    fn receive_content_span_noop() {
136        receive_content_span("test-session");
137    }
138
139    #[test]
140    fn tool_call_span_noop() {
141        tool_call_span("my_tool", "test-session");
142    }
143
144    #[test]
145    fn tool_response_span_noop() {
146        tool_response_span("test-session");
147    }
148
149    #[test]
150    fn disconnect_span_noop() {
151        disconnect_span("test-session", "shutdown");
152    }
153
154    #[test]
155    fn http_request_span_noop() {
156        http_request_span("POST", "https://api.example.com/v1");
157    }
158}