From 55a256b90ce3c0a71de93ae9a14f697dce43054a Mon Sep 17 00:00:00 2001 From: Tyler Rockwood Date: Thu, 6 Aug 2026 14:24:25 -0500 Subject: [PATCH] Update OpenTelemetry integration to 0.32 tracing-stackdriver's optional Cloud Trace correlation still depends on OpenTelemetry 0.22 and tracing-opentelemetry 0.23. Applications using the current 0.32/0.33 stack therefore cannot enable correlation without compiling two incompatible telemetry type universes. Move the optional integration to OpenTelemetry 0.32 and tracing-opentelemetry 0.33, and bump the crate version to 0.11. The newer tracing-opentelemetry release makes its internal OtelData private, so retain a weak reference to the registered Dispatch and use the public get_otel_context API to resolve the exact event parent span. The weak reference avoids a subscriber reference cycle and preserves explicit-parent and nested-span behavior. Update the OpenTelemetry test provider and ID constructors for the current APIs. Also register the existing tracing_unstable cfg so current Rust releases do not warn about the crate's valuable integration gates. Verified with cargo test, cargo test --features opentelemetry, and cargo clippy --features opentelemetry -- -D warnings with allowances for two pre-existing writer lints. --- Cargo.lock | 314 +++++++++++++++++++++++------------------ Cargo.toml | 15 +- src/event_formatter.rs | 61 ++++---- src/layer.rs | 81 +++++++---- tests/opentelemetry.rs | 12 +- 5 files changed, 280 insertions(+), 203 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1e02337..5cb3f82 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "Inflector" @@ -21,17 +21,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "async-trait" -version = "0.1.73" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.37", -] - [[package]] name = "autocfg" version = "1.1.0" @@ -65,33 +54,13 @@ dependencies = [ "num-traits", ] -[[package]] -name = "crossbeam-channel" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" -dependencies = [ - "cfg-if", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" -dependencies = [ - "cfg-if", -] - [[package]] name = "deranged" -version = "0.3.10" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eb30d70a07a3b04884d2677f06bec33509dc67ca60d92949e5535352d3191dc" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" dependencies = [ - "powerfmt", - "serde", + "serde_core", ] [[package]] @@ -185,10 +154,16 @@ dependencies = [ ] [[package]] -name = "glob" -version = "0.3.1" +name = "getrandom" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasip2", +] [[package]] name = "http" @@ -234,9 +209,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.148" +version = "0.2.189" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" +checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" [[package]] name = "log" @@ -252,14 +227,19 @@ checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c" [[package]] name = "nu-ansi-term" -version = "0.46.0" +version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "overload", - "winapi", + "windows-sys", ] +[[package]] +name = "num-conv" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" + [[package]] name = "num-traits" version = "0.2.16" @@ -277,69 +257,45 @@ checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" [[package]] name = "opentelemetry" -version = "0.22.0" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "900d57987be3f2aeb70d385fff9b27fb74c5723cc9a52d904d4f9c807a0667bf" +checksum = "b0142c63252a9e054e68a4c61a5778f7b14f576274d593f8ce883d191a099682" dependencies = [ "futures-core", "futures-sink", "js-sys", - "once_cell", "pin-project-lite", - "thiserror", - "urlencoding", + "thiserror 2.0.19", + "tracing", ] [[package]] name = "opentelemetry-stdout" -version = "0.3.0" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bdf28b381f23afcd150afc0b38a4183dd321fc96320c1554752b6b761648f78" +checksum = "a1b1c6a247d79091f0062a5f4bd058589525cf987a8d4c169440d9c1be72f0ad" dependencies = [ "chrono", - "futures-util", "opentelemetry", "opentelemetry_sdk", - "ordered-float", - "serde", - "serde_json", ] [[package]] name = "opentelemetry_sdk" -version = "0.22.1" +version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e90c7113be649e31e9a0f8b5ee24ed7a16923b322c3c5ab6367469c049d6b7e" +checksum = "9b59f80e1ac4d5ff7a2db8fb6c80badb7f0f3f858211fba08dd9aaec750894f9" dependencies = [ - "async-trait", - "crossbeam-channel", "futures-channel", "futures-executor", "futures-util", - "glob", - "once_cell", "opentelemetry", - "ordered-float", "percent-encoding", - "rand", - "thiserror", -] - -[[package]] -name = "ordered-float" -version = "4.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a76df7075c7d4d01fdcb46c912dd17fba5b60c78ea480b475f2b6ab6f666584e" -dependencies = [ - "num-traits", + "portable-atomic", + "rand 0.9.5", + "thiserror 2.0.19", ] -[[package]] -name = "overload" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" - [[package]] name = "percent-encoding" version = "2.3.1" @@ -358,6 +314,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "portable-atomic" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d20d5497ef88037a52ff98267d066e7f11fcc5e99bbfbd58a42336193aacec3" + [[package]] name = "powerfmt" version = "0.2.0" @@ -372,22 +334,28 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro2" -version = "1.0.67" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" +checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.33" +version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001" dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + [[package]] name = "rand" version = "0.8.5" @@ -395,8 +363,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha", - "rand_core", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9ef1d0d795eb7d84685bca4f72f3649f064e6641543d3a8c415898726a57b41" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.5", ] [[package]] @@ -406,7 +384,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.5", ] [[package]] @@ -415,7 +403,16 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom", + "getrandom 0.2.10", +] + +[[package]] +name = "rand_core" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" +dependencies = [ + "getrandom 0.3.4", ] [[package]] @@ -455,22 +452,32 @@ checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" [[package]] name = "serde" -version = "1.0.193" +version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.193" +version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 3.0.3", ] [[package]] @@ -530,13 +537,33 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "syn" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "thiserror" version = "1.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d6d7a740b8a666a7e828dd00da9c0dc290dff53154ea77ac109281de90589b7" dependencies = [ - "thiserror-impl", + "thiserror-impl 1.0.48", +] + +[[package]] +name = "thiserror" +version = "2.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09a43598840e33d5b0331f38c5e30d13bb11c11210a4b58f0d9b18a5a5eefcd9" +dependencies = [ + "thiserror-impl 2.0.19", ] [[package]] @@ -550,6 +577,17 @@ dependencies = [ "syn 2.0.37", ] +[[package]] +name = "thiserror-impl" +version = "2.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43cbfe0cf76104d42a574802844187e84a305e531ed54455f11fbde0f10541cd" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", +] + [[package]] name = "thread_local" version = "1.1.7" @@ -562,30 +600,31 @@ dependencies = [ [[package]] name = "time" -version = "0.3.30" +version = "0.3.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5" +checksum = "cdb87b95ec50ddfa440816d227a17b2ccbdda963a316a727fda0fc4334f7d134" dependencies = [ "deranged", - "itoa", + "num-conv", "powerfmt", - "serde", + "serde_core", "time-core", "time-macros", ] [[package]] name = "time-core" -version = "0.1.2" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" +checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109" [[package]] name = "time-macros" -version = "0.2.15" +version = "0.2.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20" +checksum = "7e689342a48d2ea927c87ea50cabf8594854bf940e9310208848d680d668ed85" dependencies = [ + "num-conv", "time-core", ] @@ -606,11 +645,10 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tracing" -version = "0.1.37" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ - "cfg-if", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -618,9 +656,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.26" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", @@ -629,9 +667,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.31" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" dependencies = [ "once_cell", "valuable", @@ -650,14 +688,12 @@ dependencies = [ [[package]] name = "tracing-opentelemetry" -version = "0.23.0" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9be14ba1bbe4ab79e9229f7f89fab8d120b865859f10527f31c033e599d2284" +checksum = "adbc64cba7137545b8044cb1fe9814f7aacf3c6b5f9b45be8bb5db538befdb26" dependencies = [ "js-sys", - "once_cell", "opentelemetry", - "opentelemetry_sdk", "smallvec", "tracing", "tracing-core", @@ -668,9 +704,9 @@ dependencies = [ [[package]] name = "tracing-serde" -version = "0.1.3" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc6b213177105856957181934e4920de57730fc69bf42c37ee5bb664d406d9e1" +checksum = "704b1aeb7be0d0a84fc9828cae51dab5970fee5088f83d1dd7ee6f6246fc6ff1" dependencies = [ "serde", "tracing-core", @@ -678,7 +714,7 @@ dependencies = [ [[package]] name = "tracing-stackdriver" -version = "0.10.0" +version = "0.11.0" dependencies = [ "Inflector", "http", @@ -686,10 +722,10 @@ dependencies = [ "opentelemetry", "opentelemetry-stdout", "opentelemetry_sdk", - "rand", + "rand 0.8.5", "serde", "serde_json", - "thiserror", + "thiserror 1.0.48", "time", "tracing", "tracing-core", @@ -702,9 +738,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.18" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" dependencies = [ "nu-ansi-term", "serde", @@ -749,12 +785,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "urlencoding" -version = "2.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" - [[package]] name = "valuable" version = "0.1.0" @@ -791,6 +821,15 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasip2" +version = "1.0.4+wasi-0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487" +dependencies = [ + "wit-bindgen", +] + [[package]] name = "wasm-bindgen" version = "0.2.87" @@ -856,23 +895,22 @@ dependencies = [ ] [[package]] -name = "winapi" -version = "0.3.9" +name = "windows-link" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" +name = "windows-sys" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] [[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" +name = "wit-bindgen" +version = "0.57.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" diff --git a/Cargo.toml b/Cargo.toml index 58c3468..bc92f32 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tracing-stackdriver" -version = "0.10.0" +version = "0.11.0" authors = ["Alex Pearson "] edition = "2021" license = "MIT" @@ -32,7 +32,7 @@ version = "0.2.9" [dependencies.opentelemetry] default-features = false features = ["trace"] -version = "0.22.0" +version = "0.32.0" optional = true [dependencies.serde] @@ -45,7 +45,7 @@ features = ["formatting"] version = "0.3.30" [dependencies.tracing-opentelemetry] -version = "0.23.0" +version = "0.33.0" optional = true [dependencies.tracing-subscriber] @@ -69,7 +69,7 @@ version = "0.1.0" lazy_static = "1.4.0" tracing = "0.1.34" rand = "0.8.5" -opentelemetry_sdk = "0.22.1" +opentelemetry_sdk = "0.32.1" [dev-dependencies.time] features = ["serde", "serde-well-known", "formatting"] @@ -78,12 +78,15 @@ version = "0.3.30" [dev-dependencies.opentelemetry] default-features = false features = ["testing", "trace"] -version = "0.22.0" +version = "0.32.0" [dev-dependencies.opentelemetry-stdout] features = ["trace"] -version = "0.3.0" +version = "0.32.0" [features] valuable = ["dep:valuable", "valuable-serde", "http", "url"] opentelemetry = ["dep:opentelemetry", "tracing-opentelemetry"] + +[lints.rust] +unexpected_cfgs = { level = "warn", check-cfg = ['cfg(tracing_unstable)'] } diff --git a/src/event_formatter.rs b/src/event_formatter.rs index 7555032..8a155d9 100644 --- a/src/event_formatter.rs +++ b/src/event_formatter.rs @@ -6,6 +6,8 @@ use crate::{ }; use serde::ser::{SerializeMap, Serializer as _}; use std::fmt; +#[cfg(feature = "opentelemetry")] +use std::sync::Arc; use time::{format_description::well_known::Rfc3339, OffsetDateTime}; use tracing_core::{Event, Subscriber}; use tracing_subscriber::{ @@ -40,6 +42,8 @@ pub struct EventFormatter { pub(crate) include_source_location: bool, #[cfg(feature = "opentelemetry")] pub(crate) cloud_trace_configuration: Option, + #[cfg(feature = "opentelemetry")] + pub(crate) dispatch: Arc>, } impl EventFormatter { @@ -87,36 +91,35 @@ impl EventFormatter { map.serialize_entry("spans", &SerializableContext::new(context))?; #[cfg(feature = "opentelemetry")] - if let (Some(crate::CloudTraceConfiguration { project_id }), Some(otel_data)) = ( - self.cloud_trace_configuration.as_ref(), - span.extensions().get::(), - ) { + if let Some(crate::CloudTraceConfiguration { project_id }) = + self.cloud_trace_configuration.as_ref() + { use opentelemetry::trace::TraceContextExt; - let builder = &otel_data.builder; - - if let Some(span_id) = builder.span_id { - map.serialize_entry("logging.googleapis.com/spanId", &span_id.to_string())?; - } - - let (trace_id, trace_sampled) = if otel_data.parent_cx.has_active_span() { - let span_ref = otel_data.parent_cx.span(); - let span_context = span_ref.span_context(); - - (Some(span_context.trace_id()), span_context.is_sampled()) - } else { - (builder.trace_id, false) - }; - - if let Some(trace_id) = trace_id { - map.serialize_entry( - "logging.googleapis.com/trace", - &format!("projects/{project_id}/traces/{trace_id}",), - )?; - } - - if trace_sampled { - map.serialize_entry("logging.googleapis.com/trace_sampled", &true)?; + if let Some(otel_context) = self + .dispatch + .get() + .and_then(tracing_core::dispatcher::WeakDispatch::upgrade) + .and_then(|dispatch| { + tracing_opentelemetry::get_otel_context(&span.id(), &dispatch) + }) + { + let otel_span = otel_context.span(); + let span_context = otel_span.span_context(); + if span_context.is_valid() { + map.serialize_entry( + "logging.googleapis.com/spanId", + &span_context.span_id().to_string(), + )?; + map.serialize_entry( + "logging.googleapis.com/trace", + &format!("projects/{project_id}/traces/{}", span_context.trace_id()), + )?; + + if span_context.is_sampled() { + map.serialize_entry("logging.googleapis.com/trace_sampled", &true)?; + } + } } } } @@ -154,6 +157,8 @@ impl Default for EventFormatter { include_source_location: true, #[cfg(feature = "opentelemetry")] cloud_trace_configuration: None, + #[cfg(feature = "opentelemetry")] + dispatch: Arc::new(std::sync::OnceLock::new()), } } } diff --git a/src/layer.rs b/src/layer.rs index fecfc73..197c31d 100644 --- a/src/layer.rs +++ b/src/layer.rs @@ -1,4 +1,6 @@ use crate::event_formatter::EventFormatter; +#[cfg(feature = "opentelemetry")] +use std::sync::{Arc, OnceLock}; use std::{fmt, io, ops::Deref}; use tracing_core::{Event, Subscriber}; use tracing_subscriber::{ @@ -29,19 +31,31 @@ pub fn layer() -> Layer where S: Subscriber + for<'span> LookupSpan<'span>, { - Layer( - tracing_subscriber::fmt::layer() + #[cfg(feature = "opentelemetry")] + let dispatch = Arc::new(OnceLock::new()); + let formatter = EventFormatter { + #[cfg(feature = "opentelemetry")] + dispatch: dispatch.clone(), + ..EventFormatter::default() + }; + Layer { + inner: tracing_subscriber::fmt::layer() .json() - .event_format(EventFormatter::default()), - ) + .event_format(formatter), + #[cfg(feature = "opentelemetry")] + dispatch, + } } /// A tracing-compatible Layer implementation for Stackdriver -pub struct Layer io::Stdout>( - tracing_subscriber::fmt::Layer, -) +pub struct Layer io::Stdout> where - S: Subscriber + for<'span> LookupSpan<'span>; + S: Subscriber + for<'span> LookupSpan<'span>, +{ + inner: tracing_subscriber::fmt::Layer, + #[cfg(feature = "opentelemetry")] + dispatch: Arc>, +} impl Layer where @@ -53,25 +67,36 @@ where where M: for<'writer> MakeWriter<'writer> + 'static, { - Layer(self.0.with_writer(make_writer)) + Layer { + inner: self.inner.with_writer(make_writer), + #[cfg(feature = "opentelemetry")] + dispatch: self.dispatch, + } } /// Configures whether or not Events will include source locations in a special LogEntry field pub fn with_source_location(self, include_source_location: bool) -> Self { - Self(self.0.map_event_format(|mut event_formatter| { - event_formatter.include_source_location = include_source_location; - event_formatter - })) + Self { + inner: self.inner.map_event_format(|mut event_formatter| { + event_formatter.include_source_location = include_source_location; + event_formatter + }), + #[cfg(feature = "opentelemetry")] + dispatch: self.dispatch, + } } /// Configures the Cloud Trace integration with OpenTelemetry through special LogEntry fields #[cfg_attr(docsrs, doc(cfg(feature = "opentelemetry")))] #[cfg(any(docsrs, feature = "opentelemetry"))] pub fn with_cloud_trace(self, configuration: crate::CloudTraceConfiguration) -> Self { - Self(self.0.map_event_format(|mut event_formatter| { - event_formatter.cloud_trace_configuration = Some(configuration); - event_formatter - })) + Self { + inner: self.inner.map_event_format(|mut event_formatter| { + event_formatter.cloud_trace_configuration = Some(configuration); + event_formatter + }), + dispatch: self.dispatch, + } } } @@ -87,7 +112,7 @@ where id: &tracing_core::span::Id, context: tracing_subscriber::layer::Context<'_, S>, ) { - self.0.on_new_span(attrs, id, context) + self.inner.on_new_span(attrs, id, context) } fn on_record( @@ -96,7 +121,7 @@ where values: &tracing_core::span::Record<'_>, context: tracing_subscriber::layer::Context<'_, S>, ) { - self.0.on_record(span, values, context) + self.inner.on_record(span, values, context) } fn on_enter( @@ -104,7 +129,7 @@ where id: &tracing_core::span::Id, context: tracing_subscriber::layer::Context<'_, S>, ) { - self.0.on_enter(id, context) + self.inner.on_enter(id, context) } fn on_exit( @@ -112,7 +137,7 @@ where id: &tracing_core::span::Id, context: tracing_subscriber::layer::Context<'_, S>, ) { - self.0.on_exit(id, context) + self.inner.on_exit(id, context) } fn on_close( @@ -120,15 +145,21 @@ where id: tracing_core::span::Id, context: tracing_subscriber::layer::Context<'_, S>, ) { - self.0.on_close(id, context) + self.inner.on_close(id, context) } fn on_event(&self, event: &Event<'_>, context: tracing_subscriber::layer::Context<'_, S>) { - self.0.on_event(event, context) + self.inner.on_event(event, context) + } + + fn on_register_dispatch(&self, subscriber: &tracing_core::Dispatch) { + #[cfg(feature = "opentelemetry")] + let _ = self.dispatch.set(subscriber.downgrade()); + self.inner.on_register_dispatch(subscriber) } unsafe fn downcast_raw(&self, id: std::any::TypeId) -> Option<*const ()> { - self.0.downcast_raw(id) + self.inner.downcast_raw(id) } } @@ -139,6 +170,6 @@ where type Target = tracing_subscriber::fmt::Layer; fn deref(&self) -> &Self::Target { - &self.0 + &self.inner } } diff --git a/tests/opentelemetry.rs b/tests/opentelemetry.rs index 8a675c2..48ea80d 100644 --- a/tests/opentelemetry.rs +++ b/tests/opentelemetry.rs @@ -5,7 +5,7 @@ use opentelemetry::{ testing::trace::TestSpan, trace::{SpanContext, SpanId, TraceContextExt, TraceFlags, TraceId, TraceState}, }; -use opentelemetry_sdk::trace::TracerProvider; +use opentelemetry_sdk::trace::SdkTracerProvider; use rand::Rng; use serde::{de::Error, Deserialize, Deserializer}; use std::{ @@ -26,7 +26,7 @@ lazy_static! { }; // use a tracer that generates valid span IDs (unlike default NoopTracer) - static ref TRACER: TracerProvider = TracerProvider::builder() + static ref TRACER: SdkTracerProvider = SdkTracerProvider::builder() .with_simple_exporter(opentelemetry_stdout::SpanExporter::default()) .build(); } @@ -98,8 +98,8 @@ fn includes_correct_cloud_trace_fields() { // generate relevant IDs let mut rng = rand::thread_rng(); - let span_id = SpanId::from_u64(rng.gen()); - let trace_id = TraceId::from_u128(rng.gen()); + let span_id = SpanId::from_bytes(rng.gen()); + let trace_id = TraceId::from_bytes(rng.gen()); // generate a tracing-based event test_with_tracing(span_id, trace_id, make_writer, || { @@ -137,8 +137,8 @@ fn handles_nested_spans() { // generate relevant IDs let mut rng = rand::thread_rng(); - let span_id = SpanId::from_u64(rng.gen()); - let trace_id = TraceId::from_u128(rng.gen()); + let span_id = SpanId::from_bytes(rng.gen()); + let trace_id = TraceId::from_bytes(rng.gen()); // generate a set of nested tracing-based events test_with_tracing(span_id, trace_id, make_writer, || {