lambda_otel_utils/
http_meter_provider.rs1use std::time::Duration;
14
15use opentelemetry_http::HttpClient;
16use opentelemetry_otlp::{WithExportConfig, WithHttpConfig};
17use opentelemetry_sdk::{
18 error::OTelSdkError,
19 metrics::{PeriodicReader, SdkMeterProvider},
20};
21use otlp_stdout_client::StdoutClient;
22
23#[derive(Debug)]
45pub struct HttpMeterProviderBuilder<C: HttpClient + 'static = StdoutClient> {
46 client: Option<C>,
47 meter_name: Option<&'static str>,
48 export_interval: Duration,
49 export_timeout: Duration,
50 install_global: bool,
51}
52
53impl Default for HttpMeterProviderBuilder {
54 fn default() -> Self {
55 Self::new()
56 }
57}
58
59impl HttpMeterProviderBuilder {
60 pub fn new() -> Self {
62 Self {
63 client: None,
64 meter_name: None,
65 export_interval: Duration::from_secs(60),
66 export_timeout: Duration::from_secs(10),
67 install_global: false,
68 }
69 }
70
71 pub fn with_stdout_client(mut self) -> Self {
73 self.client = Some(StdoutClient::new());
74 self
75 }
76
77 pub fn with_meter_name(mut self, meter_name: &'static str) -> Self {
83 self.meter_name = Some(meter_name);
84 self
85 }
86
87 pub fn with_export_interval(mut self, interval: Duration) -> Self {
89 self.export_interval = interval;
90 self
91 }
92
93 pub fn with_export_timeout(mut self, timeout: Duration) -> Self {
95 self.export_timeout = timeout;
96 self
97 }
98
99 pub fn enable_global(mut self, set_global: bool) -> Self {
109 self.install_global = set_global;
110 self
111 }
112
113 pub fn build(self) -> Result<SdkMeterProvider, OTelSdkError> {
115 let mut exporter_builder = opentelemetry_otlp::MetricExporter::builder()
116 .with_http()
117 .with_protocol(crate::protocol::get_protocol())
118 .with_timeout(self.export_timeout);
119
120 if let Some(client) = self.client {
121 exporter_builder = exporter_builder.with_http_client(client);
122 }
123
124 let exporter = exporter_builder
125 .build()
126 .map_err(|e| OTelSdkError::InternalFailure(e.to_string()))?;
127
128 let reader = PeriodicReader::builder(exporter)
129 .with_interval(self.export_interval)
130 .build();
131
132 let provider = SdkMeterProvider::builder()
133 .with_reader(reader)
134 .with_resource(crate::resource::get_lambda_resource())
135 .build();
136
137 if self.install_global {
139 opentelemetry::global::set_meter_provider(provider.clone());
140 }
141
142 Ok(provider)
143 }
144}
145
146#[cfg(test)]
147mod tests {
148 use super::*;
149
150 #[test]
151 fn test_http_meter_provider_builder_default() {
152 let builder = HttpMeterProviderBuilder::default();
153 assert!(builder.client.is_none());
154 assert!(builder.meter_name.is_none());
155 assert_eq!(builder.export_interval, Duration::from_secs(60));
156 assert_eq!(builder.export_timeout, Duration::from_secs(10));
157 assert!(!builder.install_global);
158 }
159
160 #[test]
161 fn test_http_meter_provider_builder_customization() {
162 let builder = HttpMeterProviderBuilder::new()
163 .with_stdout_client()
164 .with_meter_name("test-meter")
165 .with_export_interval(Duration::from_secs(30))
166 .with_export_timeout(Duration::from_secs(5))
167 .enable_global(true);
168
169 assert!(builder.client.is_some());
170 assert_eq!(builder.meter_name, Some("test-meter"));
171 assert_eq!(builder.export_interval, Duration::from_secs(30));
172 assert_eq!(builder.export_timeout, Duration::from_secs(5));
173 assert!(builder.install_global);
174 }
175}