diff --git a/.github/actions/build-test-wasm/action.yaml b/.github/actions/build-test-wasm/action.yaml index 90cafd5..fe00606 100644 --- a/.github/actions/build-test-wasm/action.yaml +++ b/.github/actions/build-test-wasm/action.yaml @@ -22,15 +22,15 @@ runs: wasm-pack build --target nodejs ./crates/${{ inputs.crate }} --out-dir ../../prebuilds/${{ inputs.crate }} shell: bash - name: Test WASM - # The pipeline crate's tests are top-level node:test suites that need - # --test-force-exit (the wasm exporter keeps the event loop alive after - # a flush); the other wasm crates use plain test/wasm// scripts. + # pipeline and remote_config have top-level node:test suites; the other wasm crates use + # plain test/wasm// scripts. pipeline additionally needs --test-force-exit, since its + # wasm exporter keeps the event loop alive after a flush. run: | - if [ "${{ inputs.crate }}" = "pipeline" ]; then - node --test --test-force-exit test/pipeline.js - else - node test-wasm.js ${{ inputs.crate }} - fi + case "${{ inputs.crate }}" in + pipeline) node --test --test-force-exit test/pipeline.js ;; + remote_config) node --test test/remote-config.js ;; + *) node test-wasm.js ${{ inputs.crate }} ;; + esac shell: bash - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1019981..cc558bb 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -26,6 +26,7 @@ jobs: - library_config - datadog-js-zstd - pipeline + - remote_config steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - name: 'Use composite action' diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f5ce275..f7258aa 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -14,6 +14,7 @@ jobs: - library_config - datadog-js-zstd - pipeline + - remote_config steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - name: 'Use composite action' diff --git a/Cargo.lock b/Cargo.lock index 377fa06..e9ddb93 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -55,7 +55,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -142,6 +142,15 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc0b364ead1874514c8c2855ab558056ebfeb775653e7ae45ff72f28f8f3166c" +[[package]] +name = "bs58" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" +dependencies = [ + "tinyvec", +] + [[package]] name = "bumpalo" version = "3.20.2" @@ -357,7 +366,41 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a2785755761f3ddc1492979ce1e48d2c00d09311c39e4466429188f3dd6501" dependencies = [ "quote", - "syn", + "syn 2.0.117", +] + +[[package]] +name = "darling" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9865a50f7c335f53564bb694ef660825eb8610e0a53d3e11bf1b0d3df31e03b0" +dependencies = [ + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.117", +] + +[[package]] +name = "darling_macro" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.117", ] [[package]] @@ -379,6 +422,15 @@ dependencies = [ "uuid", ] +[[package]] +name = "deranged" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" +dependencies = [ + "serde_core", +] + [[package]] name = "digest" version = "0.10.7" @@ -524,7 +576,7 @@ checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -611,10 +663,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" dependencies = [ "fallible-iterator", - "indexmap", + "indexmap 2.14.0", "stable_deref_trait", ] +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + [[package]] name = "hashbrown" version = "0.15.5" @@ -768,6 +826,23 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + [[package]] name = "indexmap" version = "2.14.0" @@ -806,7 +881,7 @@ dependencies = [ "combine", "jni-sys 0.3.1", "log", - "thiserror", + "thiserror 1.0.69", "walkdir", "windows-sys 0.45.0", ] @@ -836,7 +911,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" dependencies = [ "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -911,18 +986,20 @@ dependencies = [ "anyhow", "bytes", "http", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "libdd-capabilities" version = "2.1.0" -source = "git+https://github.com/DataDog/libdatadog.git?rev=3081603d3c74f209be4e3be951f78a1a7469397f#3081603d3c74f209be4e3be951f78a1a7469397f" +source = "git+https://github.com/DataDog/libdatadog.git?tag=v40.0.0#ea75b04c3547037937730a14cf8a72a5ebf702d7" dependencies = [ "anyhow", "bytes", + "futures-channel", + "futures-util", "http", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -941,7 +1018,7 @@ dependencies = [ [[package]] name = "libdd-capabilities-impl" version = "3.0.0" -source = "git+https://github.com/DataDog/libdatadog.git?rev=3081603d3c74f209be4e3be951f78a1a7469397f#3081603d3c74f209be4e3be951f78a1a7469397f" +source = "git+https://github.com/DataDog/libdatadog.git?tag=v40.0.0#ea75b04c3547037937730a14cf8a72a5ebf702d7" dependencies = [ "anyhow", "bytes", @@ -980,7 +1057,7 @@ dependencies = [ "rustls-platform-verifier", "serde", "static_assertions", - "thiserror", + "thiserror 1.0.69", "tokio", "tokio-rustls", "tower-service", @@ -990,7 +1067,7 @@ dependencies = [ [[package]] name = "libdd-common" version = "5.1.0" -source = "git+https://github.com/DataDog/libdatadog.git?rev=3081603d3c74f209be4e3be951f78a1a7469397f#3081603d3c74f209be4e3be951f78a1a7469397f" +source = "git+https://github.com/DataDog/libdatadog.git?tag=v40.0.0#ea75b04c3547037937730a14cf8a72a5ebf702d7" dependencies = [ "anyhow", "bytes", @@ -1011,7 +1088,7 @@ dependencies = [ "regex", "serde", "static_assertions", - "thiserror", + "thiserror 1.0.69", "tokio", "tower-service", "windows-sys 0.52.0", @@ -1039,12 +1116,12 @@ dependencies = [ "page_size", "portable-atomic", "rand", - "schemars", + "schemars 0.8.22", "serde", "serde_json", "symbolic-common", "symbolic-demangle", - "thiserror", + "thiserror 1.0.69", "tokio", "uuid", "windows 0.59.0", @@ -1053,7 +1130,7 @@ dependencies = [ [[package]] name = "libdd-data-pipeline" version = "7.0.0" -source = "git+https://github.com/DataDog/libdatadog.git?rev=3081603d3c74f209be4e3be951f78a1a7469397f#3081603d3c74f209be4e3be951f78a1a7469397f" +source = "git+https://github.com/DataDog/libdatadog.git?tag=v40.0.0#ea75b04c3547037937730a14cf8a72a5ebf702d7" dependencies = [ "anyhow", "arc-swap", @@ -1072,7 +1149,7 @@ dependencies = [ "libdd-shared-runtime 2.0.0", "libdd-tinybytes", "libdd-trace-normalization", - "libdd-trace-protobuf 4.0.0 (git+https://github.com/DataDog/libdatadog.git?rev=3081603d3c74f209be4e3be951f78a1a7469397f)", + "libdd-trace-protobuf", "libdd-trace-stats", "libdd-trace-utils", "rmp-serde", @@ -1097,7 +1174,7 @@ dependencies = [ [[package]] name = "libdd-ddsketch" version = "1.1.0" -source = "git+https://github.com/DataDog/libdatadog.git?rev=3081603d3c74f209be4e3be951f78a1a7469397f#3081603d3c74f209be4e3be951f78a1a7469397f" +source = "git+https://github.com/DataDog/libdatadog.git?tag=v40.0.0#ea75b04c3547037937730a14cf8a72a5ebf702d7" dependencies = [ "prost", ] @@ -1105,24 +1182,27 @@ dependencies = [ [[package]] name = "libdd-dogstatsd-client" version = "4.0.0" -source = "git+https://github.com/DataDog/libdatadog.git?rev=3081603d3c74f209be4e3be951f78a1a7469397f#3081603d3c74f209be4e3be951f78a1a7469397f" +source = "git+https://github.com/DataDog/libdatadog.git?tag=v40.0.0#ea75b04c3547037937730a14cf8a72a5ebf702d7" dependencies = [ "anyhow", + "async-trait", "cadence", "http", "libdd-common 5.1.0", + "libdd-shared-runtime 2.0.0", "serde", + "tokio", "tracing", ] [[package]] name = "libdd-library-config" version = "3.0.0" -source = "git+https://github.com/DataDog/libdatadog.git?rev=0c6e2a5df2a163d34c4f385353ffc5d7257c72f4#0c6e2a5df2a163d34c4f385353ffc5d7257c72f4" +source = "git+https://github.com/DataDog/libdatadog.git?tag=v40.0.0#ea75b04c3547037937730a14cf8a72a5ebf702d7" dependencies = [ "anyhow", "libc", - "libdd-trace-protobuf 4.0.0 (git+https://github.com/DataDog/libdatadog.git?rev=0c6e2a5df2a163d34c4f385353ffc5d7257c72f4)", + "libdd-trace-protobuf", "memfd", "prost", "rand", @@ -1143,6 +1223,37 @@ dependencies = [ "paste", ] +[[package]] +name = "libdd-remote-config" +version = "2.0.0" +source = "git+https://github.com/DataDog/libdatadog.git?tag=v40.0.0#ea75b04c3547037937730a14cf8a72a5ebf702d7" +dependencies = [ + "anyhow", + "base64", + "bytes", + "futures-util", + "hashbrown 0.15.5", + "http", + "http-body-util", + "libdd-capabilities 2.1.0", + "libdd-capabilities-impl 3.0.0", + "libdd-common 5.1.0", + "libdd-trace-protobuf", + "manual_future", + "serde", + "serde_json", + "serde_with", + "sha2", + "strum", + "strum_macros", + "thiserror 2.0.19", + "time", + "tokio", + "tokio-util", + "tracing", + "uuid", +] + [[package]] name = "libdd-shared-runtime" version = "1.0.0" @@ -1163,7 +1274,7 @@ dependencies = [ [[package]] name = "libdd-shared-runtime" version = "2.0.0" -source = "git+https://github.com/DataDog/libdatadog.git?rev=3081603d3c74f209be4e3be951f78a1a7469397f#3081603d3c74f209be4e3be951f78a1a7469397f" +source = "git+https://github.com/DataDog/libdatadog.git?tag=v40.0.0#ea75b04c3547037937730a14cf8a72a5ebf702d7" dependencies = [ "async-trait", "futures", @@ -1207,7 +1318,7 @@ dependencies = [ [[package]] name = "libdd-tinybytes" version = "1.1.1" -source = "git+https://github.com/DataDog/libdatadog.git?rev=3081603d3c74f209be4e3be951f78a1a7469397f#3081603d3c74f209be4e3be951f78a1a7469397f" +source = "git+https://github.com/DataDog/libdatadog.git?tag=v40.0.0#ea75b04c3547037937730a14cf8a72a5ebf702d7" dependencies = [ "serde", ] @@ -1215,21 +1326,21 @@ dependencies = [ [[package]] name = "libdd-trace-normalization" version = "3.0.0" -source = "git+https://github.com/DataDog/libdatadog.git?rev=3081603d3c74f209be4e3be951f78a1a7469397f#3081603d3c74f209be4e3be951f78a1a7469397f" +source = "git+https://github.com/DataDog/libdatadog.git?tag=v40.0.0#ea75b04c3547037937730a14cf8a72a5ebf702d7" dependencies = [ "anyhow", - "libdd-trace-protobuf 4.0.0 (git+https://github.com/DataDog/libdatadog.git?rev=3081603d3c74f209be4e3be951f78a1a7469397f)", + "libdd-trace-protobuf", ] [[package]] name = "libdd-trace-obfuscation" version = "5.0.0" -source = "git+https://github.com/DataDog/libdatadog.git?rev=3081603d3c74f209be4e3be951f78a1a7469397f#3081603d3c74f209be4e3be951f78a1a7469397f" +source = "git+https://github.com/DataDog/libdatadog.git?tag=v40.0.0#ea75b04c3547037937730a14cf8a72a5ebf702d7" dependencies = [ "anyhow", "fluent-uri", "libdd-common 5.1.0", - "libdd-trace-protobuf 4.0.0 (git+https://github.com/DataDog/libdatadog.git?rev=3081603d3c74f209be4e3be951f78a1a7469397f)", + "libdd-trace-protobuf", "libdd-trace-utils", "log", "percent-encoding", @@ -1240,17 +1351,7 @@ dependencies = [ [[package]] name = "libdd-trace-protobuf" version = "4.0.0" -source = "git+https://github.com/DataDog/libdatadog.git?rev=0c6e2a5df2a163d34c4f385353ffc5d7257c72f4#0c6e2a5df2a163d34c4f385353ffc5d7257c72f4" -dependencies = [ - "prost", - "serde", - "serde_bytes", -] - -[[package]] -name = "libdd-trace-protobuf" -version = "4.0.0" -source = "git+https://github.com/DataDog/libdatadog.git?rev=3081603d3c74f209be4e3be951f78a1a7469397f#3081603d3c74f209be4e3be951f78a1a7469397f" +source = "git+https://github.com/DataDog/libdatadog.git?tag=v40.0.0#ea75b04c3547037937730a14cf8a72a5ebf702d7" dependencies = [ "prost", "serde", @@ -1260,7 +1361,7 @@ dependencies = [ [[package]] name = "libdd-trace-stats" version = "6.0.0" -source = "git+https://github.com/DataDog/libdatadog.git?rev=3081603d3c74f209be4e3be951f78a1a7469397f#3081603d3c74f209be4e3be951f78a1a7469397f" +source = "git+https://github.com/DataDog/libdatadog.git?tag=v40.0.0#ea75b04c3547037937730a14cf8a72a5ebf702d7" dependencies = [ "anyhow", "arc-swap", @@ -1275,7 +1376,7 @@ dependencies = [ "libdd-dogstatsd-client", "libdd-shared-runtime 2.0.0", "libdd-trace-obfuscation", - "libdd-trace-protobuf 4.0.0 (git+https://github.com/DataDog/libdatadog.git?rev=3081603d3c74f209be4e3be951f78a1a7469397f)", + "libdd-trace-protobuf", "libdd-trace-utils", "rmp-serde", "serde", @@ -1288,7 +1389,7 @@ dependencies = [ [[package]] name = "libdd-trace-utils" version = "9.0.0" -source = "git+https://github.com/DataDog/libdatadog.git?rev=3081603d3c74f209be4e3be951f78a1a7469397f#3081603d3c74f209be4e3be951f78a1a7469397f" +source = "git+https://github.com/DataDog/libdatadog.git?tag=v40.0.0#ea75b04c3547037937730a14cf8a72a5ebf702d7" dependencies = [ "anyhow", "base64", @@ -1299,14 +1400,14 @@ dependencies = [ "http", "http-body", "http-body-util", - "indexmap", + "indexmap 2.14.0", "itoa", "libdd-capabilities 2.1.0", "libdd-capabilities-impl 3.0.0", "libdd-common 5.1.0", "libdd-tinybytes", "libdd-trace-normalization", - "libdd-trace-protobuf 4.0.0 (git+https://github.com/DataDog/libdatadog.git?rev=3081603d3c74f209be4e3be951f78a1a7469397f)", + "libdd-trace-protobuf", "prost", "rand", "rmp", @@ -1362,6 +1463,15 @@ version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" +[[package]] +name = "manual_future" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c72f11f1d8e0c453cbd8042dfb83c2b50384f78a5a5d41019627c5f2062ece" +dependencies = [ + "futures-util", +] + [[package]] name = "memchr" version = "2.8.0" @@ -1462,7 +1572,7 @@ dependencies = [ "napi-derive-backend", "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -1475,7 +1585,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -1521,6 +1631,12 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "num-conv" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" + [[package]] name = "num-derive" version = "0.4.2" @@ -1529,7 +1645,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -1774,7 +1890,7 @@ checksum = "d9b20ed30f105399776b9c883e68e536ef602a16ae6f596d2c473591d6ad64c6" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -1797,7 +1913,7 @@ dependencies = [ "libdd-common 5.1.0", "libdd-data-pipeline", "libdd-shared-runtime 2.0.0", - "libdd-trace-protobuf 4.0.0 (git+https://github.com/DataDog/libdatadog.git?rev=3081603d3c74f209be4e3be951f78a1a7469397f)", + "libdd-trace-protobuf", "libdd-trace-stats", "libdd-trace-utils", "rmp-serde", @@ -1825,6 +1941,12 @@ dependencies = [ "serde", ] +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "ppv-lite86" version = "0.2.21" @@ -1841,7 +1963,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", - "syn", + "syn 2.0.117", ] [[package]] @@ -1859,7 +1981,7 @@ version = "0.1.0" dependencies = [ "anyhow", "libdd-library-config", - "libdd-trace-protobuf 4.0.0 (git+https://github.com/DataDog/libdatadog.git?rev=0c6e2a5df2a163d34c4f385353ffc5d7257c72f4)", + "libdd-trace-protobuf", "napi", "napi-derive", ] @@ -1884,7 +2006,7 @@ dependencies = [ "itertools", "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -1955,7 +2077,7 @@ checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -1987,6 +2109,25 @@ version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" +[[package]] +name = "remote-config" +version = "0.1.0" +dependencies = [ + "console_error_panic_hook", + "getrandom 0.2.17", + "js-sys", + "libdatadog-nodejs-capabilities", + "libdd-common 5.1.0", + "libdd-remote-config", + "serde", + "serde-wasm-bindgen", + "serde_json", + "uuid", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-bindgen-test", +] + [[package]] name = "ring" version = "0.17.14" @@ -2171,6 +2312,30 @@ dependencies = [ "serde_json", ] +[[package]] +name = "schemars" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd191f9397d57d581cddd31014772520aa448f65ef991055d7f61582c65165f" +dependencies = [ + "dyn-clone", + "ref-cast", + "serde", + "serde_json", +] + +[[package]] +name = "schemars" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "687274d293b6cdc6e73e0fee520bf2049650090d7164f87672d212a3c530cf4a" +dependencies = [ + "dyn-clone", + "ref-cast", + "serde", + "serde_json", +] + [[package]] name = "schemars_derive" version = "0.8.22" @@ -2180,7 +2345,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn", + "syn 2.0.117", ] [[package]] @@ -2269,7 +2434,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -2280,7 +2445,7 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -2289,7 +2454,7 @@ version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" dependencies = [ - "indexmap", + "indexmap 2.14.0", "itoa", "memchr", "serde", @@ -2297,13 +2462,45 @@ dependencies = [ "zmij", ] +[[package]] +name = "serde_with" +version = "3.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a5c54c7310e7b8b9577c286d7e399ddd876c3e12b3ed917a8aabc4b96e9e8c" +dependencies = [ + "base64", + "bs58", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.14.0", + "schemars 0.9.0", + "schemars 1.2.2", + "serde_core", + "serde_json", + "serde_with_macros", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "3.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84d57bc0c8b9a17920c178daa6bb924850d54a9c97ab45194bb8c17ad66bb660" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "serde_yaml" version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "indexmap", + "indexmap 2.14.0", "itoa", "ryu", "serde", @@ -2367,6 +2564,31 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "strum" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" + +[[package]] +name = "strum_macros" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.117", +] + [[package]] name = "subtle" version = "2.6.1" @@ -2408,6 +2630,17 @@ 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 = "sys-info" version = "0.9.1" @@ -2430,7 +2663,16 @@ version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ - "thiserror-impl", + "thiserror-impl 1.0.69", +] + +[[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]] @@ -2441,9 +2683,65 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] +[[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 = "time" +version = "0.3.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb87b95ec50ddfa440816d227a17b2ccbdda963a316a727fda0fc4334f7d134" +dependencies = [ + "deranged", + "num-conv", + "powerfmt", + "serde_core", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109" + +[[package]] +name = "time-macros" +version = "0.2.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e689342a48d2ea927c87ea50cabf8594854bf940e9310208848d680d668ed85" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tinyvec" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb4ebadaa0af04fab11ae01eb5f9fdb5f9c5b875506e210e71c07873528baa7f" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + [[package]] name = "tokio" version = "1.52.1" @@ -2467,7 +2765,7 @@ checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -2663,7 +2961,7 @@ dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn", + "syn 2.0.117", "wasm-bindgen-shared", ] @@ -2706,7 +3004,7 @@ checksum = "c610311887f9e6599a546d278d12d69dfd3a3e92639b2129e4b11ad6cf1961d6" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -2732,7 +3030,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" dependencies = [ "anyhow", - "indexmap", + "indexmap 2.14.0", "wasm-encoder", "wasmparser", ] @@ -2745,7 +3043,7 @@ checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" dependencies = [ "bitflags", "hashbrown 0.15.5", - "indexmap", + "indexmap 2.14.0", "semver", ] @@ -2852,7 +3150,7 @@ checksum = "83577b051e2f49a058c308f17f273b570a6a758386fc291b5f6a934dd84e48c1" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -2863,7 +3161,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -2874,7 +3172,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -3238,9 +3536,9 @@ checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" dependencies = [ "anyhow", "heck", - "indexmap", + "indexmap 2.14.0", "prettyplease", - "syn", + "syn 2.0.117", "wasm-metadata", "wit-bindgen-core", "wit-component", @@ -3256,7 +3554,7 @@ dependencies = [ "prettyplease", "proc-macro2", "quote", - "syn", + "syn 2.0.117", "wit-bindgen-core", "wit-bindgen-rust", ] @@ -3269,7 +3567,7 @@ checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" dependencies = [ "anyhow", "bitflags", - "indexmap", + "indexmap 2.14.0", "log", "serde", "serde_derive", @@ -3288,7 +3586,7 @@ checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" dependencies = [ "anyhow", "id-arena", - "indexmap", + "indexmap 2.14.0", "log", "semver", "serde", @@ -3315,7 +3613,7 @@ checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] diff --git a/LICENSE-3rdparty.csv b/LICENSE-3rdparty.csv index 2a79a4c..fbc9b55 100644 --- a/LICENSE-3rdparty.csv +++ b/LICENSE-3rdparty.csv @@ -1,26 +1,57 @@ Component,Origin,License,Copyright -addr2line,https://github.com/gimli-rs/addr2line,Apache-2.0 OR MIT,The addr2line Authors -adler,https://github.com/jonas-schievink/adler,0BSD OR MIT OR Apache-2.0,Jonas Schievink +adler2,https://github.com/oyvindln/adler2,0BSD OR MIT OR Apache-2.0,"Jonas Schievink , oyvindln " aho-corasick,https://github.com/BurntSushi/aho-corasick,Unlicense OR MIT,Andrew Gallant +allocator-api2,https://github.com/zakarumych/allocator-api2,MIT OR Apache-2.0,Zakarum +android_system_properties,https://github.com/nical/android_system_properties,MIT OR Apache-2.0,Nicolas Silva anyhow,https://github.com/dtolnay/anyhow,MIT OR Apache-2.0,David Tolnay -backtrace,https://github.com/rust-lang/backtrace-rs,MIT OR Apache-2.0,The Rust Project Developers -base64,https://github.com/marshallpierce/rust-base64,MIT OR Apache-2.0,"Alice Maz , Marshall Pierce " +arc-swap,https://github.com/vorner/arc-swap,MIT OR Apache-2.0,Michal 'vorner' Vaner +async-trait,https://github.com/dtolnay/async-trait,MIT OR Apache-2.0,David Tolnay +atomic-waker,https://github.com/smol-rs/atomic-waker,Apache-2.0 OR MIT,"Stjepan Glavina , Contributors to futures-rs" +aws-lc-rs,https://github.com/aws/aws-lc-rs,ISC AND (Apache-2.0 OR ISC),AWS-LibCrypto +aws-lc-sys,https://github.com/aws/aws-lc-rs,ISC AND (Apache-2.0 OR ISC) AND Apache-2.0 AND MIT AND BSD-3-Clause AND (Apache-2.0 OR ISC OR MIT) AND (Apache-2.0 OR ISC OR MIT-0),AWS-LC +base64,https://github.com/marshallpierce/rust-base64,MIT OR Apache-2.0,Marshall Pierce bitflags,https://github.com/bitflags/bitflags,MIT OR Apache-2.0,The Rust Project Developers +blazesym,https://github.com/libbpf/blazesym,BSD-3-Clause,"Daniel Müller , Kui-Feng " +block-buffer,https://github.com/RustCrypto/utils,MIT OR Apache-2.0,RustCrypto Developers +block2,https://github.com/madsmtm/objc2,MIT,Mads Marquart +borrow-or-share,https://github.com/yescallop/borrow-or-share,MIT-0,Scallop Ye +bs58,https://github.com/Nullus157/bs58-rs,MIT OR Apache-2.0,The bs58 Authors bumpalo,https://github.com/fitzgen/bumpalo,MIT OR Apache-2.0,Nick Fitzgerald -byteorder,https://github.com/BurntSushi/byteorder,Unlicense OR MIT,Andrew Gallant bytes,https://github.com/tokio-rs/bytes,MIT,"Carl Lerche , Sean McArthur " -cfg-if,https://github.com/alexcrichton/cfg-if,MIT OR Apache-2.0,Alex Crichton -collector,https://github.com/DataDog/libdatadog,Apache-2.0,The collector Authors +cadence,https://github.com/56quarters/cadence,Apache-2.0 OR MIT,Nick Pillitteri +cast,https://github.com/japaric/cast.rs,MIT OR Apache-2.0,Jorge Aparicio +cc,https://github.com/rust-lang/cc-rs,MIT OR Apache-2.0,Alex Crichton +cesu8,https://github.com/emk/cesu8-rs,Apache-2.0 OR MIT,Eric Kidd +cfg-if,https://github.com/rust-lang/cfg-if,MIT OR Apache-2.0,Alex Crichton +chrono,https://github.com/chronotope/chrono,MIT OR Apache-2.0,The chrono Authors +combine,https://github.com/Marwes/combine,MIT,Markus Westerlind +console_error_panic_hook,https://github.com/rustwasm/console_error_panic_hook,Apache-2.0 OR MIT,Nick Fitzgerald +const_format,https://github.com/rodrimati1992/const_format_crates,Zlib,rodrimati1992 +const_format_proc_macros,https://github.com/rodrimati1992/const_format_crates,Zlib,rodrimati1992 +convert_case,https://github.com/rutrum/convert-case,MIT,Rutrum core-foundation,https://github.com/servo/core-foundation-rs,MIT OR Apache-2.0,The Servo Project Developers -crc32fast,https://github.com/srijs/rust-crc32fast,MIT OR Apache-2.0,"Sam Rijs , Alex Crichton " -data-pipeline,https://github.com/DataDog/libdatadog,Apache-2.0,The data-pipeline Authors -datadog-trace-normalization,https://github.com/DataDog/libdatadog,Apache-2.0,David Lee -datadog-trace-protobuf,https://github.com/DataDog/libdatadog,Apache-2.0,David Lee -datadog-trace-utils,https://github.com/DataDog/libdatadog,Apache-2.0,David Lee -ddcommon,https://github.com/DataDog/libdatadog,Apache-2.0,The ddcommon Authors +core-foundation-sys,https://github.com/servo/core-foundation-rs,MIT OR Apache-2.0,The Servo Project Developers +cpp_demangle,https://github.com/gimli-rs/cpp_demangle,MIT OR Apache-2.0,"Nick Fitzgerald , Jim Blandy , Kyle Huey " +cpufeatures,https://github.com/RustCrypto/utils,MIT OR Apache-2.0,RustCrypto Developers +crossbeam-channel,https://github.com/crossbeam-rs/crossbeam,MIT OR Apache-2.0,The crossbeam-channel Authors +crossbeam-utils,https://github.com/crossbeam-rs/crossbeam,MIT OR Apache-2.0,The crossbeam-utils Authors +crypto-common,https://github.com/RustCrypto/traits,MIT OR Apache-2.0,RustCrypto Developers +ctor,https://github.com/mmastrac/rust-ctor,Apache-2.0 OR MIT,Matt Mastracci +darling,https://github.com/TedDriggs/darling,MIT,Ted Driggs +darling_core,https://github.com/TedDriggs/darling,MIT,Ted Driggs +darling_macro,https://github.com/TedDriggs/darling,MIT,Ted Driggs +debugid,https://github.com/getsentry/rust-debugid,Apache-2.0,Sentry +deranged,https://github.com/jhpratt/deranged,MIT OR Apache-2.0,Jacob Pratt +digest,https://github.com/RustCrypto/traits,MIT OR Apache-2.0,RustCrypto Developers +dispatch2,https://github.com/madsmtm/objc2,Zlib OR Apache-2.0 OR MIT,"Mads Marquart , Mary " +dyn-clone,https://github.com/dtolnay/dyn-clone,MIT OR Apache-2.0,David Tolnay either,https://github.com/rayon-rs/either,MIT OR Apache-2.0,bluss -flate2,https://github.com/rust-lang/flate2-rs,MIT OR Apache-2.0,"Alex Crichton , Josh Triplett " -fnv,https://github.com/servo/rust-fnv,Apache-2.0 OR MIT,Alex Crichton +equivalent,https://github.com/indexmap-rs/equivalent,Apache-2.0 OR MIT,The equivalent Authors +errno,https://github.com/lambda-fairy/rust-errno,MIT OR Apache-2.0,"Chris Wong , Dan Gohman " +fallible-iterator,https://github.com/sfackler/rust-fallible-iterator,MIT OR Apache-2.0,Steven Fackler +find-msvc-tools,https://github.com/rust-lang/cc-rs,MIT OR Apache-2.0,The find-msvc-tools Authors +fluent-uri,https://github.com/yescallop/fluent-uri-rs,MIT,Scallop Ye +foldhash,https://github.com/orlp/foldhash,Zlib,Orson Peters futures,https://github.com/rust-lang/futures-rs,MIT OR Apache-2.0,The futures Authors futures-channel,https://github.com/rust-lang/futures-rs,MIT OR Apache-2.0,The futures-channel Authors futures-core,https://github.com/rust-lang/futures-rs,MIT OR Apache-2.0,The futures-core Authors @@ -30,91 +61,253 @@ futures-macro,https://github.com/rust-lang/futures-rs,MIT OR Apache-2.0,The futu futures-sink,https://github.com/rust-lang/futures-rs,MIT OR Apache-2.0,The futures-sink Authors futures-task,https://github.com/rust-lang/futures-rs,MIT OR Apache-2.0,The futures-task Authors futures-util,https://github.com/rust-lang/futures-rs,MIT OR Apache-2.0,The futures-util Authors +generic-array,https://github.com/fizyk20/generic-array,MIT,"Bartłomiej Kamiński , Aaron Trent " getrandom,https://github.com/rust-random/getrandom,MIT OR Apache-2.0,The Rand Project Developers gimli,https://github.com/gimli-rs/gimli,MIT OR Apache-2.0,The gimli Authors -hermit-abi,https://github.com/hermit-os/hermit-rs,MIT OR Apache-2.0,Stefan Lankes +hashbrown,https://github.com/rust-lang/hashbrown,MIT OR Apache-2.0,Amanieu d'Antras +heck,https://github.com/withoutboats/heck,MIT OR Apache-2.0,The heck Authors hex,https://github.com/KokaKiwi/rust-hex,MIT OR Apache-2.0,KokaKiwi http,https://github.com/hyperium/http,MIT OR Apache-2.0,"Alex Crichton , Carl Lerche , Sean McArthur " http-body,https://github.com/hyperium/http-body,MIT,"Carl Lerche , Lucio Franco , Sean McArthur " +http-body-util,https://github.com/hyperium/http-body,MIT,"Carl Lerche , Lucio Franco , Sean McArthur " httparse,https://github.com/seanmonstar/httparse,MIT OR Apache-2.0,Sean McArthur -httpdate,https://github.com/pyfisch/httpdate,MIT OR Apache-2.0,Pyfisch hyper,https://github.com/hyperium/hyper,MIT,Sean McArthur -hyper-rustls,https://github.com/ctz/hyper-rustls,Apache-2.0 OR ISC OR MIT,The hyper-rustls Authors +hyper-rustls,https://github.com/rustls/hyper-rustls,Apache-2.0 OR ISC OR MIT,The hyper-rustls Authors +hyper-util,https://github.com/hyperium/hyper-util,MIT,Sean McArthur +iana-time-zone,https://github.com/strawlab/iana-time-zone,MIT OR Apache-2.0,"Andrew Straw , René Kijewski , Ryan Lopopolo " +iana-time-zone-haiku,https://github.com/strawlab/iana-time-zone,MIT OR Apache-2.0,René Kijewski +id-arena,https://github.com/fitzgen/id-arena,MIT OR Apache-2.0,"Nick Fitzgerald , Aleksey Kladov " +ident_case,https://github.com/TedDriggs/ident_case,MIT OR Apache-2.0,Ted Driggs +indexmap,https://github.com/bluss/indexmap,Apache-2.0 OR MIT,The indexmap Authors +indexmap,https://github.com/indexmap-rs/indexmap,Apache-2.0 OR MIT,The indexmap Authors itertools,https://github.com/rust-itertools/itertools,MIT OR Apache-2.0,bluss itoa,https://github.com/dtolnay/itoa,MIT OR Apache-2.0,David Tolnay -js-sys,https://github.com/rustwasm/wasm-bindgen/tree/master/crates/js-sys,MIT OR Apache-2.0,The wasm-bindgen Developers -lazy_static,https://github.com/rust-lang-nursery/lazy-static.rs,MIT OR Apache-2.0,Marvin Löbel +jni,https://github.com/jni-rs/jni-rs,MIT OR Apache-2.0,Josh Chase +jni-sys,https://github.com/jni-rs/jni-sys,MIT OR Apache-2.0,Steven Fackler +jni-sys,https://github.com/jni-rs/jni-sys,MIT OR Apache-2.0,"Steven Fackler , Robert Bragg " +jni-sys-macros,https://github.com/jni-rs/jni-sys,MIT OR Apache-2.0,Robert Bragg +jobserver,https://github.com/rust-lang/jobserver-rs,MIT OR Apache-2.0,Alex Crichton +js-sys,https://github.com/wasm-bindgen/wasm-bindgen/tree/master/crates/js-sys,MIT OR Apache-2.0,The wasm-bindgen Developers +konst,https://github.com/rodrimati1992/konst,Zlib,rodrimati1992 +konst_macro_rules,https://github.com/rodrimati1992/konst,Zlib,rodrimati1992 +leb128fmt,https://github.com/bluk/leb128fmt,MIT OR Apache-2.0,Bryant Luk libc,https://github.com/rust-lang/libc,MIT OR Apache-2.0,The Rust Project Developers +libdd-capabilities,https://github.com/DataDog/libdatadog/tree/main/libdd-capabilities,Apache-2.0,The libdd-capabilities Authors +libdd-capabilities-impl,https://github.com/DataDog/libdatadog/tree/main/libdd-capabilities-impl,Apache-2.0,The libdd-capabilities-impl Authors +libdd-common,https://github.com/DataDog/libdatadog/tree/main/datadog-common,Apache-2.0,The libdd-common Authors +libdd-crashtracker,https://github.com/DataDog/libdatadog/tree/main/libdd-crashtracker,Apache-2.0,The libdd-crashtracker Authors +libdd-data-pipeline,https://github.com/DataDog/libdatadog/tree/main/libdd-data-pipeline,Apache-2.0,The libdd-data-pipeline Authors +libdd-ddsketch,https://github.com/DataDog/libdatadog/tree/main/libdd-ddsketch,Apache-2.0,The libdd-ddsketch Authors +libdd-dogstatsd-client,https://github.com/DataDog/libdatadog/tree/main/libdd-dogstatsd-client,Apache-2.0,The libdd-dogstatsd-client Authors +libdd-library-config,https://github.com/DataDog/libdatadog/tree/main/libdd-library-config,Apache-2.0,The libdd-library-config Authors +libdd-libunwind-sys,https://github.com/DataDog/libdatadog/tree/main/libdd-libunwind-sys,Apache-2.0,The libdd-libunwind-sys Authors +libdd-remote-config,https://github.com/DataDog/libdatadog/tree/main/libdd-remote-config,Apache-2.0,Datadog Inc. +libdd-shared-runtime,https://github.com/DataDog/libdatadog/tree/main/libdd-shared-runtime,Apache-2.0,The libdd-shared-runtime Authors +libdd-telemetry,https://github.com/DataDog/libdatadog/tree/main/libdd-telemetry,Apache-2.0,The libdd-telemetry Authors +libdd-tinybytes,https://github.com/DataDog/libdatadog/tree/main/libdd-tinybytes,Apache-2.0,The libdd-tinybytes Authors +libdd-trace-normalization,https://github.com/DataDog/libdatadog/tree/main/libdd-trace-normalization,Apache-2.0,David Lee +libdd-trace-obfuscation,https://github.com/DataDog/libdatadog/tree/main/libdd-trace-obfuscation,Apache-2.0,Datadog Inc. +libdd-trace-protobuf,https://github.com/DataDog/libdatadog/tree/main/libdd-trace-protobuf,Apache-2.0,The libdd-trace-protobuf Authors +libdd-trace-stats,https://github.com/DataDog/libdatadog/tree/main/libdd-trace-stats,Apache-2.0,The libdd-trace-stats Authors +libdd-trace-utils,https://github.com/DataDog/libdatadog/tree/main/libdd-trace-utils,Apache-2.0,The libdd-trace-utils Authors libloading,https://github.com/nagisa/rust_libloading,ISC,Simonas Kazlauskas +libm,https://github.com/rust-lang/compiler-builtins,MIT,"Alex Crichton , Amanieu d'Antras , Jorge Aparicio , Trevor Gross " +linux-raw-sys,https://github.com/sunfishcode/linux-raw-sys,Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT,Dan Gohman log,https://github.com/rust-lang/log,MIT OR Apache-2.0,The Rust Project Developers +manual_future,https://github.com/dmarcuse/manual_future,MIT,Dana Marcuse memchr,https://github.com/BurntSushi/memchr,Unlicense OR MIT,"Andrew Gallant , bluss" -miniz_oxide,https://github.com/Frommi/miniz_oxide/tree/master/miniz_oxide,MIT OR Zlib OR Apache-2.0,"Frommi , oyvindln " +memfd,https://github.com/lucab/memfd-rs,MIT OR Apache-2.0,"Luca Bruno , Simonas Kazlauskas " +memmap2,https://github.com/RazrFalcon/memmap2-rs,MIT OR Apache-2.0,"Dan Burkert , Yevhenii Reizner , The Contributors" +memoffset,https://github.com/Gilnaa/memoffset,MIT,Gilad Naaman +minicov,https://github.com/Amanieu/minicov,Apache-2.0 OR MIT,Amanieu d'Antras +miniz_oxide,https://github.com/Frommi/miniz_oxide/tree/master/miniz_oxide,MIT OR Zlib OR Apache-2.0,"Frommi , oyvindln , Rich Geldreich richgel99@gmail.com" mio,https://github.com/tokio-rs/mio,MIT,"Carl Lerche , Thomas de Zeeuw , Tokio Contributors " -neon,https://github.com/neon-bindings/neon,MIT OR Apache-2.0,Dave Herman +msvc-demangler,https://github.com/mstange/msvc-demangler-rust,MIT OR NCSA,"Markus Stange , Jeff Muizelaar " +napi,https://github.com/napi-rs/napi-rs,MIT,"Nathan Sobo , Yinan Long " +napi-derive,https://github.com/napi-rs/napi-rs,MIT,"LongYinan , Forehalo " +napi-derive-backend,https://github.com/napi-rs/napi-rs,MIT,The napi-derive-backend Authors +napi-sys,https://github.com/napi-rs/napi-rs,MIT,LongYinan +nix,https://github.com/nix-rust/nix,MIT,The nix-rust Project Developers +nu-ansi-term,https://github.com/nushell/nu-ansi-term,MIT,"ogham@bsago.me, Ryan Scheel (Havvy) , Josh Triplett , The Nushell Project Developers" +num-conv,https://github.com/jhpratt/num-conv,MIT OR Apache-2.0,Jacob Pratt +num-derive,https://github.com/rust-num/num-derive,MIT OR Apache-2.0,The Rust Project Developers num-traits,https://github.com/rust-num/num-traits,MIT OR Apache-2.0,The Rust Project Developers -num_cpus,https://github.com/seanmonstar/num_cpus,MIT OR Apache-2.0,Sean McArthur -object,https://github.com/gimli-rs/object,Apache-2.0 OR MIT,The object Authors +objc2,https://github.com/madsmtm/objc2,MIT,Mads Marquart +objc2-cloud-kit,https://github.com/madsmtm/objc2,Zlib OR Apache-2.0 OR MIT,The objc2-cloud-kit Authors +objc2-core-data,https://github.com/madsmtm/objc2,Zlib OR Apache-2.0 OR MIT,The objc2-core-data Authors +objc2-core-foundation,https://github.com/madsmtm/objc2,Zlib OR Apache-2.0 OR MIT,The objc2-core-foundation Authors +objc2-core-graphics,https://github.com/madsmtm/objc2,Zlib OR Apache-2.0 OR MIT,The objc2-core-graphics Authors +objc2-core-image,https://github.com/madsmtm/objc2,Zlib OR Apache-2.0 OR MIT,The objc2-core-image Authors +objc2-core-location,https://github.com/madsmtm/objc2,Zlib OR Apache-2.0 OR MIT,The objc2-core-location Authors +objc2-core-text,https://github.com/madsmtm/objc2,Zlib OR Apache-2.0 OR MIT,The objc2-core-text Authors +objc2-encode,https://github.com/madsmtm/objc2,MIT,Mads Marquart +objc2-foundation,https://github.com/madsmtm/objc2,MIT,The objc2-foundation Authors +objc2-io-surface,https://github.com/madsmtm/objc2,Zlib OR Apache-2.0 OR MIT,The objc2-io-surface Authors +objc2-quartz-core,https://github.com/madsmtm/objc2,Zlib OR Apache-2.0 OR MIT,The objc2-quartz-core Authors +objc2-ui-kit,https://github.com/madsmtm/objc2,Zlib OR Apache-2.0 OR MIT,The objc2-ui-kit Authors +objc2-user-notifications,https://github.com/madsmtm/objc2,Zlib OR Apache-2.0 OR MIT,The objc2-user-notifications Authors once_cell,https://github.com/matklad/once_cell,MIT OR Apache-2.0,Aleksey Kladov +oorandom,https://hg.sr.ht/~icefox/oorandom,MIT,Simon Heath openssl-probe,https://github.com/alexcrichton/openssl-probe,MIT OR Apache-2.0,Alex Crichton +os_info,https://github.com/stanislav-tkach/os_info,MIT,"Jan Schulte , Stanislav Tkach " +page_size,https://github.com/Elzair/page_size_rs,MIT OR Apache-2.0,Philip Woods paste,https://github.com/dtolnay/paste,MIT OR Apache-2.0,David Tolnay +percent-encoding,https://github.com/servo/rust-url,MIT OR Apache-2.0,The rust-url developers pin-project,https://github.com/taiki-e/pin-project,Apache-2.0 OR MIT,The pin-project Authors pin-project-internal,https://github.com/taiki-e/pin-project,Apache-2.0 OR MIT,The pin-project-internal Authors pin-project-lite,https://github.com/taiki-e/pin-project-lite,Apache-2.0 OR MIT,The pin-project-lite Authors -pin-utils,https://github.com/rust-lang-nursery/pin-utils,MIT OR Apache-2.0,Josef Brandl +portable-atomic,https://github.com/taiki-e/portable-atomic,Apache-2.0 OR MIT,The portable-atomic Authors +powerfmt,https://github.com/jhpratt/powerfmt,MIT OR Apache-2.0,Jacob Pratt +ppv-lite86,https://github.com/cryptocorrosion/cryptocorrosion,MIT OR Apache-2.0,The CryptoCorrosion Contributors +prettyplease,https://github.com/dtolnay/prettyplease,MIT OR Apache-2.0,David Tolnay proc-macro2,https://github.com/dtolnay/proc-macro2,MIT OR Apache-2.0,"David Tolnay , Alex Crichton " -prost,https://github.com/tokio-rs/prost,Apache-2.0,"Dan Burkert , Lucio Franco " -prost-derive,https://github.com/tokio-rs/prost,Apache-2.0,"Dan Burkert , Lucio Franco , Tokio Contributors " +prost,https://github.com/tokio-rs/prost,Apache-2.0,"Dan Burkert , Lucio Franco , Casper Meijn , Tokio Contributors " +prost-derive,https://github.com/tokio-rs/prost,Apache-2.0,"Dan Burkert , Lucio Franco , Casper Meijn , Tokio Contributors " quote,https://github.com/dtolnay/quote,MIT OR Apache-2.0,David Tolnay +r-efi,https://github.com/r-efi/r-efi,MIT OR Apache-2.0 OR LGPL-2.1-or-later,The r-efi Authors +rand,https://github.com/rust-random/rand,MIT OR Apache-2.0,"The Rand Project Developers, The Rust Project Developers" +rand_chacha,https://github.com/rust-random/rand,MIT OR Apache-2.0,"The Rand Project Developers, The Rust Project Developers, The CryptoCorrosion Contributors" +rand_core,https://github.com/rust-random/rand,MIT OR Apache-2.0,"The Rand Project Developers, The Rust Project Developers" +ref-cast,https://github.com/dtolnay/ref-cast,MIT OR Apache-2.0,David Tolnay +ref-cast-impl,https://github.com/dtolnay/ref-cast,MIT OR Apache-2.0,David Tolnay regex,https://github.com/rust-lang/regex,MIT OR Apache-2.0,"The Rust Project Developers, Andrew Gallant " -regex-automata,https://github.com/rust-lang/regex/tree/master/regex-automata,MIT OR Apache-2.0,"The Rust Project Developers, Andrew Gallant " -regex-syntax,https://github.com/rust-lang/regex/tree/master/regex-syntax,MIT OR Apache-2.0,"The Rust Project Developers, Andrew Gallant " -ring,https://github.com/briansmith/ring,OpenSSL license,Brian Smith -rmp,https://github.com/3Hren/msgpack-rust,MIT,Evgeny Safronov +regex-automata,https://github.com/rust-lang/regex,MIT OR Apache-2.0,"The Rust Project Developers, Andrew Gallant " +regex-syntax,https://github.com/rust-lang/regex,MIT OR Apache-2.0,"The Rust Project Developers, Andrew Gallant " +ring,https://github.com/briansmith/ring,Apache-2.0 AND ISC,The ring Authors +rmp,https://github.com/3Hren/msgpack-rust,MIT,"Evgeny Safronov , Kornel " rmp-serde,https://github.com/3Hren/msgpack-rust,MIT,Evgeny Safronov -rustc-demangle,https://github.com/alexcrichton/rustc-demangle,MIT OR Apache-2.0,Alex Crichton +rmpv,https://github.com/3Hren/msgpack-rust,MIT,Evgeny Safronov +rustc-demangle,https://github.com/rust-lang/rustc-demangle,MIT OR Apache-2.0,Alex Crichton +rustc-hash,https://github.com/rust-lang/rustc-hash,Apache-2.0 OR MIT,The Rust Project Developers +rustix,https://github.com/bytecodealliance/rustix,Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT,"Dan Gohman , Jakub Konka " rustls,https://github.com/rustls/rustls,Apache-2.0 OR ISC OR MIT,The rustls Authors -rustls-native-certs,https://github.com/ctz/rustls-native-certs,Apache-2.0 OR ISC OR MIT,The rustls-native-certs Authors -rustls-pemfile,https://github.com/rustls/pemfile,Apache-2.0 OR ISC OR MIT,The rustls-pemfile Authors +rustls-native-certs,https://github.com/rustls/rustls-native-certs,Apache-2.0 OR ISC OR MIT,The rustls-native-certs Authors +rustls-pki-types,https://github.com/rustls/pki-types,MIT OR Apache-2.0,The rustls-pki-types Authors +rustls-platform-verifier,https://github.com/rustls/rustls-platform-verifier,MIT OR Apache-2.0,The rustls-platform-verifier Authors +rustls-platform-verifier-android,https://github.com/rustls/rustls-platform-verifier,MIT OR Apache-2.0,The rustls-platform-verifier-android Authors +rustls-webpki,https://github.com/rustls/webpki,ISC,The rustls-webpki Authors +rustversion,https://github.com/dtolnay/rustversion,MIT OR Apache-2.0,David Tolnay ryu,https://github.com/dtolnay/ryu,Apache-2.0 OR BSL-1.0,David Tolnay +same-file,https://github.com/BurntSushi/same-file,Unlicense OR MIT,Andrew Gallant schannel,https://github.com/steffengy/schannel-rs,MIT,"Steven Fackler , Steffen Butzer " -sct,https://github.com/rustls/sct.rs,Apache-2.0 OR ISC OR MIT,Joseph Birr-Pixton +schemars,https://github.com/GREsau/schemars,MIT,Graham Esau +schemars_derive,https://github.com/GREsau/schemars,MIT,Graham Esau security-framework,https://github.com/kornelski/rust-security-framework,MIT OR Apache-2.0,"Steven Fackler , Kornel " +security-framework-sys,https://github.com/kornelski/rust-security-framework,MIT OR Apache-2.0,"Steven Fackler , Kornel " semver,https://github.com/dtolnay/semver,MIT OR Apache-2.0,David Tolnay -send_wrapper,https://github.com/thk1/send_wrapper,MIT OR Apache-2.0,Thomas Keh serde,https://github.com/serde-rs/serde,MIT OR Apache-2.0,"Erick Tryzelaar , David Tolnay " +serde-transcode,https://github.com/sfackler/serde-transcode,MIT OR Apache-2.0,Steven Fackler +serde-wasm-bindgen,https://github.com/cloudflare/serde-wasm-bindgen,MIT,Ingvar Stepanyan serde_bytes,https://github.com/serde-rs/bytes,MIT OR Apache-2.0,David Tolnay +serde_core,https://github.com/serde-rs/serde,MIT OR Apache-2.0,"Erick Tryzelaar , David Tolnay " +serde_derive,https://github.com/serde-rs/serde,MIT OR Apache-2.0,"Erick Tryzelaar , David Tolnay " +serde_derive_internals,https://github.com/serde-rs/serde,MIT OR Apache-2.0,"Erick Tryzelaar , David Tolnay " serde_json,https://github.com/serde-rs/json,MIT OR Apache-2.0,"Erick Tryzelaar , David Tolnay " +serde_with,https://github.com/jonasbb/serde_with,MIT OR Apache-2.0,"Jonas Bushart, Marcin Kaźmierczak" +serde_with_macros,https://github.com/jonasbb/serde_with,MIT OR Apache-2.0,Jonas Bushart +serde_yaml,https://github.com/dtolnay/serde-yaml,MIT OR Apache-2.0,David Tolnay +sha2,https://github.com/RustCrypto/hashes,MIT OR Apache-2.0,RustCrypto Developers +shlex,https://github.com/comex/rust-shlex,MIT OR Apache-2.0,"comex , Fenhl , Adrian Taylor , Alex Touchet , Daniel Parks , Garrett Berg " +simd-adler32,https://github.com/mcountryman/simd-adler32,MIT,Marvin Countryman slab,https://github.com/tokio-rs/slab,MIT,Carl Lerche smallvec,https://github.com/servo/rust-smallvec,MIT OR Apache-2.0,The Servo Project Developers socket2,https://github.com/rust-lang/socket2,MIT OR Apache-2.0,"Alex Crichton , Thomas de Zeeuw " -spin,https://github.com/mvdnes/spin-rs,MIT,"Mathijs van de Nes , John Ericson " -spin,https://github.com/mvdnes/spin-rs,MIT,"Mathijs van de Nes , John Ericson , Joshua Barretto " +stable_deref_trait,https://github.com/storyyeller/stable_deref_trait,MIT OR Apache-2.0,Robert Grosse +static_assertions,https://github.com/nvzqz/static-assertions-rs,MIT OR Apache-2.0,Nikolai Vazquez +strsim,https://github.com/rapidfuzz/strsim-rs,MIT,"Danny Guo , maxbachmann " +strum,https://github.com/Peternator7/strum,MIT,Peter Glotfelty +strum_macros,https://github.com/Peternator7/strum,MIT,Peter Glotfelty +subtle,https://github.com/dalek-cryptography/subtle,BSD-3-Clause,"Isis Lovecruft , Henry de Valence " +symbolic-common,https://github.com/getsentry/symbolic,MIT,"Armin Ronacher , Jan Michael Auer " +symbolic-demangle,https://github.com/getsentry/symbolic,MIT,"Armin Ronacher , Jan Michael Auer " syn,https://github.com/dtolnay/syn,MIT OR Apache-2.0,David Tolnay -syn-mid,https://github.com/taiki-e/syn-mid,Apache-2.0 OR MIT,The syn-mid Authors +sys-info,https://github.com/FillZpp/sys-info-rs,MIT,Siyu Wang +thin-vec,https://github.com/mozilla/thin-vec,MIT OR Apache-2.0,Aria Beingessner +thiserror,https://github.com/dtolnay/thiserror,MIT OR Apache-2.0,David Tolnay +thiserror-impl,https://github.com/dtolnay/thiserror,MIT OR Apache-2.0,David Tolnay +time,https://github.com/time-rs/time,MIT OR Apache-2.0,"Jacob Pratt , Time contributors" +time-core,https://github.com/time-rs/time,MIT OR Apache-2.0,"Jacob Pratt , Time contributors" +time-macros,https://github.com/time-rs/time,MIT OR Apache-2.0,"Jacob Pratt , Time contributors" +tinyvec,https://github.com/Lokathor/tinyvec,Zlib OR Apache-2.0 OR MIT,Lokathor +tinyvec_macros,https://github.com/Soveu/tinyvec_macros,MIT OR Apache-2.0 OR Zlib,Soveu tokio,https://github.com/tokio-rs/tokio,MIT,Tokio Contributors -tokio-rustls,https://github.com/tokio-rs/tls,MIT OR Apache-2.0,quininer kel +tokio-macros,https://github.com/tokio-rs/tokio,MIT,Tokio Contributors +tokio-rustls,https://github.com/rustls/tokio-rustls,MIT OR Apache-2.0,The tokio-rustls Authors +tokio-util,https://github.com/tokio-rs/tokio,MIT,Tokio Contributors tower-service,https://github.com/tower-rs/tower,MIT,Tower Maintainers tracing,https://github.com/tokio-rs/tracing,MIT,"Eliza Weisman , Tokio Contributors " tracing-core,https://github.com/tokio-rs/tracing,MIT,Tokio Contributors try-lock,https://github.com/seanmonstar/try-lock,MIT,Sean McArthur -unicode-ident,https://github.com/dtolnay/unicode-ident,(MIT OR Apache-2.0) AND Unicode-DFS-2016,David Tolnay +typenum,https://github.com/paholg/typenum,MIT OR Apache-2.0,"Paho Lurie-Gregg , Andre Bogus " +unicode-ident,https://github.com/dtolnay/unicode-ident,(MIT OR Apache-2.0) AND Unicode-3.0,David Tolnay +unicode-segmentation,https://github.com/unicode-rs/unicode-segmentation,MIT OR Apache-2.0,"kwantam , Manish Goregaokar " +unicode-xid,https://github.com/unicode-rs/unicode-xid,MIT OR Apache-2.0,"erick.tryzelaar , kwantam , Manish Goregaokar " +unsafe-libyaml,https://github.com/dtolnay/unsafe-libyaml,MIT,David Tolnay untrusted,https://github.com/briansmith/untrusted,ISC,Brian Smith +uuid,https://github.com/uuid-rs/uuid,Apache-2.0 OR MIT,"Ashley Mannix, Dylan DPC, Hunar Roop Kahlon" want,https://github.com/seanmonstar/want,MIT,Sean McArthur wasi,https://github.com/bytecodealliance/wasi,Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT,The Cranelift Project Developers -wasm-bindgen,https://github.com/rustwasm/wasm-bindgen,MIT OR Apache-2.0,The wasm-bindgen Developers -wasm-bindgen-backend,https://github.com/rustwasm/wasm-bindgen/tree/master/crates/backend,MIT OR Apache-2.0,The wasm-bindgen Developers -wasm-bindgen-macro,https://github.com/rustwasm/wasm-bindgen/tree/master/crates/macro,MIT OR Apache-2.0,The wasm-bindgen Developers -wasm-bindgen-macro-support,https://github.com/rustwasm/wasm-bindgen/tree/master/crates/macro-support,MIT OR Apache-2.0,The wasm-bindgen Developers -wasm-bindgen-shared,https://github.com/rustwasm/wasm-bindgen/tree/master/crates/shared,MIT OR Apache-2.0,The wasm-bindgen Developers -web-sys,https://github.com/rustwasm/wasm-bindgen/tree/master/crates/web-sys,MIT OR Apache-2.0,The wasm-bindgen Developers -webpki,https://github.com/briansmith/webpki,ISC-style,Brian Smith +wasip2,https://github.com/bytecodealliance/wasi-rs,Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT,The wasip2 Authors +wasip3,https://github.com/bytecodealliance/wasi-rs,Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT,The wasip3 Authors +wasm-bindgen,https://github.com/wasm-bindgen/wasm-bindgen,MIT OR Apache-2.0,The wasm-bindgen Developers +wasm-bindgen-futures,https://github.com/wasm-bindgen/wasm-bindgen/tree/master/crates/futures,MIT OR Apache-2.0,The wasm-bindgen Developers +wasm-bindgen-macro,https://github.com/wasm-bindgen/wasm-bindgen/tree/master/crates/macro,MIT OR Apache-2.0,The wasm-bindgen Developers +wasm-bindgen-macro-support,https://github.com/wasm-bindgen/wasm-bindgen/tree/master/crates/macro-support,MIT OR Apache-2.0,The wasm-bindgen Developers +wasm-bindgen-shared,https://github.com/wasm-bindgen/wasm-bindgen/tree/master/crates/shared,MIT OR Apache-2.0,The wasm-bindgen Developers +wasm-bindgen-test-macro,https://github.com/wasm-bindgen/wasm-bindgen,MIT OR Apache-2.0,The wasm-bindgen Developers +wasm-bindgen-test-shared,https://github.com/rustwasm/wasm-bindgen/tree/master/crates/test-shared,MIT OR Apache-2.0,The wasm-bindgen Developers +wasm-encoder,https://github.com/bytecodealliance/wasm-tools/tree/main/crates/wasm-encoder,Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT,Nick Fitzgerald +wasm-metadata,https://github.com/bytecodealliance/wasm-tools/tree/main/crates/wasm-metadata,Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT,The wasm-metadata Authors +wasmparser,https://github.com/bytecodealliance/wasm-tools/tree/main/crates/wasmparser,Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT,Yury Delendik +web-time,https://github.com/daxpedda/web-time,MIT OR Apache-2.0,The web-time Authors +webpki-root-certs,https://github.com/rustls/webpki-roots,CDLA-Permissive-2.0,The webpki-root-certs Authors winapi,https://github.com/retep998/winapi-rs,MIT OR Apache-2.0,Peter Atashian +winapi-i686-pc-windows-gnu,https://github.com/retep998/winapi-rs,MIT OR Apache-2.0,Peter Atashian +winapi-util,https://github.com/BurntSushi/winapi-util,Unlicense OR MIT,Andrew Gallant +winapi-x86_64-pc-windows-gnu,https://github.com/retep998/winapi-rs,MIT OR Apache-2.0,Peter Atashian +windows,https://github.com/microsoft/windows-rs,MIT OR Apache-2.0,Microsoft +windows-core,https://github.com/microsoft/windows-rs,MIT OR Apache-2.0,Microsoft +windows-core,https://github.com/microsoft/windows-rs,MIT OR Apache-2.0,The windows-core Authors +windows-implement,https://github.com/microsoft/windows-rs,MIT OR Apache-2.0,Microsoft +windows-implement,https://github.com/microsoft/windows-rs,MIT OR Apache-2.0,The windows-implement Authors +windows-interface,https://github.com/microsoft/windows-rs,MIT OR Apache-2.0,The windows-interface Authors +windows-link,https://github.com/microsoft/windows-rs,MIT OR Apache-2.0,Microsoft +windows-link,https://github.com/microsoft/windows-rs,MIT OR Apache-2.0,The windows-link Authors +windows-result,https://github.com/microsoft/windows-rs,MIT OR Apache-2.0,Microsoft +windows-result,https://github.com/microsoft/windows-rs,MIT OR Apache-2.0,The windows-result Authors +windows-strings,https://github.com/microsoft/windows-rs,MIT OR Apache-2.0,Microsoft +windows-strings,https://github.com/microsoft/windows-rs,MIT OR Apache-2.0,The windows-strings Authors windows-sys,https://github.com/microsoft/windows-rs,MIT OR Apache-2.0,Microsoft +windows-sys,https://github.com/microsoft/windows-rs,MIT OR Apache-2.0,The windows-sys Authors windows-targets,https://github.com/microsoft/windows-rs,MIT OR Apache-2.0,Microsoft +windows-targets,https://github.com/microsoft/windows-rs,MIT OR Apache-2.0,The windows-targets Authors windows_aarch64_gnullvm,https://github.com/microsoft/windows-rs,MIT OR Apache-2.0,Microsoft +windows_aarch64_gnullvm,https://github.com/microsoft/windows-rs,MIT OR Apache-2.0,The windows_aarch64_gnullvm Authors windows_aarch64_msvc,https://github.com/microsoft/windows-rs,MIT OR Apache-2.0,Microsoft +windows_aarch64_msvc,https://github.com/microsoft/windows-rs,MIT OR Apache-2.0,The windows_aarch64_msvc Authors windows_i686_gnu,https://github.com/microsoft/windows-rs,MIT OR Apache-2.0,Microsoft +windows_i686_gnu,https://github.com/microsoft/windows-rs,MIT OR Apache-2.0,The windows_i686_gnu Authors +windows_i686_gnullvm,https://github.com/microsoft/windows-rs,MIT OR Apache-2.0,Microsoft +windows_i686_gnullvm,https://github.com/microsoft/windows-rs,MIT OR Apache-2.0,The windows_i686_gnullvm Authors windows_i686_msvc,https://github.com/microsoft/windows-rs,MIT OR Apache-2.0,Microsoft +windows_i686_msvc,https://github.com/microsoft/windows-rs,MIT OR Apache-2.0,The windows_i686_msvc Authors windows_x86_64_gnu,https://github.com/microsoft/windows-rs,MIT OR Apache-2.0,Microsoft +windows_x86_64_gnu,https://github.com/microsoft/windows-rs,MIT OR Apache-2.0,The windows_x86_64_gnu Authors windows_x86_64_gnullvm,https://github.com/microsoft/windows-rs,MIT OR Apache-2.0,Microsoft +windows_x86_64_gnullvm,https://github.com/microsoft/windows-rs,MIT OR Apache-2.0,The windows_x86_64_gnullvm Authors windows_x86_64_msvc,https://github.com/microsoft/windows-rs,MIT OR Apache-2.0,Microsoft +windows_x86_64_msvc,https://github.com/microsoft/windows-rs,MIT OR Apache-2.0,The windows_x86_64_msvc Authors +winver,https://github.com/rhysd/winver,MIT,rhysd +wit-bindgen,https://github.com/bytecodealliance/wit-bindgen,Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT,Alex Crichton +wit-bindgen-core,https://github.com/bytecodealliance/wit-bindgen,Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT,Alex Crichton +wit-bindgen-rust,https://github.com/bytecodealliance/wit-bindgen,Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT,Alex Crichton +wit-bindgen-rust-macro,https://github.com/bytecodealliance/wit-bindgen,Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT,Alex Crichton +wit-component,https://github.com/bytecodealliance/wasm-tools/tree/main/crates/wit-component,Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT,Peter Huene +wit-parser,https://github.com/bytecodealliance/wasm-tools/tree/main/crates/wit-parser,Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT,Alex Crichton +zerocopy,https://github.com/google/zerocopy,BSD-2-Clause OR Apache-2.0 OR MIT,"Joshua Liebow-Feeser , Jack Wrenn " +zerocopy-derive,https://github.com/google/zerocopy,BSD-2-Clause OR Apache-2.0 OR MIT,"Joshua Liebow-Feeser , Jack Wrenn " +zeroize,https://github.com/RustCrypto/utils,Apache-2.0 OR MIT,The RustCrypto Project Developers +zmij,https://github.com/dtolnay/zmij,MIT,David Tolnay +zstd,https://github.com/gyscos/zstd-rs,MIT,Alexandre Bury +zstd-safe,https://github.com/gyscos/zstd-rs,MIT OR Apache-2.0,Alexandre Bury +zstd-sys,https://github.com/gyscos/zstd-rs,MIT OR Apache-2.0,Alexandre Bury diff --git a/crates/capabilities/Cargo.toml b/crates/capabilities/Cargo.toml index edb40ad..a535893 100644 --- a/crates/capabilities/Cargo.toml +++ b/crates/capabilities/Cargo.toml @@ -15,7 +15,7 @@ http = "1" bytes = "1.4" futures-core = "0.3" anyhow = "1" -libdd-capabilities = { git = "https://github.com/DataDog/libdatadog.git", rev = "3081603d3c74f209be4e3be951f78a1a7469397f" } +libdd-capabilities = { git = "https://github.com/DataDog/libdatadog.git", tag = "v40.0.0" } [dev-dependencies] wasm-bindgen-test = "0.3" diff --git a/crates/capabilities/src/http.rs b/crates/capabilities/src/http.rs index 4248cb3..e9c2b8c 100644 --- a/crates/capabilities/src/http.rs +++ b/crates/capabilities/src/http.rs @@ -32,6 +32,7 @@ extern "C" { port: u16, is_https: bool, socket_path: &str, + connection_pooling: bool, head_ptr: *const u8, head_len: u32, body_ptr: *const u8, @@ -52,11 +53,21 @@ extern "C" { /// [`crate::WasmCapabilities`] alongside the sleep and log-output capabilities /// that `TraceExporter` requires. #[derive(Debug, Clone)] -pub struct WasmHttpClient; +pub struct WasmHttpClient { + connection_pooling: bool, +} impl HttpClientCapability for WasmHttpClient { fn new_client() -> Self { - Self + Self { + connection_pooling: true, + } + } + + fn new_without_connection_pooling() -> Self { + Self { + connection_pooling: false, + } } #[allow(clippy::manual_async_fn)] @@ -101,6 +112,7 @@ impl HttpClientCapability for WasmHttpClient { port, is_https, &socket_path, + self.connection_pooling, head.as_ptr(), head.len() as u32, body.as_ptr(), diff --git a/crates/capabilities/src/http_transport.js b/crates/capabilities/src/http_transport.js index 962b6ba..dd6f450 100644 --- a/crates/capabilities/src/http_transport.js +++ b/crates/capabilities/src/http_transport.js @@ -171,7 +171,7 @@ module.exports._resetEntityHeadersCache = () => { cachedEntityHeaders = undefined } -module.exports.httpRequest = function (host, port, isHttps, socketPath, head_ptr, head_len, body_ptr, body_len, wasm_memory) { +module.exports.httpRequest = function (host, port, isHttps, socketPath, connectionPooling, head_ptr, head_len, body_ptr, body_len, wasm_memory) { // A non-empty socketPath routes over a Unix domain socket (or Windows named // pipe) instead of TCP. Sockets are always plaintext HTTP/1.1, so https is // ignored in that mode. @@ -201,9 +201,12 @@ module.exports.httpRequest = function (host, port, isHttps, socketPath, head_ptr // request options so the connection uses the correct method/path/headers // on both Node and Bun (host/port or socketPath drive the connection). const { method, path, headers } = parseRequestHead(applyEntityHeaders(headView)) + // `agent: false` gives this request its own short-lived agent rather than the global + // keep-alive one, which is what a caller asking for no connection pooling wants. const requestOptions = useSocket ? { socketPath, method, path, headers } : { host, port, method, path, headers } + if (!connectionPooling) requestOptions.agent = false const req = transport.request(requestOptions, (res) => { const chunks = [] res.on('data', chunk => chunks.push(chunk)) diff --git a/crates/capabilities/src/lib.rs b/crates/capabilities/src/lib.rs index e76a381..ca0c828 100644 --- a/crates/capabilities/src/lib.rs +++ b/crates/capabilities/src/lib.rs @@ -14,7 +14,8 @@ use std::time::Duration; use libdd_capabilities::env::{EnvCapability, EnvError}; use libdd_capabilities::file::{FileCapability, FileError, FileMetadata}; use libdd_capabilities::http::HttpError; -use libdd_capabilities::{HttpClientCapability, LogWriterCapability, MaybeSend, SleepCapability}; +// Re-exported so consumers can name the traits without depending on `libdd-capabilities` directly. +pub use libdd_capabilities::{HttpClientCapability, LogWriterCapability, MaybeSend, SleepCapability}; pub mod env; pub mod file; @@ -65,6 +66,13 @@ impl HttpClientCapability for WasmCapabilities { Self::new() } + fn new_without_connection_pooling() -> Self { + Self { + http: WasmHttpClient::new_without_connection_pooling(), + ..Self::new() + } + } + fn request( &self, req: ::http::Request<::bytes::Bytes>, diff --git a/crates/library_config/Cargo.toml b/crates/library_config/Cargo.toml index b6deab0..a3aa585 100644 --- a/crates/library_config/Cargo.toml +++ b/crates/library_config/Cargo.toml @@ -8,7 +8,7 @@ crate-type = ["cdylib", "rlib"] [dependencies] anyhow = "1" -libdd-library-config = { git = "https://github.com/DataDog/libdatadog.git", rev = "0c6e2a5df2a163d34c4f385353ffc5d7257c72f4" } +libdd-library-config = { git = "https://github.com/DataDog/libdatadog.git", tag = "v40.0.0" } wasm-bindgen = "0.2.100" serde = { version = "1.0", features = ["derive"] } diff --git a/crates/pipeline/Cargo.toml b/crates/pipeline/Cargo.toml index 29fc272..4fb7d45 100644 --- a/crates/pipeline/Cargo.toml +++ b/crates/pipeline/Cargo.toml @@ -14,13 +14,13 @@ js-sys = "0.3" serde = { version = "1.0", features = ["derive"] } serde_json = "1" libdatadog-nodejs-capabilities = { path = "../capabilities" } -libdd-capabilities = { git = "https://github.com/DataDog/libdatadog.git", rev = "3081603d3c74f209be4e3be951f78a1a7469397f" } -libdd-common = { git = "https://github.com/DataDog/libdatadog.git", rev = "3081603d3c74f209be4e3be951f78a1a7469397f", default-features = false } -libdd-data-pipeline = { git = "https://github.com/DataDog/libdatadog.git", rev = "3081603d3c74f209be4e3be951f78a1a7469397f", default-features = false } -libdd-trace-utils = { git = "https://github.com/DataDog/libdatadog.git", rev = "3081603d3c74f209be4e3be951f78a1a7469397f", default-features = false, features = ["change-buffer"] } -libdd-trace-stats = { git = "https://github.com/DataDog/libdatadog.git", rev = "3081603d3c74f209be4e3be951f78a1a7469397f", default-features = false } -libdd-trace-protobuf = { git = "https://github.com/DataDog/libdatadog.git", rev = "3081603d3c74f209be4e3be951f78a1a7469397f", default-features = false } -libdd-shared-runtime = { git = "https://github.com/DataDog/libdatadog.git", rev = "3081603d3c74f209be4e3be951f78a1a7469397f", default-features = false } +libdd-capabilities = { git = "https://github.com/DataDog/libdatadog.git", tag = "v40.0.0" } +libdd-common = { git = "https://github.com/DataDog/libdatadog.git", tag = "v40.0.0", default-features = false } +libdd-data-pipeline = { git = "https://github.com/DataDog/libdatadog.git", tag = "v40.0.0", default-features = false } +libdd-trace-utils = { git = "https://github.com/DataDog/libdatadog.git", tag = "v40.0.0", default-features = false, features = ["change-buffer"] } +libdd-trace-stats = { git = "https://github.com/DataDog/libdatadog.git", tag = "v40.0.0", default-features = false } +libdd-trace-protobuf = { git = "https://github.com/DataDog/libdatadog.git", tag = "v40.0.0", default-features = false } +libdd-shared-runtime = { git = "https://github.com/DataDog/libdatadog.git", tag = "v40.0.0", default-features = false } web-time = "1" rmp-serde = "1" bytes = "1" diff --git a/crates/process_discovery/Cargo.toml b/crates/process_discovery/Cargo.toml index 32e9449..398ccc1 100644 --- a/crates/process_discovery/Cargo.toml +++ b/crates/process_discovery/Cargo.toml @@ -8,8 +8,8 @@ crate-type = ["cdylib", "rlib"] [dependencies] anyhow = "1" -libdd-library-config = { git = "https://github.com/DataDog/libdatadog.git", rev = "0c6e2a5df2a163d34c4f385353ffc5d7257c72f4", features = ["otel-thread-ctx"] } -libdd-trace-protobuf = { git = "https://github.com/DataDog/libdatadog.git", rev = "0c6e2a5df2a163d34c4f385353ffc5d7257c72f4" } +libdd-library-config = { git = "https://github.com/DataDog/libdatadog.git", tag = "v40.0.0", features = ["otel-thread-ctx"] } +libdd-trace-protobuf = { git = "https://github.com/DataDog/libdatadog.git", tag = "v40.0.0" } napi = { version = "2" } napi-derive = { version = "2", default-features = false } diff --git a/crates/remote_config/Cargo.toml b/crates/remote_config/Cargo.toml new file mode 100644 index 0000000..184d091 --- /dev/null +++ b/crates/remote_config/Cargo.toml @@ -0,0 +1,31 @@ +[package] +name = "remote-config" +version = "0.1.0" +edition = "2021" +description = "Wasm binding for libdatadog's remote config client" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +libdd-remote-config = { git = "https://github.com/DataDog/libdatadog.git", tag = "v40.0.0", default-features = false, features = ["client"] } +libdd-common = { git = "https://github.com/DataDog/libdatadog.git", tag = "v40.0.0", default-features = false } +libdatadog-nodejs-capabilities = { path = "../capabilities" } + +wasm-bindgen = "0.2" +js-sys = "0.3" +wasm-bindgen-futures = "0.4" +serde = { version = "1.0", features = ["derive"] } +serde-wasm-bindgen = "0.4" +serde_json = "1" +console_error_panic_hook = "0.1" + +[package.metadata.wasm-pack.profile.release] +wasm-opt = ["-O", "--all-features"] + +[target.'cfg(target_arch = "wasm32")'.dependencies] +getrandom = { version = "0.2", features = ["js"] } +uuid = { version = "1", features = ["js"] } + +[dev-dependencies] +wasm-bindgen-test = "0.3" diff --git a/crates/remote_config/src/lib.rs b/crates/remote_config/src/lib.rs new file mode 100644 index 0000000..0fae59a --- /dev/null +++ b/crates/remote_config/src/lib.rs @@ -0,0 +1,308 @@ +//! Wasm binding for libdatadog's remote config client. + +use std::cell::RefCell; +use std::rc::Rc; +use std::str::FromStr; +use std::sync::Arc; + +use libdatadog_nodejs_capabilities::{HttpClientCapability, WasmCapabilities}; +use libdd_remote_config::fetch::{ + ConfigApplyState, ConfigInvariants, ConfigOptions, SingleChangesFetcher, +}; +use libdd_remote_config::file_change_tracker::{Change, FilePath}; +use libdd_remote_config::file_storage::{RawFile, SimpleFileStorage}; +use libdd_remote_config::{ + RemoteConfigCapabilities, RemoteConfigPath, RemoteConfigProduct, Target, +}; +use serde::{Deserialize, Serialize}; +use wasm_bindgen::prelude::*; + +#[wasm_bindgen(module = "/src/node-webcrypto.js")] +extern "C" { + #[wasm_bindgen(js_name = "ensureWebCrypto")] + fn ensure_web_crypto(); +} + +#[wasm_bindgen(start)] +fn init() { + console_error_panic_hook::set_once(); + ensure_web_crypto(); +} + +const APPLY_STATE_UNACKNOWLEDGED: u32 = 1; +const APPLY_STATE_ACKNOWLEDGED: u32 = 2; +const APPLY_STATE_ERROR: u32 = 3; + +type Fetcher = SingleChangesFetcher; + +/// A real `Error`, not a bare string: the JS side logs rejections with a logger that identifies a +/// cause by its `stack`, and the pure-JS fallback client rejects with `Error`s too. +fn to_js_err(err: impl std::fmt::Display) -> JsValue { + js_sys::Error::new(&err.to_string()).into() +} + +/// Deserializing capabilities one name at a time keeps an unrecognized one from discarding +/// the whole set. +fn parse_capability(name: &str) -> Option { + serde_json::from_value(serde_json::Value::String(name.to_string())).ok() +} + +/// Options accepted by [`RemoteConfigFetcher::new`]. These populate the `Client`/`ClientTracer` of +/// the remote config request. +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +struct FetcherOptions { + client_id: String, + runtime_id: String, + service: String, + env: String, + app_version: String, + /// Already-formatted `"key:value"` strings. + tags: Vec, + /// Already-formatted `"key:value"` strings. + process_tags: Vec, + language: String, + tracer_version: String, + /// Agent base URL, either `http(s)://host:port` or `unix:///path/to/socket`. libdatadog appends + /// the remote config path itself; the JS transport also accepts a Windows named pipe path. + url: String, + timeout_ms: u64, +} + +/// A single add/update/remove of one remote config file, as diffed against the previous poll. +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +struct ChangeRecord { + /// One of `"add"`, `"update"`, `"remove"`. + kind: &'static str, + /// Full unparsed remote config path, e.g. `datadog/2/APM_TRACING/config-id/name` or + /// `employee/APM_TRACING/config-id/name`. Pass this back to `setConfigState`. + path: String, + product: String, + config_id: String, + name: String, + version: f64, + /// The hash-verified file contents. Omitted for `"remove"`: the consumer already holds them from + /// the `"add"`/`"update"` that introduced the config. + #[serde(skip_serializing_if = "Option::is_none")] + contents: Option, +} + +fn to_record( + kind: &'static str, + file: &Arc>>, + contents: Option, +) -> ChangeRecord { + let path = file.path(); + ChangeRecord { + kind, + path: path.to_string(), + product: path.product.to_string(), + config_id: path.config_id.clone(), + name: path.name.clone(), + // Read after `contents`: both lock the same mutex, which is not reentrant. + version: file.version() as f64, + contents, + } +} + +fn to_contents(file: &Arc>>) -> Option { + // Lossy like `Buffer#toString('utf8')`: a config file that is not valid UTF-8 is not valid JSON + // either, so the consumer rejects it either way. + Some(String::from_utf8_lossy(file.contents().as_slice()).into_owned()) +} + +fn to_change_record(change: Change>>, Vec>) -> ChangeRecord { + match change { + Change::Add(file) => to_record("add", &file, to_contents(&file)), + Change::Update(file, _old_contents) => to_record("update", &file, to_contents(&file)), + Change::Remove(file) => to_record("remove", &file, None), + } +} + +/// Mutations recorded by the setters while a poll may be in flight, applied at the start of the next +/// one. `fetchChanges` holds the fetcher borrow across its whole round trip, so the setters must not +/// take it -- they would find it already borrowed and have nowhere to put the update. +#[derive(Default)] +struct PendingUpdates { + product_capabilities: Option<(Vec, Vec)>, + extra_services: Option>, + config_states: Vec<(RemoteConfigPath, ConfigApplyState)>, +} + +#[wasm_bindgen] +pub struct RemoteConfigFetcher { + fetcher: Rc>, + pending: Rc>, +} + +#[wasm_bindgen] +impl RemoteConfigFetcher { + #[wasm_bindgen(constructor)] + pub fn new(options: JsValue) -> Result { + let options: FetcherOptions = serde_wasm_bindgen::from_value(options).map_err(to_js_err)?; + + let url = libdd_common::parse_uri(&options.url).map_err(to_js_err)?; + + // Validate, otherwise libdatadog will panic here + if url.scheme().is_none() || url.authority().is_none() { + return Err(to_js_err(format!( + "Remote config agent URL needs both a scheme and a host: {}", + options.url + ))); + } + + let fetcher = SingleChangesFetcher::new( + SimpleFileStorage::default(), + Target::new( + options.service, + options.env, + options.app_version, + options.tags, + options.process_tags, + ), + options.runtime_id, + ConfigOptions { + invariants: ConfigInvariants { + language: options.language, + tracer_version: options.tracer_version, + endpoint: libdd_common::Endpoint { + url, + timeout_ms: options.timeout_ms, + ..Default::default() + }, + }, + // Products and capabilities are only known once the subsystems that own them have + // registered their handlers, which always happens before the first poll. + products: vec![], + capabilities: vec![], + }, + // Polling on a fixed interval is exactly the case a pooled connection hurts: the agent's + // short idle keep-alive can close it between polls, turning reuse into intermittent + // failures. + WasmCapabilities::new_without_connection_pooling(), + ) + .with_client_id(options.client_id); + + Ok(RemoteConfigFetcher { + fetcher: Rc::new(RefCell::new(fetcher)), + pending: Rc::new(RefCell::new(PendingUpdates::default())), + }) + } + + /// Polls the agent once and resolves with the changes (add/update/remove) relative to the + /// previous successful poll. An empty array means nothing changed. + /// + /// Holding the borrow across the await is deliberate: on wasm there is one thread, and the + /// borrow is what serializes polls. + #[allow(clippy::await_holding_refcell_ref)] + #[wasm_bindgen(js_name = "fetchChanges")] + pub async fn fetch_changes(&self) -> Result { + let cell = self.fetcher.clone(); + let pending = self.pending.clone(); + + // The scheduler above this only arms the next poll once the previous settled, so an + // overlapping call is a guard, not a path. + let mut fetcher = cell + .try_borrow_mut() + .map_err(|_| to_js_err("A remote config poll is already in flight"))?; + + let updates = std::mem::take(&mut *pending.borrow_mut()); + if let Some((products, capabilities)) = updates.product_capabilities { + fetcher.set_product_capabilities(products, capabilities); + } + if let Some(services) = updates.extra_services { + fetcher.set_extra_services(services); + } + for (path, state) in updates.config_states { + fetcher.fetcher.set_config_state(&path, state); + } + + let changes = fetcher + .fetch_changes::>() + .await + .map_err(to_js_err)?; + + let records: Vec = changes.into_iter().map(to_change_record).collect(); + + serde_wasm_bindgen::to_value(&records).map_err(to_js_err) + } + + /// Reports the apply outcome of a previously received change, identified by the `path` handed + /// back by `fetchChanges`. `applyState` is one of `APPLY_STATE_*` constants. + #[wasm_bindgen(js_name = "setConfigState")] + pub fn set_config_state( + &self, + path: String, + apply_state: u32, + apply_error: Option, + ) -> Result<(), JsValue> { + let state = match apply_state { + APPLY_STATE_UNACKNOWLEDGED => ConfigApplyState::Unacknowledged, + APPLY_STATE_ACKNOWLEDGED => ConfigApplyState::Acknowledged, + APPLY_STATE_ERROR => ConfigApplyState::Error(apply_error.unwrap_or_default()), + other => return Err(to_js_err(format!("Unknown apply state {other}"))), + }; + let path = RemoteConfigPath::try_parse(&path).map_err(to_js_err)?; + + self.pending + .borrow_mut() + .config_states + .push((path.into(), state)); + + Ok(()) + } + + /// Replaces the set of extra services reported to the agent. + #[wasm_bindgen(js_name = "setExtraServices")] + pub fn set_extra_services(&self, services: Vec) { + self.pending.borrow_mut().extra_services = Some(services); + } + + /// Replaces the set of subscribed products and capabilities. + /// + /// Names this build does not know are skipped and returned, so that a tracer whose own list has + /// moved ahead of libdatadog's keeps working with the names that do resolve. Reporting them is + /// left to the caller, which owns the logger. + #[wasm_bindgen(js_name = "setProductCapabilities")] + pub fn set_product_capabilities( + &self, + products: Vec, + capabilities: Vec, + ) -> Vec { + let mut unknown = vec![]; + + let products = products + .into_iter() + .filter_map(|name| match RemoteConfigProduct::from_str(&name) { + Ok(product) => Some(product), + Err(_) => { + unknown.push(name); + None + } + }) + .collect(); + + let capabilities = capabilities + .into_iter() + .filter_map(|name| match parse_capability(&name) { + Some(capability) => Some(capability), + None => { + unknown.push(name); + None + } + }) + .collect(); + + self.pending.borrow_mut().product_capabilities = Some((products, capabilities)); + + unknown + } +} + +/// Installs the host's async-context hook, so the HTTP request this module issues is not +/// re-instrumented by the tracer's own http plugin. +#[wasm_bindgen(js_name = "setStorage")] +pub fn set_storage(new_storage: &JsValue) { + libdatadog_nodejs_capabilities::http::set_storage(new_storage); +} diff --git a/crates/remote_config/src/node-webcrypto.js b/crates/remote_config/src/node-webcrypto.js new file mode 100644 index 0000000..7f71246 --- /dev/null +++ b/crates/remote_config/src/node-webcrypto.js @@ -0,0 +1,21 @@ +'use strict' + +/* eslint-disable n/no-unsupported-features/node-builtins -- + * Installing `globalThis.crypto` is the entire point of this file, and `crypto.webcrypto` is only + * reached on the versions that lack the global. The rule flags both as newer than the declared + * `>=18` range, which is exactly the gap being bridged. + */ + +// Node exposes the WebCrypto global inside a module only from v20; on v18 `globalThis.crypto` is +// undefined there (it is present under `node -e`, which makes this easy to miss). libdatadog +// generates the fetcher's default client id with `Uuid::new_v4()`, whose wasm shim reads +// `globalThis.crypto` and has no Node fallback, so on v18 constructing a fetcher panicked and +// trapped the whole module. +// +// Install the standard global from Node's own implementation when it is missing -- the same object +// Node itself exposes one major later. An existing one is never overwritten. +module.exports.ensureWebCrypto = function ensureWebCrypto () { + if (globalThis.crypto === undefined) { + globalThis.crypto = require('node:crypto').webcrypto + } +} diff --git a/package.json b/package.json index d956cc2..d816f46 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "build-debug": "mkdir -p target && yarn -s cargo-build > ./target/out.ndjson && yarn -s copy-artifacts", "build-release": "mkdir -p target && yarn -s cargo-build-release > ./target/out.ndjson && yarn -s copy-artifacts", "build-all": "mkdir -p target && yarn -s cargo-build -- --workspace > ./target/out.ndjson && yarn -s copy-artifacts && yarn -s build-wasm", - "build-wasm": "yarn -s install-wasm-pack && node scripts/build-wasm.js library_config && node scripts/build-wasm.js datadog-js-zstd && node scripts/build-wasm.js pipeline", + "build-wasm": "yarn -s install-wasm-pack && node scripts/build-wasm.js library_config && node scripts/build-wasm.js datadog-js-zstd && node scripts/build-wasm.js pipeline && node scripts/build-wasm.js remote_config", "cargo-build-release": "yarn -s cargo-build -- --release", "cargo-build": "cargo build --message-format=json-render-diagnostics", "copy-artifacts": "node ./scripts/copy-artifacts", diff --git a/test/http_transport.js b/test/http_transport.js index 5a97a58..29b7d38 100644 --- a/test/http_transport.js +++ b/test/http_transport.js @@ -56,7 +56,7 @@ describe('http_transport response header observer', () => { ) // head occupies [0, head.length); body is empty (offset 0, length 0). // Empty socketPath -> TCP transport. - return transport.httpRequest('127.0.0.1', port, false, '', 0, head.length, 0, 0, fakeWasmMemory(head)) + return transport.httpRequest('127.0.0.1', port, false, '', true, 0, head.length, 0, 0, fakeWasmMemory(head)) } it('invokes the observer with the raw response headers', async () => { @@ -166,7 +166,7 @@ describe('http_transport IPv6 host', () => { 'utf8', ) // Bracketed IPv6 host, exactly as libdatadog passes it from the agent URI. - const [status] = await transport.httpRequest('[::1]', port, false, '', 0, head.length, 0, 0, fakeWasmMemory(head)) + const [status] = await transport.httpRequest('[::1]', port, false, '', true, 0, head.length, 0, 0, fakeWasmMemory(head)) assert.strictEqual(status, 200) }) }) @@ -235,13 +235,75 @@ describe('http_transport unix socket', { skip: process.platform === 'win32' }, ( ) // host/port empty/0; socketPath drives the connection. const [status, , body] = await transport.httpRequest( - '', 0, false, socketPath, 0, head.length, 0, 0, fakeWasmMemory(head), + '', 0, false, socketPath, true, 0, head.length, 0, 0, fakeWasmMemory(head), ) assert.strictEqual(status, 200) assert.strictEqual(Buffer.from(body).toString('utf8'), RESPONSE_BODY) }) }) +describe('http_transport connection pooling', () => { + let server + let port + let sockets + let previousAgent + + before(async () => { + // Pin the agent instead of relying on `http.globalAgent`: its keep-alive default only arrived + // in Node 19, and even where it is on, reuse is an optimization Node does not guarantee. With + // an explicit keep-alive agent capped at one socket, "pooled" is deterministic on every + // supported version, and `agent: false` still bypasses it entirely. + previousAgent = http.globalAgent + http.globalAgent = new http.Agent({ keepAlive: true, maxSockets: 1 }) + + sockets = new Set() + server = http.createServer((req, res) => { + sockets.add(req.socket) + req.on('data', () => {}) + req.on('end', () => res.end(RESPONSE_BODY)) + }) + server.keepAliveTimeout = 60_000 + await new Promise(resolve => server.listen(0, '127.0.0.1', resolve)) + port = server.address().port + }) + + after(async () => { + http.globalAgent.destroy() + http.globalAgent = previousAgent + await new Promise(resolve => server.close(resolve)) + }) + + // No `Connection: close`, so the connection is reusable and pooling is observable. + function keepAliveHead () { + return Buffer.from( + `POST /v0.4/traces HTTP/1.1\r\nHost: 127.0.0.1:${port}\r\nContent-Length: 0\r\n\r\n`, + 'utf8', + ) + } + + async function poll (connectionPooling) { + sockets.clear() + for (let i = 0; i < 3; i++) { + const head = keepAliveHead() + const [status] = await transport.httpRequest( + '127.0.0.1', port, false, '', connectionPooling, 0, head.length, 0, 0, fakeWasmMemory(head), + ) + assert.strictEqual(status, 200) + } + return sockets.size + } + + it('reuses one connection when pooling is on', async () => { + assert.strictEqual(await poll(true), 1) + }) + + it('opens a fresh connection per request when pooling is off', async () => { + // What a caller polling on a fixed interval asks for: the agent's short idle keep-alive can + // close a pooled connection between polls, which turns reuse into intermittent failures. + assert.strictEqual(await poll(false), 3) + }) +}) + // Entity-header injection: container-id / entity-id / external-env detection // (Node reads /proc + env; libdatadog's own detection is inert on wasm) and the // rewrite of the Rust-rendered request head that carries them. @@ -397,7 +459,7 @@ describe('http_transport entity headers', () => { view.set(body, head.length) const [status] = await transport.httpRequest( - '127.0.0.1', port, false, '', 0, head.length, head.length, body.length, { buffer: mem }, + '127.0.0.1', port, false, '', true, 0, head.length, head.length, body.length, { buffer: mem }, ) assert.strictEqual(status, 200) assert.strictEqual(received['datadog-meta-lang'], 'nodejs') diff --git a/test/pipeline.js b/test/pipeline.js index 59511fe..bfd30a5 100644 --- a/test/pipeline.js +++ b/test/pipeline.js @@ -1134,6 +1134,10 @@ describe('pipeline', { skip }, () => { }) it('returns collapsed span count when stats cardinality overflows', async () => { + // The resource field has its own cardinality limit (1024) and collapses to a placeholder long + // before the whole-key limit (~7000) is reached, so varying it no longer overflows the key at all. + // `service` has no per-field limit, so distinct services still overflow the whole key -- which is + // what `collapsedSpans` counts. const http = require('node:http') const seen = [] const server = http.createServer((req, res) => { @@ -1155,8 +1159,8 @@ describe('pipeline', { skip }, () => { for (let i = 0; i < 15_000; i++) { const span = ns.createSpan() span.name = 'stats-span' - span.service = 'stats-svc' - span.resource = `/stats/${i}` + span.service = `stats-svc-${i}` + span.resource = '/stats' span.type = 'web' span.setTag('span.kind', 'server') span.duration = 5_000_000n diff --git a/test/remote-config.js b/test/remote-config.js new file mode 100644 index 0000000..b048563 --- /dev/null +++ b/test/remote-config.js @@ -0,0 +1,266 @@ +'use strict' + +const assert = require('node:assert') +const { createHash } = require('node:crypto') +const { execFileSync } = require('node:child_process') +const { createServer } = require('node:http') +const { test } = require('node:test') + +const libdatadog = require('..') +const { RemoteConfigFetcher } = libdatadog.load('remote_config') +assert(RemoteConfigFetcher !== undefined) + +const APPLY_STATE_ACKNOWLEDGED = 2 +const APPLY_STATE_ERROR = 3 + +const CONFIG_PATH = 'datadog/2/ASM_FEATURES/asm-features-1/config' + +/** + * Builds a `/v0.7/config` response body: a base64 encoded TUF-like `targets` document plus the + * base64 encoded files themselves, which is what the agent sends. + */ +function agentResponse (configs, targetsVersion) { + const targets = {} + const targetFiles = [] + + for (const { path, file, version } of configs) { + const raw = Buffer.from(JSON.stringify(file), 'utf8') + targets[path] = { + custom: { v: version }, + hashes: { sha256: createHash('sha256').update(raw).digest('hex') }, + length: raw.length, + } + targetFiles.push({ path, raw: raw.toString('base64') }) + } + + return JSON.stringify({ + client_configs: configs.map(({ path }) => path), + targets: Buffer.from(JSON.stringify({ + signatures: [], + signed: { + _type: 'targets', + custom: { agent_refresh_interval: 5, opaque_backend_state: `backend-state-${targetsVersion}` }, + expires: '2100-01-01T00:00:00.000000000Z', + spec_version: '1.0.0', + targets, + version: targetsVersion, + }, + }), 'utf8').toString('base64'), + target_files: targetFiles, + }) +} + +async function withAgent (run) { + const requests = [] + const responses = [] + + const server = createServer((req, res) => { + const chunks = [] + req + .on('data', chunk => chunks.push(chunk)) + .on('end', () => { + requests.push(JSON.parse(Buffer.concat(chunks).toString('utf8'))) + res.writeHead(200, { 'content-type': 'application/json' }) + res.end(responses.shift() ?? '{}') + }) + }) + + await new Promise(resolve => server.listen(0, '127.0.0.1', resolve)) + + const fetcher = new RemoteConfigFetcher({ + clientId: 'client-id-1', + runtimeId: 'runtime-id-1', + service: 'my_svc', + env: 'my_env', + appVersion: '1.0.0', + tags: ['runtime-id:runtime-id-1'], + processTags: ['entrypoint.type:script'], + language: 'nodejs', + tracerVersion: '1.2.3', + url: `http://127.0.0.1:${server.address().port}`, + timeoutMs: 5000, + }) + + try { + await run({ fetcher, requests, responses }) + } finally { + await new Promise(resolve => server.close(resolve)) + } +} + +test('reports the client identity, products and capabilities', async () => { + await withAgent(async ({ fetcher, requests }) => { + fetcher.setProductCapabilities(['ASM_FEATURES', 'ASM_DD'], ['ASM_ACTIVATION', 'ASM_DD_RULES']) + fetcher.setExtraServices(['other_svc']) + + assert.deepStrictEqual(await fetcher.fetchChanges(), []) + + const { client } = requests[0] + + assert.strictEqual(client.id, 'client-id-1') + assert.strictEqual(client.is_tracer, true) + assert.deepStrictEqual(client.products, ['ASM_FEATURES', 'ASM_DD']) + // Bits 1 (ASM_ACTIVATION) and 3 (ASM_DD_RULES) of a big-endian octet string. + assert.deepStrictEqual(client.capabilities, [0b1010]) + assert.strictEqual(client.client_tracer.language, 'nodejs') + assert.strictEqual(client.client_tracer.service, 'my_svc') + assert.deepStrictEqual(client.client_tracer.extra_services, ['other_svc']) + assert.deepStrictEqual(client.client_tracer.process_tags, ['entrypoint.type:script']) + }) +}) + +test('diffs successive polls into add, update and remove changes', async () => { + await withAgent(async ({ fetcher, responses }) => { + fetcher.setProductCapabilities(['ASM_FEATURES'], []) + + responses.push(agentResponse([{ path: CONFIG_PATH, file: { asm: { enabled: true } }, version: 1 }], 1)) + + const added = await fetcher.fetchChanges() + assert.strictEqual(added.length, 1) + assert.strictEqual(added[0].kind, 'add') + assert.strictEqual(added[0].path, CONFIG_PATH) + assert.strictEqual(added[0].product, 'ASM_FEATURES') + assert.strictEqual(added[0].configId, 'asm-features-1') + assert.strictEqual(added[0].name, 'config') + assert.strictEqual(added[0].version, 1) + assert.deepStrictEqual(JSON.parse(added[0].contents), { asm: { enabled: true } }) + + // An unchanged config is not reported again. + responses.push(agentResponse([{ path: CONFIG_PATH, file: { asm: { enabled: true } }, version: 1 }], 2)) + assert.deepStrictEqual(await fetcher.fetchChanges(), []) + + responses.push(agentResponse([{ path: CONFIG_PATH, file: { asm: { enabled: false } }, version: 2 }], 3)) + + const updated = await fetcher.fetchChanges() + assert.strictEqual(updated.length, 1) + assert.strictEqual(updated[0].kind, 'update') + assert.strictEqual(updated[0].version, 2) + assert.deepStrictEqual(JSON.parse(updated[0].contents), { asm: { enabled: false } }) + + responses.push(agentResponse([], 4)) + + const removed = await fetcher.fetchChanges() + assert.strictEqual(removed.length, 1) + assert.strictEqual(removed[0].kind, 'remove') + assert.strictEqual(removed[0].path, CONFIG_PATH) + assert.strictEqual(removed[0].contents, undefined) + }) +}) + +test('sends the apply state set for a config on the next poll', async () => { + await withAgent(async ({ fetcher, requests, responses }) => { + fetcher.setProductCapabilities(['ASM_FEATURES'], []) + + responses.push(agentResponse([{ path: CONFIG_PATH, file: { asm: { enabled: true } }, version: 1 }], 1)) + await fetcher.fetchChanges() + + fetcher.setConfigState(CONFIG_PATH, APPLY_STATE_ERROR, 'Error: could not apply') + + responses.push(agentResponse([{ path: CONFIG_PATH, file: { asm: { enabled: true } }, version: 1 }], 2)) + await fetcher.fetchChanges() + + assert.deepStrictEqual(requests[1].client.state.config_states, [{ + id: 'asm-features-1', + version: 1, + product: 'ASM_FEATURES', + apply_state: APPLY_STATE_ERROR, + apply_error: 'Error: could not apply', + }]) + assert.deepStrictEqual(requests[1].cached_target_files, [{ + path: CONFIG_PATH, + length: 24, + hashes: [{ + algorithm: 'sha256', + hash: createHash('sha256').update(JSON.stringify({ asm: { enabled: true } })).digest('hex'), + }], + }]) + + fetcher.setConfigState(CONFIG_PATH, APPLY_STATE_ACKNOWLEDGED, '') + + responses.push(agentResponse([{ path: CONFIG_PATH, file: { asm: { enabled: true } }, version: 1 }], 3)) + await fetcher.fetchChanges() + + assert.strictEqual(requests[2].client.state.config_states[0].apply_state, APPLY_STATE_ACKNOWLEDGED) + assert.strictEqual(requests[2].client.state.config_states[0].apply_error, '') + }) +}) + +test('skips unknown products and capabilities, and rejects bad apply states', async () => { + await withAgent(async ({ fetcher }) => { + // Names this build does not know are skipped and returned, so that a tracer whose own lists + // have moved ahead of libdatadog's keeps working with the names that do resolve. + assert.deepStrictEqual( + fetcher.setProductCapabilities(['ASM_FEATURES', 'NOT_A_PRODUCT'], ['ASM_ACTIVATION', 'NOT_A_CAPABILITY']), + ['NOT_A_PRODUCT', 'NOT_A_CAPABILITY'], + ) + + assert.throws(() => fetcher.setConfigState(CONFIG_PATH, 42, ''), { message: /Unknown apply state 42/ }) + assert.throws(() => fetcher.setConfigState('nonsense', APPLY_STATE_ACKNOWLEDGED, '')) + }) +}) + +test('constructs on a runtime without a WebCrypto global', () => { + // libdatadog generates the default client id with a uuid whose wasm shim reads + // `globalThis.crypto` and has no Node fallback. Node only exposes that global inside a module + // from v20, so without the shim in `src/node_webcrypto.js` every constructor panics and traps the + // module -- which is how it presented on Node 18, as total failure followed by a hang. + // + // A child process, because the shim runs once when the module loads: the global has to be absent + // before that, which is exactly the Node 18 condition. + const script = ` + delete globalThis.crypto + if (typeof globalThis.crypto !== 'undefined') throw new Error('could not hide the global') + const { RemoteConfigFetcher } = require(${JSON.stringify(require.resolve('..'))}).load('remote_config') + new RemoteConfigFetcher({ + clientId: 'client-id-1', runtimeId: 'runtime-id-1', service: 'my_svc', env: 'my_env', + appVersion: '1.0.0', tags: [], processTags: [], language: 'nodejs', tracerVersion: '1.2.3', + url: 'http://127.0.0.1:8126', timeoutMs: 1000, + }) + process.stdout.write('constructed') + ` + + const out = execFileSync(process.execPath, ['-e', script], { encoding: 'utf8' }) + + assert.strictEqual(out, 'constructed') +}) + +test('rejects an agent url without a scheme and host', () => { + // libdatadog appends the remote config path to this URI and unwraps the result, so a scheme + // without an authority would panic -- and abort the process, since release builds do not unwind. + // `agent-host:8126` is the reachable shape: JavaScript's `new URL` accepts it too. + assert.throws( + () => new RemoteConfigFetcher({ + clientId: 'client-id-1', + runtimeId: 'runtime-id-1', + service: 'my_svc', + env: 'my_env', + appVersion: '1.0.0', + tags: [], + processTags: [], + language: 'nodejs', + tracerVersion: '1.2.3', + url: 'agent-host:8126', + timeoutMs: 1000, + }), + { message: /needs both a scheme and a host/ }, + ) +}) + +test('rejects a failed poll', async () => { + // Only the URL parsing is exercised here: no socket is listening, so the poll fails. + const fetcher = new RemoteConfigFetcher({ + clientId: 'client-id-1', + runtimeId: 'runtime-id-1', + service: 'my_svc', + env: 'my_env', + appVersion: '1.0.0', + tags: [], + processTags: [], + language: 'nodejs', + tracerVersion: '1.2.3', + url: 'unix:///tmp/definitely-not-a-datadog-apm-socket', + timeoutMs: 1000, + }) + + await assert.rejects(fetcher.fetchChanges()) +})