diff --git a/Cargo.lock b/Cargo.lock index 15b4b16676..6f1b4dddbf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -334,6 +334,25 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "383d29d513d8764dcdc42ea295d979eb99c3c9f00607b3692cf68a431f7dca72" +[[package]] +name = "bindgen" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd4865004a46a0aafb2a0a5eb19d3c9fc46ee5f063a6cfc605c69ac9ecf5263d" +dependencies = [ + "bitflags", + "cexpr", + "clang-sys", + "lazy_static", + "lazycell", + "peeking_take_while", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", +] + [[package]] name = "bit-vec" version = "0.6.3" @@ -409,6 +428,15 @@ dependencies = [ "generic-array", ] +[[package]] +name = "boringssl-src" +version = "0.3.0+688fc5c" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f901accdf830d2ea2f4e27f923a5e1125cd8b1a39ab578b9db1a42d578a6922b" +dependencies = [ + "cmake", +] + [[package]] name = "bs58" version = "0.4.0" @@ -478,6 +506,15 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" +[[package]] +name = "cexpr" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4aedb84272dbe89af497cf81375129abda4fc0a9e7c5d317498c15cc30c0d27" +dependencies = [ + "nom 5.1.2", +] + [[package]] name = "cfg-if" version = "1.0.0" @@ -529,6 +566,17 @@ dependencies = [ "generic-array", ] +[[package]] +name = "clang-sys" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a050e2153c5be08febd6734e29298e844fdb0fa21aeddd63b4eb7baa106c69b" +dependencies = [ + "glob", + "libc", + "libloading", +] + [[package]] name = "clap" version = "3.2.11" @@ -788,9 +836,9 @@ dependencies = [ [[package]] name = "ctor" -version = "0.1.21" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccc0a48a9b826acdf4028595adc9db92caea352f7af011a3034acd172a52a0aa" +checksum = "f877be4f7c9f246b183111634f75baa039715e3f46ce860677d3b19a69fb229c" dependencies = [ "quote", "syn", @@ -905,6 +953,7 @@ dependencies = [ "mockall", "mockall_derive", "model", + "otel-tests", "rand 0.6.5", "rust_decimal", "rust_decimal_macros", @@ -913,7 +962,6 @@ dependencies = [ "tokio", "tokio-extras", "tracing", - "tracing-subscriber", "xtra", "xtra-bitmex-price-feed", "xtra-libp2p", @@ -1433,6 +1481,36 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" +[[package]] +name = "grpcio" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d99e00eed7e0a04ee2705112e7cfdbe1a3cc771147f22f016a8cd2d002187b" +dependencies = [ + "futures", + "grpcio-sys", + "libc", + "log", + "parking_lot 0.11.2", + "protobuf", +] + +[[package]] +name = "grpcio-sys" +version = "0.9.1+1.38.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9447d1a926beeef466606cc45717f80897998b548e7dc622873d453e1ecb4be4" +dependencies = [ + "bindgen", + "boringssl-src", + "cc", + "cmake", + "libc", + "libz-sys", + "pkg-config", + "walkdir", +] + [[package]] name = "h2" version = "0.3.10" @@ -1485,7 +1563,7 @@ dependencies = [ "base64", "byteorder", "flate2", - "nom", + "nom 7.0.0", "num-traits", ] @@ -1771,6 +1849,12 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + [[package]] name = "libc" version = "0.2.121" @@ -1789,6 +1873,16 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "libloading" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd" +dependencies = [ + "cfg-if", + "winapi 0.3.9", +] + [[package]] name = "libm" version = "0.2.2" @@ -2376,6 +2470,16 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" +[[package]] +name = "nom" +version = "5.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af" +dependencies = [ + "memchr", + "version_check", +] + [[package]] name = "nom" version = "7.0.0" @@ -2521,9 +2625,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.12.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225" +checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1" [[package]] name = "opaque-debug" @@ -2567,9 +2671,11 @@ dependencies = [ "async-trait", "futures", "futures-util", + "grpcio", "http", "opentelemetry", "prost 0.9.0", + "protobuf", "thiserror", "tokio", "tonic 0.6.2", @@ -2582,6 +2688,28 @@ version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64" +[[package]] +name = "otel-tests" +version = "0.1.0" +dependencies = [ + "futures", + "opentelemetry", + "opentelemetry-otlp", + "otel-tests-macro", + "tokio", + "tracing", + "tracing-opentelemetry", + "tracing-subscriber", +] + +[[package]] +name = "otel-tests-macro" +version = "0.1.0" +dependencies = [ + "quote", + "syn", +] + [[package]] name = "output_vt100" version = "0.1.2" @@ -2703,6 +2831,12 @@ dependencies = [ "syn", ] +[[package]] +name = "peeking_take_while" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" + [[package]] name = "percent-encoding" version = "2.1.0" @@ -3023,6 +3157,12 @@ dependencies = [ "prost 0.10.4", ] +[[package]] +name = "protobuf" +version = "2.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf7e6d18738ecd0902d30d1ad232c9125985a3422929b16c65517b38adc14f96" + [[package]] name = "quick-error" version = "2.0.1" @@ -3534,6 +3674,12 @@ dependencies = [ "rust_decimal", ] +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + [[package]] name = "rustc_version" version = "0.4.0" @@ -3897,6 +4043,12 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "shlex" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2" + [[package]] name = "signal-hook-registry" version = "1.4.0" @@ -4037,7 +4189,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4b7922be017ee70900be125523f38bdd644f4f06a1b16e8fa5a8ee8c34bffd4" dependencies = [ "itertools", - "nom", + "nom 7.0.0", "unicode_categories", ] diff --git a/Cargo.toml b/Cargo.toml index 32b4df5702..19564b756e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,8 @@ members = [ "shared-bin", "daemon-tests", "tokio-extras", + "otel-tests", + "otel-tests-macro", "xtras", "xtra-bitmex-price-feed", "bdk-ext", diff --git a/daemon-tests/Cargo.toml b/daemon-tests/Cargo.toml index 57bd9c02cc..4a2b3fbb7c 100644 --- a/daemon-tests/Cargo.toml +++ b/daemon-tests/Cargo.toml @@ -13,6 +13,7 @@ maker = { path = "../maker" } mockall = "0.11" mockall_derive = "0.11" model = { path = "../model" } +otel-tests = { path = "../otel-tests" } rand = "0.6" rust_decimal = "1.25" rust_decimal_macros = "1.25" @@ -21,7 +22,6 @@ time = "0.3.11" tokio = { version = "1", features = ["rt-multi-thread", "macros", "sync", "net", "tracing"] } tokio-extras = { path = "../tokio-extras", features = ["xtra"] } tracing = { version = "0.1" } -tracing-subscriber = { version = "0.3", default-features = false, features = ["fmt", "ansi", "env-filter", "local-time", "tracing-log", "json"] } xtra = { version = "0.6", features = ["instrumentation"] } xtra-bitmex-price-feed = { path = "../xtra-bitmex-price-feed" } xtra-libp2p = { path = "../xtra-libp2p" } diff --git a/daemon-tests/src/lib.rs b/daemon-tests/src/lib.rs index 2c239a154f..ff65a83e97 100644 --- a/daemon-tests/src/lib.rs +++ b/daemon-tests/src/lib.rs @@ -43,10 +43,7 @@ use time::OffsetDateTime; use tokio::net::TcpListener; use tokio::sync::watch; use tokio_extras::Tasks; -use tracing::subscriber::DefaultGuard; -use tracing_subscriber::filter::LevelFilter; -use tracing_subscriber::util::SubscriberInitExt; -use tracing_subscriber::EnvFilter; +use tracing::instrument; use xtra::Actor; use xtra_bitmex_price_feed::Quote; use xtra_libp2p::libp2p::Multiaddr; @@ -61,6 +58,7 @@ fn oracle_pk() -> XOnlyPublicKey { .unwrap() } +#[instrument] pub async fn start_both() -> (Maker, Taker) { let maker = Maker::start(&MakerConfig::default()).await; let taker = Taker::start( @@ -73,7 +71,7 @@ pub async fn start_both() -> (Maker, Taker) { (maker, taker) } -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Debug)] pub struct MakerConfig { oracle_pk: XOnlyPublicKey, seed: RandomSeed, @@ -112,7 +110,7 @@ impl Default for MakerConfig { } } -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Debug)] pub struct TakerConfig { oracle_pk: XOnlyPublicKey, seed: RandomSeed, @@ -176,6 +174,7 @@ impl Maker { &mut self.feeds.connected_takers } + #[instrument(name = "Start maker", skip_all)] pub async fn start(config: &MakerConfig) -> Self { let port = match config.dedicated_port { Some(port) => port, @@ -350,6 +349,7 @@ impl Taker { &mut self.system.maker_online_status_feed_receiver } + #[instrument(name = "Start taker", skip_all)] pub async fn start( config: &TakerConfig, maker_address: SocketAddr, @@ -546,27 +546,6 @@ fn dummy_price() -> Decimal { dec!(50_000) } -pub fn init_tracing() -> DefaultGuard { - let filter = EnvFilter::from_default_env() - // apply warning level globally - .add_directive(LevelFilter::WARN.into()) - // log traces from test itself - .add_directive("happy_path=debug".parse().unwrap()) - .add_directive("wire=trace".parse().unwrap()) - .add_directive("taker=debug".parse().unwrap()) - .add_directive("maker=debug".parse().unwrap()) - .add_directive("daemon=debug".parse().unwrap()) - .add_directive("xtra_libp2p=debug".parse().unwrap()) - .add_directive("xtra_libp2p_offer=debug".parse().unwrap()) - .add_directive("xtra_libp2p_ping=debug".parse().unwrap()) - .add_directive("rocket=warn".parse().unwrap()); - - tracing_subscriber::fmt() - .with_env_filter(filter) - .with_test_writer() - .set_default() -} - pub async fn mock_oracle_announcements( maker: &mut Maker, taker: &mut Taker, diff --git a/daemon-tests/tests/happy_path.rs b/daemon-tests/tests/happy_path.rs index eac688f788..fce4a4f654 100644 --- a/daemon-tests/tests/happy_path.rs +++ b/daemon-tests/tests/happy_path.rs @@ -13,7 +13,6 @@ use daemon_tests::flow::next; use daemon_tests::flow::next_maker_offers; use daemon_tests::flow::next_with; use daemon_tests::flow::one_cfd_with_state; -use daemon_tests::init_tracing; use daemon_tests::maia::OliviaData; use daemon_tests::mock_oracle_announcements; use daemon_tests::mocks::oracle::dummy_wrong_attestation; @@ -37,6 +36,7 @@ use model::Position; use model::Role; use model::Usd; use model::SETTLEMENT_INTERVAL; +use otel_tests::otel_test; use rust_decimal_macros::dec; use std::time::Duration; use tokio_extras::time::sleep; @@ -125,9 +125,8 @@ macro_rules! expire { }; } -#[tokio::test] +#[otel_test] async fn taker_receives_order_from_maker_on_publication() { - let _guard = init_tracing(); let (mut maker, mut taker) = start_both().await; assert!(is_next_offers_none(taker.offers_feed()).await.unwrap()); @@ -192,9 +191,8 @@ fn assert_eq_orders(mut published: CfdOrder, received: CfdOrder) { assert_eq!(received.funding_rate_hourly_percent, "0.00100"); } -#[tokio::test] +#[otel_test] async fn taker_takes_order_and_maker_rejects() { - let _guard = init_tracing(); let (mut maker, mut taker) = start_both().await; is_next_offers_none(taker.offers_feed()).await.unwrap(); @@ -224,9 +222,8 @@ async fn taker_takes_order_and_maker_rejects() { wait_next_state!(order_id, maker, taker, CfdState::Rejected); } -#[tokio::test] +#[otel_test] async fn another_offer_is_automatically_created_after_taker_takes_order() { - let _guard = init_tracing(); let (mut maker, mut taker) = start_both().await; is_next_offers_none(taker.offers_feed()).await.unwrap(); @@ -275,9 +272,8 @@ async fn another_offer_is_automatically_created_after_taker_takes_order() { ) } -#[tokio::test] +#[otel_test] async fn taker_takes_order_and_maker_accepts_and_contract_setup() { - let _guard = init_tracing(); let (mut maker, mut taker) = start_both().await; is_next_offers_none(taker.offers_feed()).await.unwrap(); @@ -318,15 +314,13 @@ async fn taker_takes_order_and_maker_accepts_and_contract_setup() { wait_next_state!(order_id, maker, taker, CfdState::Open); } -#[tokio::test] +#[otel_test] async fn collaboratively_close_an_open_cfd_maker_going_short() { - let _guard = init_tracing(); collaboratively_close_an_open_cfd(Position::Short).await; } -#[tokio::test] +#[otel_test] async fn collaboratively_close_an_open_cfd_maker_going_long() { - let _guard = init_tracing(); collaboratively_close_an_open_cfd(Position::Long).await; } @@ -358,15 +352,13 @@ async fn collaboratively_close_an_open_cfd(maker_position: Position) { wait_next_state!(order_id, maker, taker, CfdState::Closed); } -#[tokio::test] +#[otel_test] async fn force_close_an_open_cfd_maker_going_short() { - let _guard = init_tracing(); force_close_open_cfd(Position::Short).await; } -#[tokio::test] +#[otel_test] async fn force_close_an_open_cfd_maker_going_long() { - let _guard = init_tracing(); force_close_open_cfd(Position::Long).await; } @@ -401,9 +393,8 @@ async fn force_close_open_cfd(maker_position: Position) { wait_next_state!(order_id, maker, taker, CfdState::Closed); } -#[tokio::test] +#[otel_test] async fn rollover_an_open_cfd_maker_going_short() { - let _guard = init_tracing(); let (mut maker, mut taker, order_id, fee_structure) = prepare_rollover(Position::Short, OliviaData::example_0()).await; @@ -422,9 +413,8 @@ async fn rollover_an_open_cfd_maker_going_short() { .await; } -#[tokio::test] +#[otel_test] async fn rollover_an_open_cfd_maker_going_long() { - let _guard = init_tracing(); let (mut maker, mut taker, order_id, fee_structure) = prepare_rollover(Position::Long, OliviaData::example_0()).await; @@ -443,11 +433,10 @@ async fn rollover_an_open_cfd_maker_going_long() { .await; } -#[tokio::test] +#[otel_test] async fn double_rollover_an_open_cfd() { // double rollover ensures that both parties properly succeeded and can do another rollover - let _guard = init_tracing(); let (mut maker, mut taker, order_id, fee_structure) = prepare_rollover(Position::Short, OliviaData::example_0()).await; @@ -483,10 +472,8 @@ async fn double_rollover_an_open_cfd() { /// The contract setup is done with `example_0`. /// The first rollover is done with `example_1`. /// The second rollover is done with `example_0` (we re-use it) -#[tokio::test] +#[otel_test] async fn retry_rollover_an_open_cfd() { - let _guard = init_tracing(); - let contract_setup_oracle_data = OliviaData::example_0(); let contract_setup_oracle_data_announcement = contract_setup_oracle_data.announcement(); let (mut maker, mut taker, order_id, fee_structure) = @@ -677,9 +664,8 @@ async fn rollover( ); } -#[tokio::test] +#[otel_test] async fn maker_rejects_rollover_of_open_cfd() { - let _guard = init_tracing(); let oracle_data = OliviaData::example_0(); let (mut maker, mut taker, order_id, _) = start_from_open_cfd_state(oracle_data.announcement(), Position::Short).await; @@ -701,9 +687,8 @@ async fn maker_rejects_rollover_of_open_cfd() { wait_next_state!(order_id, maker, taker, CfdState::Open); } -#[tokio::test] +#[otel_test] async fn maker_rejects_rollover_after_commit_finality() { - let _guard = init_tracing(); let oracle_data = OliviaData::example_0(); let (mut maker, mut taker, order_id, _) = start_from_open_cfd_state(oracle_data.announcement(), Position::Short).await; @@ -734,9 +719,8 @@ async fn maker_rejects_rollover_after_commit_finality() { wait_next_state!(order_id, maker, taker, CfdState::OpenCommitted); } -#[tokio::test] +#[otel_test] async fn maker_accepts_rollover_after_commit_finality() { - let _guard = init_tracing(); let oracle_data = OliviaData::example_0(); let (mut maker, mut taker, order_id, _) = start_from_open_cfd_state(oracle_data.announcement(), Position::Short).await; @@ -771,9 +755,8 @@ async fn maker_accepts_rollover_after_commit_finality() { ); } -#[tokio::test] +#[otel_test] async fn maker_rejects_collab_settlement_after_commit_finality() { - let _guard = init_tracing(); let (mut maker, mut taker, order_id, _) = start_from_open_cfd_state(OliviaData::example_0().announcement(), Position::Short).await; taker.mocks.mock_latest_quote(Some(dummy_quote())).await; @@ -800,9 +783,8 @@ async fn maker_rejects_collab_settlement_after_commit_finality() { wait_next_state!(order_id, maker, taker, CfdState::OpenCommitted); } -#[tokio::test] +#[otel_test] async fn maker_accepts_collab_settlement_after_commit_finality() { - let _guard = init_tracing(); let (mut maker, mut taker, order_id, _) = start_from_open_cfd_state(OliviaData::example_0().announcement(), Position::Short).await; taker.mocks.mock_latest_quote(Some(dummy_quote())).await; @@ -829,9 +811,8 @@ async fn maker_accepts_collab_settlement_after_commit_finality() { wait_next_state!(order_id, maker, taker, CfdState::OpenCommitted); } -#[tokio::test] +#[otel_test] async fn open_cfd_is_refunded() { - let _guard = init_tracing(); let oracle_data = OliviaData::example_0(); let (mut maker, mut taker, order_id, _) = start_from_open_cfd_state(oracle_data.announcement(), Position::Short).await; @@ -849,10 +830,8 @@ async fn open_cfd_is_refunded() { wait_next_state!(order_id, maker, taker, CfdState::Refunded); } -#[tokio::test] +#[otel_test] async fn taker_notices_lack_of_maker() { - let _guard = init_tracing(); - let maker_config = MakerConfig::default() .with_dedicated_port(35123) .with_dedicated_libp2p_port(35124); // set fixed ports so the taker can reconnect @@ -893,10 +872,8 @@ async fn taker_notices_lack_of_maker() { ); } -#[tokio::test] +#[otel_test] async fn maker_notices_lack_of_taker() { - let _guard = init_tracing(); - let (mut maker, taker) = start_both().await; assert_eq!( vec![taker.id], diff --git a/daemon/src/seed.rs b/daemon/src/seed.rs index 76e1d77a77..a23d23e2aa 100644 --- a/daemon/src/seed.rs +++ b/daemon/src/seed.rs @@ -9,6 +9,8 @@ use model::libp2p::PeerId; use rand::Rng; use sha2::Sha256; use std::convert::TryInto; +use std::fmt; +use std::fmt::Debug; use std::path::Path; /// Struct containing keys for both legacy and libp2p connections. @@ -97,6 +99,12 @@ impl Seed for RandomSeed { } } +impl Debug for RandomSeed { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("RandomSeed").field(&"...").finish() + } +} + impl RandomSeed { /// Initialize a [`Seed`] from a path. /// Generates new seed if there was no seed found in the given path diff --git a/otel-tests-macro/Cargo.toml b/otel-tests-macro/Cargo.toml new file mode 100644 index 0000000000..a8e7fa8017 --- /dev/null +++ b/otel-tests-macro/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "otel-tests-macro" +version = "0.1.0" +edition = "2021" +description = "Internal #[otel_test] macro crate for otel-tests" + +[lib] +proc-macro = true + +[dependencies] +quote = "1" +syn = { version = "1", features = ["full"] } diff --git a/otel-tests-macro/src/lib.rs b/otel-tests-macro/src/lib.rs new file mode 100644 index 0000000000..ceacf3d012 --- /dev/null +++ b/otel-tests-macro/src/lib.rs @@ -0,0 +1,48 @@ +use proc_macro::TokenStream; +use quote::quote; +use syn::ItemFn; + +#[proc_macro_attribute] +pub fn otel_test(_attribute: TokenStream, item: TokenStream) -> TokenStream { + let fn_item = syn::parse::(item).unwrap(); + + let sig = fn_item.sig; + let block = fn_item.block; + let name = &sig.ident; + let attrs = fn_item.attrs; + + let test = if attrs.is_empty() { + quote!(#[otel_tests::__reexport::tokio::test]) + } else { + quote!() + }; + + let tokens = quote! { + #test + #(#attrs)* + #sig { + ::otel_tests::init_tracing(module_path!()); + + let caught = { + ::otel_tests::__reexport::futures::FutureExt::catch_unwind(std::panic::AssertUnwindSafe(tracing::Instrument::instrument( + async #block, tracing::info_span!(stringify!(#name)) + ))).await + }; + + // Give the otel thread time to receive the spans before flush + #[allow(clippy::disallowed_methods)] + ::otel_tests::__reexport::tokio::time::sleep(std::time::Duration::from_secs(1)).await; + + // If this is the last test that's running, the main thread might exit. Then, the + // opentelemetry exporter thread might not have exported all of its spans yet, leading + // to some dropped spans. This ensures in most cases that it happens. + ::otel_tests::__reexport::opentelemetry::global::force_flush_tracer_provider(); + + if let Err(e) = caught { + panic!("{:#?}", e); + } + } + }; + + tokens.into() +} diff --git a/otel-tests/Cargo.toml b/otel-tests/Cargo.toml new file mode 100644 index 0000000000..5d3f951b5e --- /dev/null +++ b/otel-tests/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "otel-tests" +version = "0.1.0" +edition = "2021" +description = "Internal #[otel_test] macro to export test spans over OTLP" + +[dependencies] +futures = "0.3" +opentelemetry = { version = "0.17.0", features = ["rt-tokio"] } +opentelemetry-otlp = { version = "0.10.0", features = ["grpc-sys", "trace"] } +otel-tests-macro = { path = "../otel-tests-macro" } +tokio = { version = "1", features = ["macros"] } +tracing = "0.1" +tracing-opentelemetry = "0.17.4" +tracing-subscriber = { version = "0.3", default-features = false, features = ["fmt", "ansi", "env-filter", "local-time", "tracing-log", "json"] } diff --git a/otel-tests/src/lib.rs b/otel-tests/src/lib.rs new file mode 100644 index 0000000000..e901cfb2b1 --- /dev/null +++ b/otel-tests/src/lib.rs @@ -0,0 +1,71 @@ +use opentelemetry::sdk::trace; +use opentelemetry::sdk::Resource; +use opentelemetry::KeyValue; +use opentelemetry_otlp::WithExportConfig; +use std::sync::Once; +use tracing_subscriber::filter::LevelFilter; +use tracing_subscriber::layer::SubscriberExt; +use tracing_subscriber::util::SubscriberInitExt; +use tracing_subscriber::EnvFilter; +use tracing_subscriber::Layer; +use tracing_subscriber::Registry; + +#[doc(hidden)] +pub mod __reexport { + pub use futures; + pub use opentelemetry; + pub use tokio; +} + +pub use otel_tests_macro::otel_test; + +static INIT_OTLP_EXPORTER: Once = Once::new(); + +pub fn init_tracing(module: &'static str) { + INIT_OTLP_EXPORTER.call_once(|| { + let env = std::env::var("ITCHYSATS_TEST_INSTRUMENTATION").unwrap_or_default(); + let telemetry = if env == "1" { + let cfg = trace::Config::default() + .with_resource(Resource::new([KeyValue::new("service.name", module)])); + + let tracer = opentelemetry_otlp::new_pipeline() + .tracing() + .with_trace_config(cfg) + .with_exporter( + opentelemetry_otlp::new_exporter() + .grpcio() + .with_endpoint("localhost:4317"), + ) + .install_simple() + .unwrap(); + + Some( + tracing_opentelemetry::layer() + .with_tracer(tracer) + .with_filter(LevelFilter::DEBUG), + ) + } else { + None + }; + + let filter = EnvFilter::from_default_env() + // apply warning level globally + .add_directive(LevelFilter::WARN.into()) + // log traces from test itself + .add_directive(format!("{module}=debug").parse().unwrap()) + .add_directive("wire=trace".parse().unwrap()) + .add_directive("taker=debug".parse().unwrap()) + .add_directive("maker=debug".parse().unwrap()) + .add_directive("daemon=debug".parse().unwrap()) + .add_directive("xtra_libp2p=debug".parse().unwrap()) + .add_directive("xtra_libp2p_offer=debug".parse().unwrap()) + .add_directive("xtra_libp2p_ping=debug".parse().unwrap()) + .add_directive("rocket=warn".parse().unwrap()); + + let fmt_layer = tracing_subscriber::fmt::layer() + .with_test_writer() + .with_filter(filter); + + Registry::default().with(telemetry).with(fmt_layer).init(); + }) +}