opentelemetry_otlp/exporter/http/
metrics.rs1use std::sync::Arc;
2
3use crate::metric::MetricsClient;
4use http::{header::CONTENT_TYPE, Method};
5use opentelemetry::otel_debug;
6use opentelemetry_sdk::error::{OTelSdkError, OTelSdkResult};
7use opentelemetry_sdk::metrics::data::ResourceMetrics;
8
9use super::OtlpHttpClient;
10
11impl MetricsClient for OtlpHttpClient {
12 async fn export(&self, metrics: &ResourceMetrics) -> OTelSdkResult {
13 let client = self
14 .client
15 .lock()
16 .map_err(|e| OTelSdkError::InternalFailure(format!("Failed to acquire lock: {e:?}")))
17 .and_then(|g| match &*g {
18 Some(client) => Ok(Arc::clone(client)),
19 _ => Err(OTelSdkError::AlreadyShutdown),
20 })?;
21
22 let (body, content_type, content_encoding) =
23 self.build_metrics_export_body(metrics).ok_or_else(|| {
24 OTelSdkError::InternalFailure("Failed to serialize metrics".to_string())
25 })?;
26
27 let mut request_builder = http::Request::builder()
28 .method(Method::POST)
29 .uri(&self.collector_endpoint)
30 .header(CONTENT_TYPE, content_type);
31
32 if let Some(encoding) = content_encoding {
33 request_builder = request_builder.header("Content-Encoding", encoding);
34 }
35
36 let mut request = request_builder
37 .body(body.into())
38 .map_err(|e| OTelSdkError::InternalFailure(format!("{e:?}")))?;
39
40 for (k, v) in &self.headers {
41 request.headers_mut().insert(k.clone(), v.clone());
42 }
43
44 otel_debug!(name: "HttpMetricsClient.ExportStarted");
45 let result = client.send_bytes(request).await;
46
47 match result {
48 Ok(response) => {
49 if response.status().is_success() {
50 otel_debug!(name: "HttpMetricsClient.ExportSucceeded");
51 Ok(())
52 } else {
53 let error = format!(
54 "OpenTelemetry metrics export failed. Status Code: {}, Response: {:?}",
55 response.status().as_u16(),
56 response.body()
57 );
58 otel_debug!(name: "HttpMetricsClient.ExportFailed", error = &error);
59 Err(OTelSdkError::InternalFailure(error))
60 }
61 }
62 Err(e) => {
63 let error = format!("{e:?}");
64 otel_debug!(name: "HttpMetricsClient.ExportFailed", error = &error);
65 Err(OTelSdkError::InternalFailure(error))
66 }
67 }
68 }
69
70 fn shutdown(&self) -> OTelSdkResult {
71 self.client
72 .lock()
73 .map_err(|e| OTelSdkError::InternalFailure(format!("Failed to acquire lock: {e}")))?
74 .take();
75
76 Ok(())
77 }
78}