Skip to content

Commit f9608c4

Browse files
authored
Merge branch 'main' into fix/blocking-strategy-deadlock
2 parents 5404c60 + 9650783 commit f9608c4

12 files changed

Lines changed: 350 additions & 59 deletions

File tree

.github/workflows/benchmark.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ jobs:
6464
name: continuous benchmark tracking
6565
if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
6666
# Use bare-metal runner on the upstream repo for consistent results; fall back to shared runners elsewhere
67-
runs-on: ${{ github.repository == 'open-telemetry/opentelemetry-rust' && 'oracle-bare-metal-64cpu-512gb-x86-64' || 'ubuntu-latest' }}
67+
runs-on: ${{ github.repository == 'open-telemetry/opentelemetry-rust' && 'oracle-bare-metal-64cpu-1024gb-x86-64-ubuntu-24' || 'ubuntu-latest' }}
6868
permissions:
6969
contents: write
7070
container:

opentelemetry-appender-tracing/src/layer.rs

Lines changed: 48 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1077,8 +1077,14 @@ mod tests {
10771077
.with_simple_exporter(exporter.clone())
10781078
.build();
10791079

1080-
let level_filter = tracing_subscriber::filter::LevelFilter::INFO;
1081-
let layer = layer::OpenTelemetryTracingBridge::new(&provider).with_filter(level_filter);
1080+
let layer = layer::OpenTelemetryTracingBridge::new(&provider).with_filter(
1081+
tracing_subscriber::filter::filter_fn(|meta| {
1082+
// Allow spans at any level (needed for on_new_span to store span attributes),
1083+
// but only allow ERROR events to prevent internal otel_info! events from leaking
1084+
// in when internal-logs feature is enabled and tests run in parallel.
1085+
meta.is_span() || *meta.level() <= tracing::Level::ERROR
1086+
}),
1087+
);
10821088
let subscriber = tracing_subscriber::registry().with(layer);
10831089
let _guard = tracing::subscriber::set_default(subscriber);
10841090

@@ -1122,8 +1128,14 @@ mod tests {
11221128
.with_simple_exporter(exporter.clone())
11231129
.build();
11241130

1125-
let level_filter = tracing_subscriber::filter::LevelFilter::INFO;
1126-
let layer = layer::OpenTelemetryTracingBridge::new(&provider).with_filter(level_filter);
1131+
let layer = layer::OpenTelemetryTracingBridge::new(&provider).with_filter(
1132+
tracing_subscriber::filter::filter_fn(|meta| {
1133+
// Allow spans at any level (needed for on_new_span to store span attributes),
1134+
// but only allow ERROR events to prevent internal otel_info! events from leaking
1135+
// in when internal-logs feature is enabled and tests run in parallel.
1136+
meta.is_span() || *meta.level() <= tracing::Level::ERROR
1137+
}),
1138+
);
11271139
let subscriber = tracing_subscriber::registry().with(layer);
11281140
let _guard = tracing::subscriber::set_default(subscriber);
11291141

@@ -1177,8 +1189,14 @@ mod tests {
11771189
.with_simple_exporter(exporter.clone())
11781190
.build();
11791191

1180-
let level_filter = tracing_subscriber::filter::LevelFilter::INFO;
1181-
let layer = layer::OpenTelemetryTracingBridge::new(&provider).with_filter(level_filter);
1192+
let layer = layer::OpenTelemetryTracingBridge::new(&provider).with_filter(
1193+
tracing_subscriber::filter::filter_fn(|meta| {
1194+
// Allow spans at any level (needed for on_new_span to store span attributes),
1195+
// but only allow ERROR events to prevent internal otel_info! events from leaking
1196+
// in when internal-logs feature is enabled and tests run in parallel.
1197+
meta.is_span() || *meta.level() <= tracing::Level::ERROR
1198+
}),
1199+
);
11821200
let subscriber = tracing_subscriber::registry().with(layer);
11831201
let _guard = tracing::subscriber::set_default(subscriber);
11841202

@@ -1283,8 +1301,14 @@ mod tests {
12831301
.with_simple_exporter(exporter.clone())
12841302
.build();
12851303

1286-
let level_filter = tracing_subscriber::filter::LevelFilter::INFO;
1287-
let layer = layer::OpenTelemetryTracingBridge::new(&provider).with_filter(level_filter);
1304+
let layer = layer::OpenTelemetryTracingBridge::new(&provider).with_filter(
1305+
tracing_subscriber::filter::filter_fn(|meta| {
1306+
// Allow spans at any level (needed for on_new_span to store span attributes),
1307+
// but only allow ERROR events to prevent internal otel_info! events from leaking
1308+
// in when internal-logs feature is enabled and tests run in parallel.
1309+
meta.is_span() || *meta.level() <= tracing::Level::ERROR
1310+
}),
1311+
);
12881312
let subscriber = tracing_subscriber::registry().with(layer);
12891313
let _guard = tracing::subscriber::set_default(subscriber);
12901314

@@ -1343,7 +1367,10 @@ mod tests {
13431367

13441368
let layer = layer::OpenTelemetryTracingBridge::builder(&provider)
13451369
.with_span_attribute_allowlist(["session.id"])
1346-
.build();
1370+
.build()
1371+
.with_filter(tracing_subscriber::filter::filter_fn(|meta| {
1372+
meta.is_span() || *meta.level() <= tracing::Level::ERROR
1373+
}));
13471374
let subscriber = tracing_subscriber::registry().with(layer);
13481375
let _guard = tracing::subscriber::set_default(subscriber);
13491376

@@ -1377,7 +1404,10 @@ mod tests {
13771404

13781405
let layer = layer::OpenTelemetryTracingBridge::builder(&provider)
13791406
.with_span_attribute_allowlist(["session.id"])
1380-
.build();
1407+
.build()
1408+
.with_filter(tracing_subscriber::filter::filter_fn(|meta| {
1409+
meta.is_span() || *meta.level() <= tracing::Level::ERROR
1410+
}));
13811411
let subscriber = tracing_subscriber::registry().with(layer);
13821412
let _guard = tracing::subscriber::set_default(subscriber);
13831413

@@ -1421,7 +1451,10 @@ mod tests {
14211451

14221452
let layer = layer::OpenTelemetryTracingBridge::builder(&provider)
14231453
.with_span_attribute_allowlist(std::iter::empty::<&str>())
1424-
.build();
1454+
.build()
1455+
.with_filter(tracing_subscriber::filter::filter_fn(|meta| {
1456+
meta.is_span() || *meta.level() <= tracing::Level::ERROR
1457+
}));
14251458
let subscriber = tracing_subscriber::registry().with(layer);
14261459
let _guard = tracing::subscriber::set_default(subscriber);
14271460

@@ -1456,7 +1489,10 @@ mod tests {
14561489

14571490
let layer = layer::OpenTelemetryTracingBridge::builder(&provider)
14581491
.with_span_attribute_allowlist(["session.id"])
1459-
.build();
1492+
.build()
1493+
.with_filter(tracing_subscriber::filter::filter_fn(|meta| {
1494+
meta.is_span() || *meta.level() <= tracing::Level::ERROR
1495+
}));
14601496
let subscriber = tracing_subscriber::registry().with(layer);
14611497
let _guard = tracing::subscriber::set_default(subscriber);
14621498

opentelemetry-otlp/CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
## vNext
44

5+
- Add `tls-provider-agnostic` feature flag for environments that require a custom crypto backend (e.g., OpenSSL for FIPS compliance). Enables TLS code paths without bundling `ring` or `aws-lc-rs`.
56
- Add `build()` directly on `SpanExporterBuilder`, `MetricExporterBuilder`, and `LogExporterBuilder`
67
(before selecting a transport), which auto-selects the transport based on the
78
`OTEL_EXPORTER_OTLP_PROTOCOL` environment variable or enabled features.
@@ -13,6 +14,12 @@
1314
silently sending unencrypted traffic. When a TLS feature is enabled and an `https://` endpoint is used without
1415
an explicit `.with_tls_config()`, a default `ClientTlsConfig` is automatically applied.
1516
[#3182](https://github.com/open-telemetry/opentelemetry-rust/issues/3182)
17+
- Prevent auth tokens from leaking in export error messages. gRPC and HTTP
18+
exporter errors no longer include potentially sensitive server responses
19+
(e.g., authentication tokens echoed back). Error messages returned to SDK
20+
processors contain only the gRPC status code or HTTP status code. Full
21+
details are logged at DEBUG level only.
22+
[#3021](https://github.com/open-telemetry/opentelemetry-rust/issues/3021)
1623
- Add support for `OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE` environment variable
1724
to configure metrics temporality. Accepted values: `cumulative` (default), `delta`,
1825
`lowmemory` (case-insensitive). Programmatic `.with_temporality()` overrides the env var.

opentelemetry-otlp/Cargo.toml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,13 @@ experimental-grpc-retry = ["grpc-tonic", "opentelemetry_sdk/experimental_async_r
8080
# http compression
8181
gzip-http = ["flate2"]
8282
zstd-http = ["zstd"]
83-
tls = ["tls-ring"] # Deprecated: use tls-ring or tls-aws-lc.
83+
tls = ["tls-ring"] # Deprecated: use tls-ring or tls-aws-lc or tls-provider-agnostic
8484
tls-ring = ["tonic/tls-ring"]
8585
tls-aws-lc = ["tonic/tls-aws-lc"]
86+
# Provider-agnostic TLS: enables TLS code paths without bundling a specific
87+
# crypto provider. Use this when you install a
88+
# CryptoProvider globally (e.g., via rustls-openssl for FIPS/OpenSSL environments).
89+
tls-provider-agnostic = ["tonic/_tls-any"]
8690
tls-roots = ["tonic/tls-native-roots"]
8791
tls-webpki-roots = ["tonic/tls-webpki-roots"]
8892

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

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -490,7 +490,17 @@ impl OtlpHttpClient {
490490

491491
// Send request
492492
let response = client.send_bytes(request).await.map_err(|e| {
493-
HttpExportError::new(0, format!("Network error: {e:?}")) // Network error
493+
// Connection errors (e.g., "Connection refused", DNS failures) typically
494+
// indicate user-side misconfigurations and don't contain sensitive data.
495+
// We don't log at WARN here because SDK processors (BatchLogProcessor,
496+
// BatchSpanProcessor, PeriodicReader) already log the returned error
497+
// via otel_error!.
498+
otel_debug!(
499+
name: "HttpClient.NetworkError",
500+
url = request_uri.as_str(),
501+
error = format!("{e}")
502+
);
503+
HttpExportError::new(0, "HTTP export failed: network error".to_string())
494504
})?;
495505

496506
let status_code = response.status().as_u16();
@@ -501,12 +511,18 @@ impl OtlpHttpClient {
501511
.map(|s| s.to_string());
502512

503513
if !response.status().is_success() {
504-
let message = format!(
505-
"HTTP export failed. Url: {}, Status: {}, Response: {:?}",
506-
request_uri,
507-
status_code,
508-
response.body()
514+
// We don't log at WARN here because SDK processors (BatchLogProcessor,
515+
// BatchSpanProcessor, PeriodicReader) already log the returned error
516+
// via otel_error!. Response body may contain sensitive information
517+
// (e.g., auth tokens echoed back by the server), so log it at DEBUG
518+
// level only.
519+
otel_debug!(
520+
name: "HttpClient.StatusError",
521+
status_code = status_code,
522+
url = request_uri.as_str(),
523+
response_body = format!("{:?}", response.body())
509524
);
525+
let message = format!("HTTP export failed with status code: {status_code}");
510526
return Err(match retry_after {
511527
Some(retry_after) => {
512528
HttpExportError::with_retry_after(status_code, retry_after, message)

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

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,7 @@ impl LogExporter for TonicLogsClient {
9494
.interceptor
9595
.call(Request::new(()))
9696
.map_err(|e| {
97-
// Convert interceptor errors to tonic::Status for retry classification
98-
tonic::Status::internal(format!("interceptor error: {e:?}"))
97+
super::handle_interceptor_error!("TonicLogsClient", e)
9998
})?
10099
.into_parts();
101100
Ok((inner.client.clone(), m, e))
@@ -137,9 +136,9 @@ impl LogExporter for TonicLogsClient {
137136
.await
138137
{
139138
Ok(_) => Ok(()),
140-
Err(tonic_status) => Err(OTelSdkError::InternalFailure(format!(
141-
"export error: {tonic_status:?}"
142-
))),
139+
Err(tonic_status) => {
140+
super::handle_tonic_export_error!("TonicLogsClient", tonic_status)
141+
}
143142
}
144143
}
145144

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

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,7 @@ impl MetricsClient for TonicMetricsClient {
8585
.interceptor
8686
.call(Request::new(()))
8787
.map_err(|e| {
88-
tonic::Status::internal(format!(
89-
"unexpected status while exporting {e:?}"
90-
))
88+
super::handle_interceptor_error!("TonicMetricsClient", e)
9189
})?
9290
.into_parts();
9391
Ok((inner.client.clone(), m, e))
@@ -127,9 +125,9 @@ impl MetricsClient for TonicMetricsClient {
127125
.await
128126
{
129127
Ok(_) => Ok(()),
130-
Err(tonic_status) => Err(OTelSdkError::InternalFailure(format!(
131-
"export error: {tonic_status:?}"
132-
))),
128+
Err(tonic_status) => {
129+
super::handle_tonic_export_error!("TonicMetricsClient", tonic_status)
130+
}
133131
}
134132
}
135133

0 commit comments

Comments
 (0)