Skip to content

Commit 19c3017

Browse files
authored
Merge pull request #2463 from calebschoepp/grpc-otel
feat(telemetry): Make telemetry support http/protobuf protocol in addition to grpc protocol
2 parents 63972c2 + 0992503 commit 19c3017

File tree

6 files changed

+242
-30
lines changed

6 files changed

+242
-30
lines changed

Cargo.lock

Lines changed: 85 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/telemetry/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ http0 = { version = "0.2.9", package = "http" }
1010
http1 = { version = "1.0.0", package = "http" }
1111
opentelemetry = { version = "0.22.0", features = [ "metrics", "trace"] }
1212
opentelemetry_sdk = { version = "0.22.1", features = ["rt-tokio"] }
13-
opentelemetry-otlp = { version = "0.15.0", default_features=false, features = ["http-proto", "trace", "http", "reqwest-client", "metrics"] }
13+
opentelemetry-otlp = { version = "0.15.0", default_features=false, features = ["http-proto", "trace", "http", "reqwest-client", "metrics", "grpc-tonic"] }
1414
opentelemetry-semantic-conventions = "0.14.0"
1515
tracing = { version = "0.1.37", features = ["log"] }
1616
tracing-appender = "0.2.2"

crates/telemetry/src/env.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/// Returns a boolean indicating if the OTEL layer should be enabled.
2+
///
3+
/// It is considered enabled if any of the following environment variables are set and not empty:
4+
/// - `OTEL_EXPORTER_OTLP_ENDPOINT`
5+
/// - `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT`
6+
/// - `OTEL_EXPORTER_OTLP_METRICS_ENDPOINT`
7+
///
8+
/// Note that this is overridden if OTEL_SDK_DISABLED is set and not empty.
9+
pub(crate) fn otel_enabled() -> bool {
10+
const ENABLING_VARS: &[&str] = &[
11+
"OTEL_EXPORTER_OTLP_ENDPOINT",
12+
"OTEL_EXPORTER_OTLP_TRACES_ENDPOINT",
13+
"OTEL_EXPORTER_OTLP_METRICS_ENDPOINT",
14+
];
15+
ENABLING_VARS
16+
.iter()
17+
.any(|key| std::env::var_os(key).is_some_and(|val| !val.is_empty()))
18+
}
19+
20+
/// Returns a boolean indicating if the OTEL SDK should be disabled for all signals.
21+
///
22+
/// It is considered disabled if the environment variable `OTEL_SDK_DISABLED` is set and not empty.
23+
pub(crate) fn otel_sdk_disabled() -> bool {
24+
std::env::var_os("OTEL_SDK_DISABLED").is_some_and(|val| !val.is_empty())
25+
}
26+
27+
/// The protocol to use for OTLP exporter.
28+
pub(crate) enum OtlpProtocol {
29+
Grpc,
30+
HttpProtobuf,
31+
HttpJson,
32+
}
33+
34+
impl OtlpProtocol {
35+
/// Returns the protocol to be used for exporting traces as defined by the environment.
36+
pub(crate) fn traces_protocol_from_env() -> Self {
37+
let trace_protocol = std::env::var("OTEL_EXPORTER_OTLP_TRACES_PROTOCOL");
38+
let general_protocol = std::env::var("OTEL_EXPORTER_OTLP_PROTOCOL");
39+
let protocol = trace_protocol.unwrap_or(general_protocol.unwrap_or_default());
40+
41+
match protocol.as_str() {
42+
"grpc" => Self::Grpc,
43+
"http/protobuf" => Self::HttpProtobuf,
44+
"http/json" => Self::HttpJson,
45+
_ => Self::HttpProtobuf,
46+
}
47+
}
48+
}

crates/telemetry/src/lib.rs

Lines changed: 3 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
use std::io::IsTerminal;
22

3+
use env::otel_enabled;
4+
use env::otel_sdk_disabled;
35
use opentelemetry_sdk::propagation::TraceContextPropagator;
46
use tracing_subscriber::{fmt, prelude::*, registry, EnvFilter, Layer};
57

68
pub mod detector;
9+
mod env;
710
mod propagation;
811
mod traces;
912

@@ -48,32 +51,6 @@ pub fn init(spin_version: String) -> anyhow::Result<ShutdownGuard> {
4851
Ok(ShutdownGuard)
4952
}
5053

51-
/// Returns a boolean indicating if the OTEL layer should be enabled.
52-
///
53-
/// It is considered enabled if any of the following environment variables are set and not empty:
54-
/// - `OTEL_EXPORTER_OTLP_ENDPOINT`
55-
/// - `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT`
56-
/// - `OTEL_EXPORTER_OTLP_METRICS_ENDPOINT`
57-
///
58-
/// Note that this is overridden if OTEL_SDK_DISABLED is set and not empty.
59-
fn otel_enabled() -> bool {
60-
const ENABLING_VARS: &[&str] = &[
61-
"OTEL_EXPORTER_OTLP_ENDPOINT",
62-
"OTEL_EXPORTER_OTLP_TRACES_ENDPOINT",
63-
"OTEL_EXPORTER_OTLP_METRICS_ENDPOINT",
64-
];
65-
ENABLING_VARS
66-
.iter()
67-
.any(|key| std::env::var_os(key).is_some_and(|val| !val.is_empty()))
68-
}
69-
70-
/// Returns a boolean indicating if the OTEL SDK should be disabled for all signals.
71-
///
72-
/// It is considered disabled if the environment variable `OTEL_SDK_DISABLED` is set and not empty.
73-
fn otel_sdk_disabled() -> bool {
74-
std::env::var_os("OTEL_SDK_DISABLED").is_some_and(|val| !val.is_empty())
75-
}
76-
7754
fn otel_error_handler(err: opentelemetry::global::Error) {
7855
static FIRST_OTEL_ERROR: std::sync::Once = std::sync::Once::new();
7956
FIRST_OTEL_ERROR.call_once(|| {

crates/telemetry/src/traces.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use std::time::Duration;
22

3-
use opentelemetry_otlp::WithExportConfig;
3+
use anyhow::bail;
4+
use opentelemetry_otlp::{SpanExporterBuilder, WithExportConfig};
45
use opentelemetry_otlp::{OTEL_EXPORTER_OTLP_ENDPOINT, OTEL_EXPORTER_OTLP_TRACES_ENDPOINT};
56
use opentelemetry_sdk::{
67
resource::{EnvResourceDetector, TelemetryResourceDetector},
@@ -11,6 +12,7 @@ use tracing_opentelemetry::OpenTelemetryLayer;
1112
use tracing_subscriber::{EnvFilter, Layer, Registry};
1213

1314
use crate::detector::SpinResourceDetector;
15+
use crate::env::OtlpProtocol;
1416

1517
/// Constructs a layer for the tracing subscriber that sends spans to an OTEL collector.
1618
///
@@ -39,9 +41,17 @@ pub(crate) fn otel_tracing_layer(
3941
// currently default to using the HTTP exporter but in the future we could select off of the
4042
// combination of OTEL_EXPORTER_OTLP_PROTOCOL and OTEL_EXPORTER_OTLP_TRACES_PROTOCOL to
4143
// determine whether we should use http/protobuf or grpc.
42-
let mut exporter = opentelemetry_otlp::new_exporter().http();
44+
let mut exporter: SpanExporterBuilder = match OtlpProtocol::traces_protocol_from_env() {
45+
OtlpProtocol::Grpc => opentelemetry_otlp::new_exporter().tonic().into(),
46+
OtlpProtocol::HttpProtobuf => opentelemetry_otlp::new_exporter().http().into(),
47+
OtlpProtocol::HttpJson => bail!("http/json OTLP protocol is not supported"),
48+
};
4349
if let Some(endpoint) = fix_endpoint_bug() {
44-
exporter = exporter.with_endpoint(endpoint);
50+
match exporter {
51+
SpanExporterBuilder::Tonic(inner) => exporter = inner.with_endpoint(endpoint).into(),
52+
SpanExporterBuilder::Http(inner) => exporter = inner.with_endpoint(endpoint).into(),
53+
_ => {}
54+
}
4555
}
4656

4757
let tracer = opentelemetry_otlp::new_pipeline()

0 commit comments

Comments
 (0)