Skip to content

Commit

Permalink
Add http-json feature flag
Browse files Browse the repository at this point in the history
  • Loading branch information
ramgdev committed Feb 27, 2024
1 parent ab9415a commit 1482d5c
Show file tree
Hide file tree
Showing 7 changed files with 43 additions and 33 deletions.
5 changes: 4 additions & 1 deletion opentelemetry-otlp/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ reqwest = { workspace = true, optional = true }
http = { workspace = true, optional = true }
serde = { workspace = true, features = ["derive"], optional = true }
thiserror = { workspace = true }
serde_json = { workspace = true, optional = true }

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

# add ons
serialize = ["serde"]
serialize = ["serde", "serde_json"]

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

Expand All @@ -73,6 +74,8 @@ http-proto = ["prost", "opentelemetry-http", "opentelemetry-proto/gen-tonic-mess
reqwest-blocking-client = ["reqwest/blocking", "opentelemetry-http/reqwest"]
reqwest-client = ["reqwest", "opentelemetry-http/reqwest"]
reqwest-rustls = ["reqwest", "reqwest/rustls-tls-native-roots"]
# http json
http-json = ["serde_json", "prost", "opentelemetry-http", "opentelemetry-proto/gen-tonic-messages", "http", "trace", "metrics"]

# test
integration-testing = ["tonic", "prost", "tokio/full", "trace"]
2 changes: 1 addition & 1 deletion opentelemetry-otlp/examples/basic-otlp-http/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ publish = false
once_cell = { workspace = true }
opentelemetry = { path = "../../../opentelemetry" }
opentelemetry_sdk = { path = "../../../opentelemetry-sdk", features = ["rt-tokio", "metrics", "logs"] }
opentelemetry-otlp = { path = "../..", features = ["http-proto", "reqwest-client", "logs"] }
opentelemetry-otlp = { path = "../..", features = ["http-proto", "http-json", "reqwest-client", "logs"] }
opentelemetry-appender-tracing = { path = "../../../opentelemetry-appender-tracing", default-features = false}
opentelemetry-semantic-conventions = { path = "../../../opentelemetry-semantic-conventions" }

Expand Down
2 changes: 1 addition & 1 deletion opentelemetry-otlp/src/exporter/http/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ mod logs;
mod trace;

/// Configuration of the http transport
#[cfg(feature = "http-proto")]
#[cfg(any(feature = "http-proto", feature = "http-json"))]
#[derive(Debug)]
#[cfg_attr(
all(
Expand Down
8 changes: 4 additions & 4 deletions opentelemetry-otlp/src/exporter/http/trace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ impl SpanExporter for OtlpHttpClient {
}
}

#[cfg(feature = "http-proto")]
#[cfg(any(feature = "http-proto", feature = "http-json"))]
fn build_body(spans: Vec<SpanData>) -> TraceResult<(Vec<u8>, &'static str)> {
use opentelemetry_proto::tonic::collector::trace::v1::ExportTraceServiceRequest;
use prost::Message;
Expand All @@ -79,12 +79,12 @@ fn build_body(spans: Vec<SpanData>) -> TraceResult<(Vec<u8>, &'static str)> {
let mut buf = vec![];
req.encode(&mut buf).map_err(crate::Error::from)?;

Ok((buf, "application/x-protobuf"))
Ok((buf, "application/x-protobuf"))

Check warning on line 82 in opentelemetry-otlp/src/exporter/http/trace.rs

View check run for this annotation

Codecov / codecov/patch

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

Added line #L82 was not covered by tests
}

#[cfg(not(feature = "http-proto"))]
#[cfg(not(any(feature = "http-proto", feature = "http-json")))]
fn build_body(spans: Vec<SpanData>) -> TraceResult<(Vec<u8>, &'static str)> {
Err(TraceError::Other(
"No http protocol configured. Enable one via `http-proto`".into(),
"No http protocol configured. Enable one via `http-proto` or `http-json`".into(),
))
}
28 changes: 17 additions & 11 deletions opentelemetry-otlp/src/exporter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//!
//! OTLP supports sending data via different protocols and formats.

#[cfg(feature = "http-proto")]
#[cfg(any(feature = "http-proto", feature = "http-json"))]
use crate::exporter::http::HttpExporterBuilder;
#[cfg(feature = "grpc-tonic")]
use crate::exporter::tonic::TonicExporterBuilder;
Expand Down Expand Up @@ -31,15 +31,19 @@ pub const OTEL_EXPORTER_OTLP_COMPRESSION: &str = "OTEL_EXPORTER_OTLP_COMPRESSION
#[cfg(feature = "http-proto")]
/// Default protocol, using http-proto.
pub const OTEL_EXPORTER_OTLP_PROTOCOL_DEFAULT: &str = OTEL_EXPORTER_OTLP_PROTOCOL_HTTP_PROTOBUF;
#[cfg(all(feature = "grpc-tonic", not(feature = "http-proto")))]
/// Default protocol, using grpc as http-proto feature is not enabled.
#[cfg(all(feature = "http-json", feature = "trace", not(any(feature = "http-proto", feature = "grpc-tonic"))))]
/// Default protocol, using http-json.
pub const OTEL_EXPORTER_OTLP_PROTOCOL_DEFAULT: &str = OTEL_EXPORTER_OTLP_PROTOCOL_HTTP_JSON;
#[cfg(all(feature = "grpc-tonic", not(any(feature = "http-proto", feature = "http-json"))))]
/// Default protocol, using grpc as http-proto or http-json feature is not enabled.
pub const OTEL_EXPORTER_OTLP_PROTOCOL_DEFAULT: &str = OTEL_EXPORTER_OTLP_PROTOCOL_GRPC;
#[cfg(not(any(any(feature = "grpc-tonic", feature = "http-proto"))))]
#[cfg(not(any(any(feature = "grpc-tonic", feature = "http-proto", feature = "http-json"))))]
/// Default protocol if no features are enabled.
pub const OTEL_EXPORTER_OTLP_PROTOCOL_DEFAULT: &str = "";

const OTEL_EXPORTER_OTLP_PROTOCOL_HTTP_PROTOBUF: &str = "http/protobuf";
const OTEL_EXPORTER_OTLP_PROTOCOL_GRPC: &str = "grpc";
const OTEL_EXPORTER_OTLP_PROTOCOL_HTTP_JSON: &str = "http/json";

/// Max waiting time for the backend to process each signal batch, defaults to 10 seconds.
pub const OTEL_EXPORTER_OTLP_TIMEOUT: &str = "OTEL_EXPORTER_OTLP_TIMEOUT";
Expand All @@ -50,7 +54,7 @@ pub const OTEL_EXPORTER_OTLP_TIMEOUT_DEFAULT: u64 = 10;
const OTEL_EXPORTER_OTLP_GRPC_ENDPOINT_DEFAULT: &str = "http://localhost:4317";
const OTEL_EXPORTER_OTLP_HTTP_ENDPOINT_DEFAULT: &str = "http://localhost:4318";

#[cfg(feature = "http-proto")]
#[cfg(any(feature = "http-proto", feature = "http-json"))]
pub(crate) mod http;
#[cfg(feature = "grpc-tonic")]
pub(crate) mod tonic;
Expand Down Expand Up @@ -112,6 +116,7 @@ fn default_protocol() -> Protocol {
match OTEL_EXPORTER_OTLP_PROTOCOL_DEFAULT {
OTEL_EXPORTER_OTLP_PROTOCOL_HTTP_PROTOBUF => Protocol::HttpBinary,
OTEL_EXPORTER_OTLP_PROTOCOL_GRPC => Protocol::Grpc,
OTEL_EXPORTER_OTLP_PROTOCOL_HTTP_JSON => Protocol::HttpJson,

Check warning on line 119 in opentelemetry-otlp/src/exporter/mod.rs

View check run for this annotation

Codecov / codecov/patch

opentelemetry-otlp/src/exporter/mod.rs#L119

Added line #L119 was not covered by tests
_ => Protocol::HttpBinary,
}
}
Expand All @@ -121,11 +126,12 @@ fn default_endpoint(protocol: Protocol) -> String {
match protocol {
Protocol::Grpc => OTEL_EXPORTER_OTLP_GRPC_ENDPOINT_DEFAULT.to_string(),
Protocol::HttpBinary => OTEL_EXPORTER_OTLP_HTTP_ENDPOINT_DEFAULT.to_string(),
Protocol::HttpJson => OTEL_EXPORTER_OTLP_HTTP_ENDPOINT_DEFAULT.to_string(),

Check warning on line 129 in opentelemetry-otlp/src/exporter/mod.rs

View check run for this annotation

Codecov / codecov/patch

opentelemetry-otlp/src/exporter/mod.rs#L129

Added line #L129 was not covered by tests
}
}

/// default user-agent headers
#[cfg(any(feature = "grpc-tonic", feature = "http-proto"))]
#[cfg(any(feature = "grpc-tonic", feature = "http-proto", feature = "http-json"))]
fn default_headers() -> std::collections::HashMap<String, String> {
let mut headers = std::collections::HashMap::new();
headers.insert(
Expand All @@ -148,7 +154,7 @@ impl HasExportConfig for TonicExporterBuilder {
}
}

#[cfg(feature = "http-proto")]
#[cfg(any(feature = "http-proto", feature = "http-json"))]
impl HasExportConfig for HttpExporterBuilder {
fn export_config(&mut self) -> &mut ExportConfig {
&mut self.exporter_config
Expand Down Expand Up @@ -210,15 +216,15 @@ impl<B: HasExportConfig> WithExportConfig for B {
}
}

#[cfg(any(feature = "grpc-tonic", feature = "http-proto"))]
#[cfg(any(feature = "grpc-tonic", feature = "http-proto", feature = "http-json"))]
fn parse_header_string(value: &str) -> impl Iterator<Item = (&str, &str)> {
value
.split_terminator(',')
.map(str::trim)
.filter_map(parse_header_key_value_string)
}

#[cfg(any(feature = "grpc-tonic", feature = "http-proto"))]
#[cfg(any(feature = "grpc-tonic", feature = "http-proto", feature = "http-json"))]
fn parse_header_key_value_string(key_value_string: &str) -> Option<(&str, &str)> {
key_value_string
.split_once('=')
Expand All @@ -227,7 +233,7 @@ fn parse_header_key_value_string(key_value_string: &str) -> Option<(&str, &str)>
}

#[cfg(test)]
#[cfg(any(feature = "grpc-tonic", feature = "http-proto"))]
#[cfg(any(feature = "grpc-tonic", feature = "http-proto", feature = "http-json"))]
mod tests {

pub(crate) fn run_env_test<T, F>(env_vars: T, f: F)
Expand All @@ -245,7 +251,7 @@ mod tests {
)
}

#[cfg(feature = "http-proto")]
#[cfg(any(feature = "http-proto", feature = "http-json"))]
#[test]
fn test_default_http_endpoint() {
let exporter_builder = crate::new_exporter().http();
Expand Down
23 changes: 12 additions & 11 deletions opentelemetry-otlp/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@
//! * `reqwest-blocking-client`: Use reqwest blocking http client.
//! * `reqwest-client`: Use reqwest http client.
//! * `reqwest-rustls`: Use reqwest with TLS.
//! * `http-json`: Use http as transport layer, JSON as body format.
//!
//! # Kitchen Sink Full Configuration
//!
Expand Down Expand Up @@ -247,7 +248,7 @@ pub use crate::exporter::{

use opentelemetry_sdk::export::ExportError;

#[cfg(feature = "http-proto")]
#[cfg(any(feature = "http-proto", feature = "http-json"))]
pub use crate::exporter::http::HttpExporterBuilder;

#[cfg(feature = "grpc-tonic")]
Expand Down Expand Up @@ -278,7 +279,7 @@ impl OtlpExporterPipeline {
/// and build the exporter.
///
/// This exporter can be used in both `tracing` and `metrics` pipeline.
#[cfg(feature = "http-proto")]
#[cfg(any(feature = "http-proto", feature = "http-json"))]
pub fn http(self) -> HttpExporterBuilder {
HttpExporterBuilder::default()
}
Expand Down Expand Up @@ -314,7 +315,7 @@ pub enum Error {
Transport(#[from] tonic::transport::Error),

/// Wrap the [`tonic::codegen::http::uri::InvalidUri`] error
#[cfg(any(feature = "grpc-tonic", feature = "http-proto"))]
#[cfg(any(feature = "grpc-tonic", feature = "http-proto", feature = "http-json"))]
#[error("invalid URI {0}")]
InvalidUri(#[from] http::uri::InvalidUri),

Expand All @@ -329,32 +330,32 @@ pub enum Error {
},

/// Http requests failed because no http client is provided.
#[cfg(feature = "http-proto")]
#[cfg(any(feature = "http-proto", feature = "http-json"))]
#[error(
"no http client, you must select one from features or provide your own implementation"
)]
NoHttpClient,

/// Http requests failed.
#[cfg(feature = "http-proto")]
#[cfg(any(feature = "http-proto", feature = "http-json"))]
#[error("http request failed with {0}")]
RequestFailed(#[from] opentelemetry_http::HttpError),

/// The provided value is invalid in HTTP headers.
#[cfg(any(feature = "grpc-tonic", feature = "http-proto"))]
#[cfg(any(feature = "grpc-tonic", feature = "http-proto", feature = "http-json"))]
#[error("http header value error {0}")]
InvalidHeaderValue(#[from] http::header::InvalidHeaderValue),

/// The provided name is invalid in HTTP headers.
#[cfg(any(feature = "grpc-tonic", feature = "http-proto"))]
#[cfg(any(feature = "grpc-tonic", feature = "http-proto", feature = "http-json"))]
#[error("http header name error {0}")]
InvalidHeaderName(#[from] http::header::InvalidHeaderName),

/// Prost encode failed
#[cfg(feature = "http-proto")]
#[cfg(any(feature = "http-proto", all(feature = "http-json", not(feature = "trace"))))]
#[error("prost encoding error {0}")]
EncodeError(#[from] prost::EncodeError),

/// The lock in exporters has been poisoned.
#[cfg(feature = "metrics")]
#[error("the lock of the {0} has been poisoned")]
Expand Down Expand Up @@ -393,10 +394,10 @@ impl ExportError for Error {
pub enum Protocol {
/// GRPC protocol
Grpc,
// TODO add support for other protocols
// HttpJson,
/// HTTP protocol with binary protobuf
HttpBinary,
/// HTTP protocol with JSON payload
HttpJson,
}

#[derive(Debug, Default)]
Expand Down
8 changes: 4 additions & 4 deletions opentelemetry-otlp/src/span.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use sdk::runtime::RuntimeChannel;
#[cfg(feature = "grpc-tonic")]
use crate::exporter::tonic::TonicExporterBuilder;

#[cfg(feature = "http-proto")]
#[cfg(any(feature = "http-proto", feature = "http-json"))]
use crate::exporter::http::HttpExporterBuilder;

use crate::{NoExporterConfig, OtlpPipeline};
Expand Down Expand Up @@ -187,7 +187,7 @@ pub enum SpanExporterBuilder {
#[cfg(feature = "grpc-tonic")]
Tonic(TonicExporterBuilder),
/// Http span exporter builder
#[cfg(feature = "http-proto")]
#[cfg(any(feature = "http-proto", feature = "http-json"))]
Http(HttpExporterBuilder),
}

Expand All @@ -197,7 +197,7 @@ impl SpanExporterBuilder {
match self {
#[cfg(feature = "grpc-tonic")]
SpanExporterBuilder::Tonic(builder) => builder.build_span_exporter(),
#[cfg(feature = "http-proto")]
#[cfg(any(feature = "http-proto", feature = "http-json"))]
SpanExporterBuilder::Http(builder) => builder.build_span_exporter(),
}
}
Expand All @@ -210,7 +210,7 @@ impl From<TonicExporterBuilder> for SpanExporterBuilder {
}
}

#[cfg(feature = "http-proto")]
#[cfg(any(feature = "http-proto", feature = "http-json"))]
impl From<HttpExporterBuilder> for SpanExporterBuilder {
fn from(exporter: HttpExporterBuilder) -> Self {
SpanExporterBuilder::Http(exporter)
Expand Down

0 comments on commit 1482d5c

Please sign in to comment.