Skip to content

Commit 1eaa485

Browse files
committed
Merge remote-tracking branch 'origin/main' into reexport-tracing
# Conflicts: # opentelemetry-sdk/Cargo.toml
2 parents 9b8f146 + 99cb67d commit 1eaa485

File tree

32 files changed

+313
-129
lines changed

32 files changed

+313
-129
lines changed

.cspell.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@
4242
"Dwarnings",
4343
"EPYC",
4444
"flamegraph",
45+
"Gerring",
46+
"Grübel",
4547
"hasher",
4648
"Isobel",
4749
"jaegertracing",

.github/workflows/benchmark.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,5 +56,5 @@ jobs:
5656
- uses: boa-dev/criterion-compare-action@v3
5757
with:
5858
cwd: opentelemetry-sdk
59-
features: rt-tokio,testing,metrics,logs,spec_unstable_metrics_views
59+
features: testing,metrics,logs,spec_unstable_metrics_views,spec_unstable_logs_enabled,experimental_logs_concurrent_log_processor
6060
branchName: ${{ env.BRANCH_NAME }}

.github/workflows/ci.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,10 @@ jobs:
5858
submodules: true
5959
- uses: dtolnay/rust-toolchain@stable
6060
with:
61-
components: rustfmt
61+
components: rustfmt, clippy
62+
- uses: taiki-e/install-action@v2
63+
with:
64+
tool: cargo-hack
6265
- uses: arduino/setup-protoc@v3
6366
with:
6467
repo-token: ${{ secrets.GITHUB_TOKEN }}

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ you're more than welcome to participate!
187187

188188
### Approvers
189189

190+
* [Anton Grübel](https://github.com/gruebel), Baz
190191
* [Shaun Cox](https://github.com/shaun-cox), Microsoft
191192
* [Scott Gerring](https://github.com/scottgerring), Datadog
192193

docs/design/logs.md

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,25 @@ only meant for OTel components itself and anyone writing extensions like custom
345345
Exporters etc.
346346

347347
// TODO: Document the principles followed when selecting severity for internal
348-
logs // TODO: Document how this can cause circular loop and plans to address it.
348+
logs
349+
350+
When OpenTelemetry components generate logs that could potentially feed back
351+
into OpenTelemetry, this can result in what is known as "telemetry-induced
352+
telemetry." To address this, OpenTelemetry provides a mechanism to suppress such
353+
telemetry using the `Context`. Components are expected to mark telemetry as
354+
suppressed within a specific `Context` by invoking
355+
`Context::enter_telemetry_suppressed_scope()`. The Logs SDK implementation
356+
checks this flag in the current `Context` and ignores logs if suppression is
357+
enabled.
358+
359+
This mechanism relies on proper in-process propagation of the `Context`.
360+
However, external libraries like `hyper` and `tonic`, which are used by
361+
OpenTelemetry in its OTLP Exporters, do not propagate OpenTelemetry's `Context`.
362+
As a result, the suppression mechanism does not work out-of-the-box to suppress
363+
logs originating from these libraries.
364+
365+
// TODO: Document how OTLP can solve this issue without asking external
366+
crates to respect and propagate OTel Context.
349367

350368
## Summary
351369

examples/logs-basic/src/main.rs

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,21 @@ fn main() {
1515
.with_simple_exporter(exporter)
1616
.build();
1717

18-
// For the OpenTelemetry layer, add a tracing filter to filter events from
19-
// OpenTelemetry and its dependent crates (opentelemetry-otlp uses crates
20-
// like reqwest/tonic etc.) from being sent back to OTel itself, thus
21-
// preventing infinite telemetry generation. The filter levels are set as
22-
// follows:
18+
// To prevent a telemetry-induced-telemetry loop, OpenTelemetry's own internal
19+
// logging is properly suppressed. However, logs emitted by external components
20+
// (such as reqwest, tonic, etc.) are not suppressed as they do not propagate
21+
// OpenTelemetry context. Until this issue is addressed
22+
// (https://github.com/open-telemetry/opentelemetry-rust/issues/2877),
23+
// filtering like this is the best way to suppress such logs.
24+
//
25+
// The filter levels are set as follows:
2326
// - Allow `info` level and above by default.
24-
// - Restrict `opentelemetry`, `hyper`, `tonic`, and `reqwest` completely.
25-
// Note: This will also drop events from crates like `tonic` etc. even when
26-
// they are used outside the OTLP Exporter. For more details, see:
27-
// https://github.com/open-telemetry/opentelemetry-rust/issues/761
27+
// - Completely restrict logs from `hyper`, `tonic`, `h2`, and `reqwest`.
28+
//
29+
// Note: This filtering will also drop logs from these components even when
30+
// they are used outside of the OTLP Exporter.
2831
let filter_otel = EnvFilter::new("info")
2932
.add_directive("hyper=off".parse().unwrap())
30-
.add_directive("opentelemetry=off".parse().unwrap())
3133
.add_directive("tonic=off".parse().unwrap())
3234
.add_directive("h2=off".parse().unwrap())
3335
.add_directive("reqwest=off".parse().unwrap());

examples/tracing-grpc/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ opentelemetry_sdk = { path = "../../opentelemetry-sdk", features = ["rt-tokio"]
2222
opentelemetry-stdout = { workspace = true, features = ["trace"] }
2323
prost = { workspace = true }
2424
tokio = { workspace = true, features = ["full"] }
25-
tonic = { workspace = true, features = ["server", "codegen", "channel", "prost"] }
25+
tonic = { workspace = true, features = ["server", "codegen", "channel", "prost", "router"] }
2626

2727
[build-dependencies]
2828
tonic-build = { workspace = true }

opentelemetry-appender-tracing/examples/basic.rs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,19 @@ fn main() {
1616
.with_simple_exporter(exporter)
1717
.build();
1818

19-
// For the OpenTelemetry layer, add a tracing filter to filter events from
20-
// OpenTelemetry and its dependent crates (opentelemetry-otlp uses crates
21-
// like reqwest/tonic etc.) from being sent back to OTel itself, thus
22-
// preventing infinite telemetry generation. The filter levels are set as
23-
// follows:
19+
// To prevent a telemetry-induced-telemetry loop, OpenTelemetry's own internal
20+
// logging is properly suppressed. However, logs emitted by external components
21+
// (such as reqwest, tonic, etc.) are not suppressed as they do not propagate
22+
// OpenTelemetry context. Until this issue is addressed
23+
// (https://github.com/open-telemetry/opentelemetry-rust/issues/2877),
24+
// filtering like this is the best way to suppress such logs.
25+
//
26+
// The filter levels are set as follows:
2427
// - Allow `info` level and above by default.
25-
// - Restrict `opentelemetry`, `hyper`, `tonic`, and `reqwest` completely.
26-
// Note: This will also drop events from crates like `tonic` etc. even when
27-
// they are used outside the OTLP Exporter. For more details, see:
28-
// https://github.com/open-telemetry/opentelemetry-rust/issues/761
28+
// - Completely restrict logs from `hyper`, `tonic`, `h2`, and `reqwest`.
29+
//
30+
// Note: This filtering will also drop logs from these components even when
31+
// they are used outside of the OTLP Exporter.
2932
let filter_otel = EnvFilter::new("info")
3033
.add_directive("hyper=off".parse().unwrap())
3134
.add_directive("opentelemetry=off".parse().unwrap())

opentelemetry-appender-tracing/src/layer.rs

Lines changed: 2 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -289,13 +289,11 @@ mod tests {
289289
use opentelemetry::{logs::AnyValue, Key};
290290
use opentelemetry_sdk::error::{OTelSdkError, OTelSdkResult};
291291
use opentelemetry_sdk::logs::{InMemoryLogExporter, LogProcessor};
292-
use opentelemetry_sdk::logs::{LogBatch, LogExporter};
293292
use opentelemetry_sdk::logs::{SdkLogRecord, SdkLoggerProvider};
294293
use opentelemetry_sdk::trace::{Sampler, SdkTracerProvider};
295-
use tracing::{error, warn};
294+
use tracing::error;
296295
use tracing_subscriber::prelude::__tracing_subscriber_SubscriberExt;
297-
use tracing_subscriber::util::SubscriberInitExt;
298-
use tracing_subscriber::{EnvFilter, Layer};
296+
use tracing_subscriber::Layer;
299297

300298
pub fn attributes_contains(log_record: &SdkLogRecord, key: &Key, value: &AnyValue) -> bool {
301299
log_record
@@ -313,69 +311,6 @@ mod tests {
313311
}
314312

315313
// cargo test --features=testing
316-
317-
#[derive(Clone, Debug, Default)]
318-
struct ReentrantLogExporter;
319-
320-
impl LogExporter for ReentrantLogExporter {
321-
async fn export(&self, _batch: LogBatch<'_>) -> OTelSdkResult {
322-
// This will cause a deadlock as the export itself creates a log
323-
// while still within the lock of the SimpleLogProcessor.
324-
warn!(name: "my-event-name", target: "reentrant", event_id = 20, user_name = "otel", user_email = "[email protected]");
325-
Ok(())
326-
}
327-
}
328-
329-
#[test]
330-
#[ignore = "See issue: https://github.com/open-telemetry/opentelemetry-rust/issues/1745"]
331-
fn simple_processor_deadlock() {
332-
let exporter: ReentrantLogExporter = ReentrantLogExporter;
333-
let logger_provider = SdkLoggerProvider::builder()
334-
.with_simple_exporter(exporter.clone())
335-
.build();
336-
337-
let layer = layer::OpenTelemetryTracingBridge::new(&logger_provider);
338-
339-
// Setting subscriber as global as that is the only way to test this scenario.
340-
tracing_subscriber::registry().with(layer).init();
341-
warn!(name: "my-event-name", target: "my-system", event_id = 20, user_name = "otel", user_email = "[email protected]");
342-
}
343-
344-
#[test]
345-
#[ignore = "While this test runs fine, this uses global subscriber and does not play well with other tests."]
346-
fn simple_processor_no_deadlock() {
347-
let exporter: ReentrantLogExporter = ReentrantLogExporter;
348-
let logger_provider = SdkLoggerProvider::builder()
349-
.with_simple_exporter(exporter.clone())
350-
.build();
351-
352-
let layer = layer::OpenTelemetryTracingBridge::new(&logger_provider);
353-
354-
// This filter will prevent the deadlock as the reentrant log will be
355-
// ignored.
356-
let filter = EnvFilter::new("debug").add_directive("reentrant=error".parse().unwrap());
357-
// Setting subscriber as global as that is the only way to test this scenario.
358-
tracing_subscriber::registry()
359-
.with(filter)
360-
.with(layer)
361-
.init();
362-
warn!(name: "my-event-name", target: "my-system", event_id = 20, user_name = "otel", user_email = "[email protected]");
363-
}
364-
365-
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
366-
#[ignore = "While this test runs fine, this uses global subscriber and does not play well with other tests."]
367-
async fn batch_processor_no_deadlock() {
368-
let exporter: ReentrantLogExporter = ReentrantLogExporter;
369-
let logger_provider = SdkLoggerProvider::builder()
370-
.with_batch_exporter(exporter.clone())
371-
.build();
372-
373-
let layer = layer::OpenTelemetryTracingBridge::new(&logger_provider);
374-
375-
tracing_subscriber::registry().with(layer).init();
376-
warn!(name: "my-event-name", target: "my-system", event_id = 20, user_name = "otel", user_email = "[email protected]");
377-
}
378-
379314
#[test]
380315
fn tracing_appender_standalone() {
381316
// Arrange

opentelemetry-otlp/examples/basic-otlp-http/src/main.rs

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -72,19 +72,21 @@ async fn main() -> Result<(), Box<dyn Error + Send + Sync + 'static>> {
7272
// Create a new OpenTelemetryTracingBridge using the above LoggerProvider.
7373
let otel_layer = OpenTelemetryTracingBridge::new(&logger_provider);
7474

75-
// For the OpenTelemetry layer, add a tracing filter to filter events from
76-
// OpenTelemetry and its dependent crates (opentelemetry-otlp uses crates
77-
// like reqwest/tonic etc.) from being sent back to OTel itself, thus
78-
// preventing infinite telemetry generation. The filter levels are set as
79-
// follows:
75+
// To prevent a telemetry-induced-telemetry loop, OpenTelemetry's own internal
76+
// logging is properly suppressed. However, logs emitted by external components
77+
// (such as reqwest, tonic, etc.) are not suppressed as they do not propagate
78+
// OpenTelemetry context. Until this issue is addressed
79+
// (https://github.com/open-telemetry/opentelemetry-rust/issues/2877),
80+
// filtering like this is the best way to suppress such logs.
81+
//
82+
// The filter levels are set as follows:
8083
// - Allow `info` level and above by default.
81-
// - Restrict `opentelemetry`, `hyper`, `tonic`, and `reqwest` completely.
82-
// Note: This will also drop events from crates like `tonic` etc. even when
83-
// they are used outside the OTLP Exporter. For more details, see:
84-
// https://github.com/open-telemetry/opentelemetry-rust/issues/761
84+
// - Completely restrict logs from `hyper`, `tonic`, `h2`, and `reqwest`.
85+
//
86+
// Note: This filtering will also drop logs from these components even when
87+
// they are used outside of the OTLP Exporter.
8588
let filter_otel = EnvFilter::new("info")
8689
.add_directive("hyper=off".parse().unwrap())
87-
.add_directive("opentelemetry=off".parse().unwrap())
8890
.add_directive("tonic=off".parse().unwrap())
8991
.add_directive("h2=off".parse().unwrap())
9092
.add_directive("reqwest=off".parse().unwrap());

0 commit comments

Comments
 (0)