opentelemetry_otlp/
metric.rs1#[cfg(any(feature = "http-proto", feature = "http-json", feature = "grpc-tonic"))]
7use crate::HasExportConfig;
8
9#[cfg(any(feature = "http-proto", feature = "http-json"))]
10use crate::{exporter::http::HttpExporterBuilder, HasHttpConfig, HttpExporterBuilderSet};
11
12#[cfg(feature = "grpc-tonic")]
13use crate::{exporter::tonic::TonicExporterBuilder, HasTonicConfig, TonicExporterBuilderSet};
14
15use crate::{ExporterBuildError, NoExporterBuilderSet};
16
17use core::fmt;
18use opentelemetry_sdk::error::OTelSdkResult;
19
20use opentelemetry_sdk::metrics::{
21 data::ResourceMetrics, exporter::PushMetricExporter, Temporality,
22};
23use std::fmt::{Debug, Formatter};
24use std::time::Duration;
25
26pub const OTEL_EXPORTER_OTLP_METRICS_ENDPOINT: &str = "OTEL_EXPORTER_OTLP_METRICS_ENDPOINT";
30pub const OTEL_EXPORTER_OTLP_METRICS_TIMEOUT: &str = "OTEL_EXPORTER_OTLP_METRICS_TIMEOUT";
32pub const OTEL_EXPORTER_OTLP_METRICS_COMPRESSION: &str = "OTEL_EXPORTER_OTLP_METRICS_COMPRESSION";
34pub const OTEL_EXPORTER_OTLP_METRICS_HEADERS: &str = "OTEL_EXPORTER_OTLP_METRICS_HEADERS";
39
40#[derive(Debug, Default, Clone)]
42pub struct MetricExporterBuilder<C> {
43 client: C,
44 temporality: Temporality,
45}
46
47impl MetricExporterBuilder<NoExporterBuilderSet> {
48 pub fn new() -> Self {
50 MetricExporterBuilder::default()
51 }
52}
53
54impl<C> MetricExporterBuilder<C> {
55 #[cfg(feature = "grpc-tonic")]
57 pub fn with_tonic(self) -> MetricExporterBuilder<TonicExporterBuilderSet> {
58 MetricExporterBuilder {
59 client: TonicExporterBuilderSet(TonicExporterBuilder::default()),
60 temporality: self.temporality,
61 }
62 }
63
64 #[cfg(any(feature = "http-proto", feature = "http-json"))]
66 pub fn with_http(self) -> MetricExporterBuilder<HttpExporterBuilderSet> {
67 MetricExporterBuilder {
68 client: HttpExporterBuilderSet(HttpExporterBuilder::default()),
69 temporality: self.temporality,
70 }
71 }
72
73 pub fn with_temporality(self, temporality: Temporality) -> MetricExporterBuilder<C> {
75 MetricExporterBuilder {
76 client: self.client,
77 temporality,
78 }
79 }
80}
81
82#[cfg(feature = "grpc-tonic")]
83impl MetricExporterBuilder<TonicExporterBuilderSet> {
84 pub fn build(self) -> Result<MetricExporter, ExporterBuildError> {
86 let exporter = self.client.0.build_metrics_exporter(self.temporality)?;
87 opentelemetry::otel_debug!(name: "MetricExporterBuilt");
88 Ok(exporter)
89 }
90}
91
92#[cfg(any(feature = "http-proto", feature = "http-json"))]
93impl MetricExporterBuilder<HttpExporterBuilderSet> {
94 pub fn build(self) -> Result<MetricExporter, ExporterBuildError> {
96 let exporter = self.client.0.build_metrics_exporter(self.temporality)?;
97 Ok(exporter)
98 }
99}
100
101#[cfg(feature = "grpc-tonic")]
102impl HasExportConfig for MetricExporterBuilder<TonicExporterBuilderSet> {
103 fn export_config(&mut self) -> &mut crate::ExportConfig {
104 &mut self.client.0.exporter_config
105 }
106}
107
108#[cfg(any(feature = "http-proto", feature = "http-json"))]
109impl HasExportConfig for MetricExporterBuilder<HttpExporterBuilderSet> {
110 fn export_config(&mut self) -> &mut crate::ExportConfig {
111 &mut self.client.0.exporter_config
112 }
113}
114
115#[cfg(feature = "grpc-tonic")]
116impl HasTonicConfig for MetricExporterBuilder<TonicExporterBuilderSet> {
117 fn tonic_config(&mut self) -> &mut crate::TonicConfig {
118 &mut self.client.0.tonic_config
119 }
120}
121
122#[cfg(any(feature = "http-proto", feature = "http-json"))]
123impl HasHttpConfig for MetricExporterBuilder<HttpExporterBuilderSet> {
124 fn http_client_config(&mut self) -> &mut crate::exporter::http::HttpConfig {
125 &mut self.client.0.http_config
126 }
127}
128
129pub(crate) trait MetricsClient: fmt::Debug + Send + Sync + 'static {
131 fn export(
132 &self,
133 metrics: &ResourceMetrics,
134 ) -> impl std::future::Future<Output = OTelSdkResult> + Send;
135 fn shutdown(&self) -> OTelSdkResult;
136}
137
138pub struct MetricExporter {
140 client: SupportedTransportClient,
141 temporality: Temporality,
142}
143
144#[derive(Debug)]
145enum SupportedTransportClient {
146 #[cfg(feature = "grpc-tonic")]
147 Tonic(crate::exporter::tonic::metrics::TonicMetricsClient),
148 #[cfg(any(feature = "http-proto", feature = "http-json"))]
149 Http(crate::exporter::http::OtlpHttpClient),
150}
151
152impl Debug for MetricExporter {
153 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
154 f.debug_struct("MetricExporter").finish()
155 }
156}
157
158impl PushMetricExporter for MetricExporter {
159 async fn export(&self, metrics: &ResourceMetrics) -> OTelSdkResult {
160 match &self.client {
161 #[cfg(feature = "grpc-tonic")]
162 SupportedTransportClient::Tonic(client) => client.export(metrics).await,
163 #[cfg(any(feature = "http-proto", feature = "http-json"))]
164 SupportedTransportClient::Http(client) => client.export(metrics).await,
165 }
166 }
167
168 fn force_flush(&self) -> OTelSdkResult {
169 Ok(())
171 }
172
173 fn shutdown(&self) -> OTelSdkResult {
174 self.shutdown_with_timeout(Duration::from_secs(5))
175 }
176
177 fn shutdown_with_timeout(&self, _timeout: std::time::Duration) -> OTelSdkResult {
178 match &self.client {
179 #[cfg(feature = "grpc-tonic")]
180 SupportedTransportClient::Tonic(client) => client.shutdown(),
181 #[cfg(any(feature = "http-proto", feature = "http-json"))]
182 SupportedTransportClient::Http(client) => client.shutdown(),
183 }
184 }
185
186 fn temporality(&self) -> Temporality {
187 self.temporality
188 }
189}
190
191impl MetricExporter {
192 pub fn builder() -> MetricExporterBuilder<NoExporterBuilderSet> {
194 MetricExporterBuilder::default()
195 }
196
197 #[cfg(feature = "grpc-tonic")]
198 pub(crate) fn from_tonic(
199 client: crate::exporter::tonic::metrics::TonicMetricsClient,
200 temporality: Temporality,
201 ) -> Self {
202 Self {
203 client: SupportedTransportClient::Tonic(client),
204 temporality,
205 }
206 }
207
208 #[cfg(any(feature = "http-proto", feature = "http-json"))]
209 pub(crate) fn from_http(
210 client: crate::exporter::http::OtlpHttpClient,
211 temporality: Temporality,
212 ) -> Self {
213 Self {
214 client: SupportedTransportClient::Http(client),
215 temporality,
216 }
217 }
218}