rig_core/telemetry/
mod.rs1use crate::completion::GetTokenUsage;
7use serde::Serialize;
8
9pub trait ProviderRequestExt {
11 type InputMessage: Serialize;
13
14 fn get_input_messages(&self) -> Vec<Self::InputMessage>;
16 fn get_system_prompt(&self) -> Option<String>;
18 fn get_model_name(&self) -> String;
20 fn get_prompt(&self) -> Option<String>;
22}
23
24pub trait ProviderResponseExt {
26 type OutputMessage: Serialize;
28 type Usage: Serialize;
30
31 fn get_response_id(&self) -> Option<String>;
33
34 fn get_response_model_name(&self) -> Option<String>;
36
37 fn get_output_messages(&self) -> Vec<Self::OutputMessage>;
39
40 fn get_text_response(&self) -> Option<String>;
42
43 fn get_usage(&self) -> Option<Self::Usage>;
45}
46
47pub trait SpanCombinator {
50 fn record_token_usage<U>(&self, usage: &U)
52 where
53 U: GetTokenUsage;
54
55 fn record_response_metadata<R>(&self, response: &R)
57 where
58 R: ProviderResponseExt;
59
60 fn record_model_input<T>(&self, messages: &T)
62 where
63 T: Serialize;
64
65 fn record_model_output<T>(&self, messages: &T)
67 where
68 T: Serialize;
69}
70
71impl SpanCombinator for tracing::Span {
72 fn record_token_usage<U>(&self, usage: &U)
73 where
74 U: GetTokenUsage,
75 {
76 if self.is_disabled() {
77 return;
78 }
79
80 if let Some(usage) = usage.token_usage() {
81 self.record("gen_ai.usage.input_tokens", usage.input_tokens);
82 self.record("gen_ai.usage.output_tokens", usage.output_tokens);
83 self.record(
84 "gen_ai.usage.cache_read.input_tokens",
85 usage.cached_input_tokens,
86 );
87 self.record(
88 "gen_ai.usage.cache_creation.input_tokens",
89 usage.cache_creation_input_tokens,
90 );
91 self.record("gen_ai.usage.reasoning_tokens", usage.reasoning_tokens);
92 }
93 }
94
95 fn record_response_metadata<R>(&self, response: &R)
96 where
97 R: ProviderResponseExt,
98 {
99 if self.is_disabled() {
100 return;
101 }
102
103 if let Some(id) = response.get_response_id() {
104 self.record("gen_ai.response.id", id);
105 }
106
107 if let Some(model_name) = response.get_response_model_name() {
108 self.record("gen_ai.response.model", model_name);
109 }
110 }
111
112 fn record_model_input<T>(&self, input: &T)
113 where
114 T: Serialize,
115 {
116 if self.is_disabled() {
117 return;
118 }
119
120 if let Ok(input_as_json_string) = serde_json::to_string(input) {
121 self.record("gen_ai.input.messages", input_as_json_string);
122 }
123 }
124
125 fn record_model_output<T>(&self, output: &T)
126 where
127 T: Serialize,
128 {
129 if self.is_disabled() {
130 return;
131 }
132
133 if let Ok(output_as_json_string) = serde_json::to_string(output) {
134 self.record("gen_ai.output.messages", output_as_json_string);
135 }
136 }
137}