Skip to content

Commit 65deeef

Browse files
authored
Merge branch 'main' into feat/log-kvs
2 parents bc267e0 + 8a9a569 commit 65deeef

File tree

16 files changed

+4568
-1295
lines changed

16 files changed

+4568
-1295
lines changed

RELEASING.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ A draft PR can be created, but before releasing consider the following:
1616

1717
* Are there any pending pull requests which should be included in the next release?
1818
* Are they blockers?
19-
* Are there any unresolved issues which should be resolved before the next release?
19+
* Are there any unresolved issues which should be resolved before the next release? Check the release [blockers milestone](https://github.com/open-telemetry/opentelemetry-rust/milestones) for every release
2020
* Bring it up at a SIG meeting, this can usually get some of these questions answered sooner than later. It will also
2121
help establish a person to perform the release. Ideally this can be someone different each time to ensure that the
2222
process is documented.

opentelemetry-otlp/CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88

99
### Added
1010

11+
- Aded `http/json` support for all signals ([#1585])
12+
13+
[#1585]: https://github.com/open-telemetry/opentelemetry-rust/pull/1585
14+
1115
- Added `DeltaTemporalitySelector` ([#1568])
1216
- Add `webkpi-roots` features to `reqwest` and `tonic` backends
1317

opentelemetry-otlp/Cargo.toml

+4-1
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ reqwest = { workspace = true, optional = true }
4242
http = { workspace = true, optional = true }
4343
serde = { workspace = true, features = ["derive"], optional = true }
4444
thiserror = { workspace = true }
45+
serde_json = { workspace = true, optional = true }
4546

4647
[dev-dependencies]
4748
tokio-stream = { workspace = true, features = ["net"] }
@@ -58,7 +59,7 @@ metrics = ["opentelemetry/metrics", "opentelemetry_sdk/metrics", "opentelemetry-
5859
logs = ["opentelemetry/logs", "opentelemetry_sdk/logs", "opentelemetry-proto/logs"]
5960

6061
# add ons
61-
serialize = ["serde"]
62+
serialize = ["serde", "serde_json"]
6263

6364
default = ["grpc-tonic", "trace"]
6465

@@ -71,6 +72,8 @@ tls-webkpi-roots = ["tls", "tonic/tls-webpki-roots"]
7172

7273
# http binary
7374
http-proto = ["prost", "opentelemetry-http", "opentelemetry-proto/gen-tonic-messages", "http", "trace", "metrics"]
75+
# http json
76+
http-json = ["serde_json", "prost", "opentelemetry-http", "opentelemetry-proto/gen-tonic-messages", "opentelemetry-proto/with-serde", "http", "trace", "metrics"]
7477
reqwest-blocking-client = ["reqwest/blocking", "opentelemetry-http/reqwest"]
7578
reqwest-client = ["reqwest", "opentelemetry-http/reqwest"]
7679
reqwest-rustls = ["reqwest", "opentelemetry-http/reqwest-rustls"]

opentelemetry-otlp/examples/basic-otlp-http/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ publish = false
99
once_cell = { workspace = true }
1010
opentelemetry = { path = "../../../opentelemetry" }
1111
opentelemetry_sdk = { path = "../../../opentelemetry-sdk", features = ["rt-tokio", "metrics", "logs"] }
12-
opentelemetry-otlp = { path = "../..", features = ["http-proto", "reqwest-client", "logs"] }
12+
opentelemetry-otlp = { path = "../..", features = ["http-proto", "http-json", "reqwest-client", "logs"] }
1313
opentelemetry-appender-tracing = { path = "../../../opentelemetry-appender-tracing", default-features = false}
1414
opentelemetry-semantic-conventions = { path = "../../../opentelemetry-semantic-conventions" }
1515

opentelemetry-otlp/src/exporter/http/logs.rs

+1-22
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ impl LogExporter for OtlpHttpClient {
1919
_ => Err(LogError::Other("exporter is already shut down".into())),
2020
})?;
2121

22-
let (body, content_type) = build_body(batch)?;
22+
let (body, content_type) = self.build_logs_export_body(batch)?;
2323
let mut request = http::Request::builder()
2424
.method(Method::POST)
2525
.uri(&self.collector_endpoint)
@@ -51,24 +51,3 @@ impl LogExporter for OtlpHttpClient {
5151
let _ = self.client.lock().map(|mut c| c.take());
5252
}
5353
}
54-
55-
#[cfg(feature = "http-proto")]
56-
fn build_body(logs: Vec<LogData>) -> LogResult<(Vec<u8>, &'static str)> {
57-
use opentelemetry_proto::tonic::collector::logs::v1::ExportLogsServiceRequest;
58-
use prost::Message;
59-
60-
let req = ExportLogsServiceRequest {
61-
resource_logs: logs.into_iter().map(Into::into).collect(),
62-
};
63-
let mut buf = vec![];
64-
req.encode(&mut buf).map_err(crate::Error::from)?;
65-
66-
Ok((buf, "application/x-protobuf"))
67-
}
68-
69-
#[cfg(not(feature = "http-proto"))]
70-
fn build_body(logs: Vec<LogData>) -> LogResult<(Vec<u8>, &'static str)> {
71-
Err(LogsError::Other(
72-
"No http protocol configured. Enable one via `http-proto`".into(),
73-
))
74-
}

opentelemetry-otlp/src/exporter/http/metrics.rs

+1-20
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ impl MetricsClient for OtlpHttpClient {
2121
_ => Err(MetricsError::Other("exporter is already shut down".into())),
2222
})?;
2323

24-
let (body, content_type) = build_body(metrics)?;
24+
let (body, content_type) = self.build_metrics_export_body(metrics)?;
2525
let mut request = http::Request::builder()
2626
.method(Method::POST)
2727
.uri(&self.collector_endpoint)
@@ -47,22 +47,3 @@ impl MetricsClient for OtlpHttpClient {
4747
Ok(())
4848
}
4949
}
50-
51-
#[cfg(feature = "http-proto")]
52-
fn build_body(metrics: &mut ResourceMetrics) -> Result<(Vec<u8>, &'static str)> {
53-
use prost::Message;
54-
55-
let req: opentelemetry_proto::tonic::collector::metrics::v1::ExportMetricsServiceRequest =
56-
(&*metrics).into();
57-
let mut buf = vec![];
58-
req.encode(&mut buf).map_err(crate::Error::from)?;
59-
60-
Ok((buf, "application/x-protobuf"))
61-
}
62-
63-
#[cfg(not(feature = "http-proto"))]
64-
fn build_body(metrics: &mut ResourceMetrics) -> Result<(Vec<u8>, &'static str)> {
65-
Err(MetricsError::Other(
66-
"No http protocol configured. Enable one via `http-proto`".into(),
67-
))
68-
}

opentelemetry-otlp/src/exporter/http/mod.rs

+85-5
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,23 @@
1+
use super::{default_headers, default_protocol, parse_header_string};
12
use crate::{
23
ExportConfig, Protocol, OTEL_EXPORTER_OTLP_ENDPOINT, OTEL_EXPORTER_OTLP_HEADERS,
34
OTEL_EXPORTER_OTLP_TIMEOUT,
45
};
56
use http::{HeaderName, HeaderValue, Uri};
67
use opentelemetry_http::HttpClient;
8+
#[cfg(feature = "logs")]
9+
use opentelemetry_sdk::export::logs::LogData;
10+
#[cfg(feature = "trace")]
11+
use opentelemetry_sdk::export::trace::SpanData;
12+
#[cfg(feature = "metrics")]
13+
use opentelemetry_sdk::metrics::data::ResourceMetrics;
14+
use prost::Message;
715
use std::collections::HashMap;
816
use std::env;
917
use std::str::FromStr;
1018
use std::sync::{Arc, Mutex};
1119
use std::time::Duration;
1220

13-
use super::{default_headers, parse_header_string};
14-
1521
#[cfg(feature = "metrics")]
1622
mod metrics;
1723

@@ -22,7 +28,7 @@ mod logs;
2228
mod trace;
2329

2430
/// Configuration of the http transport
25-
#[cfg(feature = "http-proto")]
31+
#[cfg(any(feature = "http-proto", feature = "http-json"))]
2632
#[derive(Debug)]
2733
#[cfg_attr(
2834
all(
@@ -98,7 +104,7 @@ impl Default for HttpExporterBuilder {
98104
fn default() -> Self {
99105
HttpExporterBuilder {
100106
exporter_config: ExportConfig {
101-
protocol: Protocol::HttpBinary,
107+
protocol: default_protocol(),
102108
..ExportConfig::default()
103109
},
104110
http_config: HttpConfig {
@@ -110,6 +116,12 @@ impl Default for HttpExporterBuilder {
110116
}
111117

112118
impl HttpExporterBuilder {
119+
/// Specify the OTLP protocol to be used by the exporter
120+
pub fn with_protocol(mut self, protocol: Protocol) -> Self {
121+
self.exporter_config.protocol = protocol;
122+
self
123+
}
124+
113125
/// Assign client implementation
114126
pub fn with_http_client<T: HttpClient + 'static>(mut self, client: T) -> Self {
115127
self.http_config.client = Some(Arc::new(client));
@@ -181,7 +193,13 @@ impl HttpExporterBuilder {
181193
add_header_from_string(&input, &mut headers);
182194
}
183195

184-
Ok(OtlpHttpClient::new(http_client, endpoint, headers, timeout))
196+
Ok(OtlpHttpClient::new(
197+
http_client,
198+
endpoint,
199+
headers,
200+
self.exporter_config.protocol,
201+
timeout,
202+
))
185203
}
186204

187205
/// Create a log exporter with the current configuration
@@ -254,6 +272,7 @@ struct OtlpHttpClient {
254272
client: Mutex<Option<Arc<dyn HttpClient>>>,
255273
collector_endpoint: Uri,
256274
headers: HashMap<HeaderName, HeaderValue>,
275+
protocol: Protocol,
257276
_timeout: Duration,
258277
}
259278

@@ -263,15 +282,76 @@ impl OtlpHttpClient {
263282
client: Arc<dyn HttpClient>,
264283
collector_endpoint: Uri,
265284
headers: HashMap<HeaderName, HeaderValue>,
285+
protocol: Protocol,
266286
timeout: Duration,
267287
) -> Self {
268288
OtlpHttpClient {
269289
client: Mutex::new(Some(client)),
270290
collector_endpoint,
271291
headers,
292+
protocol,
272293
_timeout: timeout,
273294
}
274295
}
296+
297+
#[cfg(feature = "trace")]
298+
fn build_trace_export_body(
299+
&self,
300+
spans: Vec<SpanData>,
301+
) -> opentelemetry::trace::TraceResult<(Vec<u8>, &'static str)> {
302+
use opentelemetry_proto::tonic::collector::trace::v1::ExportTraceServiceRequest;
303+
304+
let req = ExportTraceServiceRequest {
305+
resource_spans: spans.into_iter().map(Into::into).collect(),
306+
};
307+
match self.protocol {
308+
#[cfg(feature = "http-json")]
309+
Protocol::HttpJson => match serde_json::to_string_pretty(&req) {
310+
Ok(json) => Ok((json.into(), "application/json")),
311+
Err(e) => Err(opentelemetry::trace::TraceError::from(e.to_string())),
312+
},
313+
_ => Ok((req.encode_to_vec(), "application/x-protobuf")),
314+
}
315+
}
316+
317+
#[cfg(feature = "logs")]
318+
fn build_logs_export_body(
319+
&self,
320+
logs: Vec<LogData>,
321+
) -> opentelemetry::logs::LogResult<(Vec<u8>, &'static str)> {
322+
use opentelemetry_proto::tonic::collector::logs::v1::ExportLogsServiceRequest;
323+
324+
let req = ExportLogsServiceRequest {
325+
resource_logs: logs.into_iter().map(Into::into).collect(),
326+
};
327+
match self.protocol {
328+
#[cfg(feature = "http-json")]
329+
Protocol::HttpJson => match serde_json::to_string_pretty(&req) {
330+
Ok(json) => Ok((json.into(), "application/json")),
331+
Err(e) => Err(opentelemetry::logs::LogError::from(e.to_string())),
332+
},
333+
_ => Ok((req.encode_to_vec(), "application/x-protobuf")),
334+
}
335+
}
336+
337+
#[cfg(feature = "metrics")]
338+
fn build_metrics_export_body(
339+
&self,
340+
metrics: &mut ResourceMetrics,
341+
) -> opentelemetry::metrics::Result<(Vec<u8>, &'static str)> {
342+
use opentelemetry_proto::tonic::collector::metrics::v1::ExportMetricsServiceRequest;
343+
344+
let req: ExportMetricsServiceRequest = (&*metrics).into();
345+
346+
match self.protocol {
347+
#[cfg(feature = "http-json")]
348+
Protocol::HttpJson => match serde_json::to_string_pretty(&req) {
349+
Ok(json) => Ok((json.into(), "application/json")),
350+
Err(e) => Err(opentelemetry::metrics::MetricsError::Other(e.to_string())),
351+
},
352+
_ => Ok((req.encode_to_vec(), "application/x-protobuf")),
353+
}
354+
}
275355
}
276356

277357
fn build_endpoint_uri(endpoint: &str, path: &str) -> Result<Uri, crate::Error> {

opentelemetry-otlp/src/exporter/http/trace.rs

+2-23
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::sync::Arc;
22

33
use futures_core::future::BoxFuture;
44
use http::{header::CONTENT_TYPE, Method};
5-
use opentelemetry::trace::{TraceError, TraceResult};
5+
use opentelemetry::trace::TraceError;
66
use opentelemetry_sdk::export::trace::{ExportResult, SpanData, SpanExporter};
77

88
use super::OtlpHttpClient;
@@ -21,7 +21,7 @@ impl SpanExporter for OtlpHttpClient {
2121
Err(err) => return Box::pin(std::future::ready(Err(err))),
2222
};
2323

24-
let (body, content_type) = match build_body(batch) {
24+
let (body, content_type) = match self.build_trace_export_body(batch) {
2525
Ok(body) => body,
2626
Err(e) => return Box::pin(std::future::ready(Err(e))),
2727
};
@@ -67,24 +67,3 @@ impl SpanExporter for OtlpHttpClient {
6767
let _ = self.client.lock().map(|mut c| c.take());
6868
}
6969
}
70-
71-
#[cfg(feature = "http-proto")]
72-
fn build_body(spans: Vec<SpanData>) -> TraceResult<(Vec<u8>, &'static str)> {
73-
use opentelemetry_proto::tonic::collector::trace::v1::ExportTraceServiceRequest;
74-
use prost::Message;
75-
76-
let req = ExportTraceServiceRequest {
77-
resource_spans: spans.into_iter().map(Into::into).collect(),
78-
};
79-
let mut buf = vec![];
80-
req.encode(&mut buf).map_err(crate::Error::from)?;
81-
82-
Ok((buf, "application/x-protobuf"))
83-
}
84-
85-
#[cfg(not(feature = "http-proto"))]
86-
fn build_body(spans: Vec<SpanData>) -> TraceResult<(Vec<u8>, &'static str)> {
87-
Err(TraceError::Other(
88-
"No http protocol configured. Enable one via `http-proto`".into(),
89-
))
90-
}

0 commit comments

Comments
 (0)