From 919fcacf2ad98152ddff4ae8fe181760a08bc5d5 Mon Sep 17 00:00:00 2001 From: Caleb Schoepp Date: Fri, 22 Mar 2024 12:22:48 -0600 Subject: [PATCH 01/13] feat(wasi-otel): A WASI OTel host component Signed-off-by: Caleb Schoepp fix: update opentelemetry version Signed-off-by: Andrew Steurer <94206073+asteurer@users.noreply.github.com> Fix out of date Cargo.lock from bad rebase Signed-off-by: Caleb Schoepp feat(factor-otel): adding metrics Signed-off-by: Andrew Steurer <94206073+asteurer@users.noreply.github.com> feat(factor-otel): refactoring otel conversions Signed-off-by: Andrew Steurer <94206073+asteurer@users.noreply.github.com> fix(telemetry): update BatchLogProcessor to be async Signed-off-by: Andrew Steurer <94206073+asteurer@users.noreply.github.com> feat(factor-otel): refactoring WIT and updating conversions Signed-off-by: Andrew Steurer <94206073+asteurer@users.noreply.github.com> fix(factor-otel): updating WIT Signed-off-by: Andrew Steurer <94206073+asteurer@users.noreply.github.com> feat(factor-otel): updating WIT and conversions Signed-off-by: Andrew Steurer <94206073+asteurer@users.noreply.github.com> feat(factor-otel): small refactors Signed-off-by: Andrew Steurer <94206073+asteurer@users.noreply.github.com> fix(factor-otel): rebasing wasi-otel branch on main Signed-off-by: Andrew Steurer <94206073+asteurer@users.noreply.github.com> --- Cargo.lock | 3197 ++++++++++------- Cargo.toml | 6 + crates/factor-key-value/Cargo.toml | 1 + crates/factor-key-value/src/host.rs | 24 +- crates/factor-key-value/src/lib.rs | 8 +- crates/factor-llm/Cargo.toml | 1 + crates/factor-llm/src/host.rs | 4 + crates/factor-llm/src/lib.rs | 6 +- crates/factor-otel/Cargo.toml | 25 + crates/factor-otel/src/host.rs | 87 + crates/factor-otel/src/lib.rs | 213 ++ crates/factor-outbound-http/Cargo.toml | 1 + crates/factor-outbound-http/src/lib.rs | 5 + crates/factor-outbound-http/src/spin.rs | 2 + crates/factor-outbound-mqtt/Cargo.toml | 1 + crates/factor-outbound-mqtt/src/host.rs | 13 +- crates/factor-outbound-mqtt/src/lib.rs | 4 + crates/factor-outbound-mysql/Cargo.toml | 1 + crates/factor-outbound-mysql/src/host.rs | 3 + crates/factor-outbound-mysql/src/lib.rs | 5 + crates/factor-outbound-pg/Cargo.toml | 1 + crates/factor-outbound-pg/src/host.rs | 4 + crates/factor-outbound-pg/src/lib.rs | 6 + crates/factor-outbound-redis/Cargo.toml | 1 + crates/factor-outbound-redis/src/host.rs | 23 +- crates/factor-outbound-redis/src/lib.rs | 4 + crates/factor-sqlite/Cargo.toml | 1 + crates/factor-sqlite/src/host.rs | 6 + crates/factor-sqlite/src/lib.rs | 5 +- crates/factor-variables/Cargo.toml | 1 + crates/factor-variables/src/host.rs | 1 + crates/factor-variables/src/lib.rs | 6 +- crates/runtime-config/Cargo.toml | 1 + crates/runtime-config/src/lib.rs | 7 + crates/runtime-factors/Cargo.toml | 1 + crates/runtime-factors/src/lib.rs | 3 + crates/telemetry/Cargo.toml | 6 +- crates/telemetry/src/env.rs | 18 +- crates/telemetry/src/lib.rs | 12 +- crates/telemetry/src/logs.rs | 5 +- crates/telemetry/src/metrics.rs | 5 +- crates/telemetry/src/traces.rs | 7 +- crates/trigger-http/Cargo.toml | 1 + crates/trigger-http/src/wasi.rs | 1 + crates/world/Cargo.toml | 3 + crates/world/src/conversions.rs | 492 +++ tests/integration.rs | 437 ++- tests/test-components/components/Cargo.lock | 865 +++-- .../components/otel-smoke-test/Cargo.toml | 12 + .../components/otel-smoke-test/src/lib.rs | 22 + .../components/wasi-otel-tracing/Cargo.toml | 16 + .../components/wasi-otel-tracing/src/lib.rs | 130 + tests/testcases/otel-smoke-test/spin.toml | 13 +- tests/testcases/wasi-otel-tracing/spin.toml | 19 + wit/deps/otel/metrics.wit | 264 ++ wit/deps/otel/tracing.wit | 122 + wit/deps/otel/types.wit | 48 + wit/deps/otel/world.wit | 7 + wit/world.wit | 1 + 59 files changed, 4509 insertions(+), 1675 deletions(-) create mode 100644 crates/factor-otel/Cargo.toml create mode 100644 crates/factor-otel/src/host.rs create mode 100644 crates/factor-otel/src/lib.rs create mode 100644 tests/test-components/components/otel-smoke-test/Cargo.toml create mode 100644 tests/test-components/components/otel-smoke-test/src/lib.rs create mode 100644 tests/test-components/components/wasi-otel-tracing/Cargo.toml create mode 100644 tests/test-components/components/wasi-otel-tracing/src/lib.rs create mode 100644 tests/testcases/wasi-otel-tracing/spin.toml create mode 100644 wit/deps/otel/metrics.wit create mode 100644 wit/deps/otel/tracing.wit create mode 100644 wit/deps/otel/types.wit create mode 100644 wit/deps/otel/world.wit diff --git a/Cargo.lock b/Cargo.lock index a3172f282b..b5af3917d7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,27 +4,18 @@ version = 4 [[package]] name = "addr2line" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" -dependencies = [ - "gimli 0.31.1", -] - -[[package]] -name = "addr2line" -version = "0.25.0" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9acbfca36652500c911ddb767ed433e3ed99b032b5d935be73c6923662db1d43" +checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" dependencies = [ - "gimli 0.32.0", + "gimli", ] [[package]] name = "adler2" -version = "2.0.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "adler32" @@ -49,37 +40,39 @@ version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" dependencies = [ - "getrandom 0.2.15", + "getrandom 0.2.16", "once_cell", "version_check", ] [[package]] name = "ahash" -version = "0.8.11" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" dependencies = [ "cfg-if", + "getrandom 0.3.4", "once_cell", + "serde", "version_check", "zerocopy", ] [[package]] name = "aho-corasick" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" dependencies = [ "memchr", ] [[package]] name = "allocator-api2" -version = "0.2.20" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45862d1c77f2228b9e10bc609d5bc203d86ebc9b87ad8d5d5167a6c9abf739d9" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "ambient-authority" @@ -87,12 +80,6 @@ version = "0.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e9d4ee0d472d1cd2e28c97dfa124b3d8d992e10eb0a035f33f5d12e3a177ba3b" -[[package]] -name = "android-tzdata" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" - [[package]] name = "android_system_properties" version = "0.1.5" @@ -104,9 +91,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.18" +version = "0.6.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" +checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" dependencies = [ "anstyle", "anstyle-parse", @@ -119,43 +106,44 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.10" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" +checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" [[package]] name = "anstyle-parse" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.2" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" +checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] name = "anstyle-wincon" -version = "3.0.6" +version = "3.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" +checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a" dependencies = [ "anstyle", - "windows-sys 0.59.0", + "once_cell_polyfill", + "windows-sys 0.60.2", ] [[package]] name = "anyhow" -version = "1.0.93" +version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" dependencies = [ "backtrace", ] @@ -168,9 +156,9 @@ checksum = "d301b3b94cb4b2f23d7917810addbbaff90738e0ca2be692bd027e70d7e0330c" [[package]] name = "arbitrary" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" +checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1" dependencies = [ "derive_arbitrary", ] @@ -199,7 +187,7 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532" dependencies = [ - "event-listener 5.3.1", + "event-listener 5.4.1", "event-listener-strategy", "futures-core", "pin-project-lite", @@ -218,9 +206,9 @@ dependencies = [ [[package]] name = "async-channel" -version = "2.3.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a" +checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2" dependencies = [ "concurrent-queue", "event-listener-strategy", @@ -230,67 +218,82 @@ dependencies = [ [[package]] name = "async-compression" -version = "0.4.17" +version = "0.4.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cb8f1d480b0ea3783ab015936d2a55c87e219676f0c0b7dec61494043f21857" +checksum = "5a89bce6054c720275ac2432fbba080a66a2106a44a1b804553930ca6909f4e0" dependencies = [ - "flate2", + "compression-codecs", + "compression-core", "futures-core", - "memchr", "pin-project-lite", "tokio", ] [[package]] name = "async-executor" -version = "1.13.1" +version = "1.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30ca9a001c1e8ba5149f91a74362376cc6bc5b919d92d988668657bd570bdcec" +checksum = "497c00e0fd83a72a79a39fcbd8e3e2f055d6f6c7e025f3b3d91f4f8e76527fb8" dependencies = [ "async-task", "concurrent-queue", - "fastrand 2.2.0", - "futures-lite 2.5.0", + "fastrand 2.3.0", + "futures-lite 2.6.1", + "pin-project-lite", "slab", ] [[package]] name = "async-fs" -version = "2.1.2" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebcd09b382f40fcd159c2d695175b2ae620ffa5f3bd6f664131efff4e8b9e04a" +checksum = "8034a681df4aed8b8edbd7fbe472401ecf009251c8b40556b304567052e294c5" dependencies = [ "async-lock", "blocking", - "futures-lite 2.5.0", + "futures-lite 2.6.1", ] [[package]] -name = "async-io" -version = "2.4.0" +name = "async-global-executor" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a2b323ccce0a1d90b449fd71f2a06ca7faa7c54c2751f06c9bd851fc061059" +checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c" dependencies = [ + "async-channel 2.5.0", + "async-executor", + "async-io", "async-lock", + "blocking", + "futures-lite 2.6.1", + "once_cell", +] + +[[package]] +name = "async-io" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "456b8a8feb6f42d237746d4b3e9a178494627745c3c56c6ea55d92ba50d026fc" +dependencies = [ + "autocfg", "cfg-if", "concurrent-queue", "futures-io", - "futures-lite 2.5.0", + "futures-lite 2.6.1", "parking", "polling", - "rustix 0.38.40", + "rustix 1.1.2", "slab", - "tracing", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "async-lock" -version = "3.4.0" +version = "3.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" +checksum = "5fd03604047cee9b6ce9de9f70c6cd540a0520c813cbd49bae61f33ab80ed1dc" dependencies = [ - "event-listener 5.3.1", + "event-listener 5.4.1", "event-listener-strategy", "pin-project-lite", ] @@ -312,21 +315,20 @@ dependencies = [ [[package]] name = "async-process" -version = "2.3.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63255f1dc2381611000436537bbedfe83183faa303a5a0edaf191edef06526bb" +checksum = "fc50921ec0055cdd8a16de48773bfeec5c972598674347252c0399676be7da75" dependencies = [ - "async-channel 2.3.1", + "async-channel 2.5.0", "async-io", "async-lock", "async-signal", "async-task", "blocking", "cfg-if", - "event-listener 5.3.1", - "futures-lite 2.5.0", - "rustix 0.38.40", - "tracing", + "event-listener 5.4.1", + "futures-lite 2.6.1", + "rustix 1.1.2", ] [[package]] @@ -342,9 +344,9 @@ dependencies = [ [[package]] name = "async-signal" -version = "0.2.10" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "637e00349800c0bdf8bfc21ebbc0b6524abea702b0da4168ac00d070d0c0b9f3" +checksum = "43c070bbf59cd3570b6b2dd54cd772527c7c3620fce8be898406dd3ed6adc64c" dependencies = [ "async-io", "async-lock", @@ -352,10 +354,37 @@ dependencies = [ "cfg-if", "futures-core", "futures-io", - "rustix 0.38.40", + "rustix 1.1.2", "signal-hook-registry", "slab", - "windows-sys 0.59.0", + "windows-sys 0.61.2", +] + +[[package]] +name = "async-std" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c8e079a4ab67ae52b7403632e4618815d6db36d2a010cfe41b02c1b1578f93b" +dependencies = [ + "async-channel 1.9.0", + "async-global-executor", + "async-io", + "async-lock", + "async-process", + "crossbeam-utils", + "futures-channel", + "futures-core", + "futures-io", + "futures-lite 2.6.1", + "gloo-timers", + "kv-log-macro", + "log", + "memchr", + "once_cell", + "pin-project-lite", + "pin-utils", + "slab", + "wasm-bindgen-futures", ] [[package]] @@ -388,9 +417,9 @@ checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" [[package]] name = "async-trait" -version = "0.1.83" +version = "0.1.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", @@ -434,15 +463,15 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "aws-config" -version = "1.5.10" +version = "1.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b49afaa341e8dd8577e1a2200468f98956d6eda50bcf4a53246cc00174ba924" +checksum = "1856b1b48b65f71a4dd940b1c0931f9a7b646d4a924b9828ffefc1454714668a" dependencies = [ "aws-credential-types", "aws-runtime", @@ -457,9 +486,9 @@ dependencies = [ "aws-smithy-types", "aws-types", "bytes", - "fastrand 2.2.0", + "fastrand 2.3.0", "hex", - "http 0.2.12", + "http 1.3.1", "ring", "time", "tokio", @@ -470,9 +499,9 @@ dependencies = [ [[package]] name = "aws-credential-types" -version = "1.2.1" +version = "1.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60e8f6b615cb5fc60a98132268508ad104310f0cfb25a1c22eee76efdf9154da" +checksum = "faf26925f4a5b59eb76722b63c2892b1d70d06fa053c72e4a100ec308c1d47bc" dependencies = [ "aws-smithy-async", "aws-smithy-runtime-api", @@ -482,9 +511,9 @@ dependencies = [ [[package]] name = "aws-runtime" -version = "1.4.3" +version = "1.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a10d5c055aa540164d9561a0e2e74ad30f0dcf7393c3a92f6733ddf9c5762468" +checksum = "9f2402da1a5e16868ba98725e5d73f26b8116eaa892e56f2cd0bf5eec7985f70" dependencies = [ "aws-credential-types", "aws-sigv4", @@ -495,10 +524,9 @@ dependencies = [ "aws-smithy-types", "aws-types", "bytes", - "fastrand 2.2.0", + "fastrand 2.3.0", "http 0.2.12", "http-body 0.4.6", - "once_cell", "percent-encoding", "pin-project-lite", "tracing", @@ -507,9 +535,9 @@ dependencies = [ [[package]] name = "aws-sdk-dynamodb" -version = "1.53.0" +version = "1.97.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6355a9536b92daf4c4b7d4d4f60dd08ea780259ed80bac0312f2e1df4398176" +checksum = "6034694d9f6b47ead8af47a1b79a85e185751d1171e9b983c4b3328bbff480c6" dependencies = [ "aws-credential-types", "aws-runtime", @@ -521,18 +549,17 @@ dependencies = [ "aws-smithy-types", "aws-types", "bytes", - "fastrand 2.2.0", + "fastrand 2.3.0", "http 0.2.12", - "once_cell", "regex-lite", "tracing", ] [[package]] name = "aws-sdk-sso" -version = "1.49.0" +version = "1.88.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09677244a9da92172c8dc60109b4a9658597d4d298b188dd0018b6a66b410ca4" +checksum = "d05b276777560aa9a196dbba2e3aada4d8006d3d7eeb3ba7fe0c317227d933c4" dependencies = [ "aws-credential-types", "aws-runtime", @@ -544,17 +571,17 @@ dependencies = [ "aws-smithy-types", "aws-types", "bytes", + "fastrand 2.3.0", "http 0.2.12", - "once_cell", "regex-lite", "tracing", ] [[package]] name = "aws-sdk-ssooidc" -version = "1.50.0" +version = "1.90.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81fea2f3a8bb3bd10932ae7ad59cc59f65f270fc9183a7e91f501dc5efbef7ee" +checksum = "f9be14d6d9cd761fac3fd234a0f47f7ed6c0df62d83c0eeb7012750e4732879b" dependencies = [ "aws-credential-types", "aws-runtime", @@ -566,17 +593,17 @@ dependencies = [ "aws-smithy-types", "aws-types", "bytes", + "fastrand 2.3.0", "http 0.2.12", - "once_cell", "regex-lite", "tracing", ] [[package]] name = "aws-sdk-sts" -version = "1.49.0" +version = "1.90.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53dcf5e7d9bd1517b8b998e170e650047cea8a2b85fe1835abe3210713e541b7" +checksum = "98a862d704c817d865c8740b62d8bbeb5adcb30965e93b471df8a5bcefa20a80" dependencies = [ "aws-credential-types", "aws-runtime", @@ -589,17 +616,17 @@ dependencies = [ "aws-smithy-types", "aws-smithy-xml", "aws-types", + "fastrand 2.3.0", "http 0.2.12", - "once_cell", "regex-lite", "tracing", ] [[package]] name = "aws-sigv4" -version = "1.2.5" +version = "1.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5619742a0d8f253be760bfbb8e8e8368c69e3587e4637af5754e488a611499b1" +checksum = "c35452ec3f001e1f2f6db107b6373f1f48f05ec63ba2c5c9fa91f07dad32af11" dependencies = [ "aws-credential-types", "aws-smithy-http", @@ -610,8 +637,7 @@ dependencies = [ "hex", "hmac", "http 0.2.12", - "http 1.1.0", - "once_cell", + "http 1.3.1", "percent-encoding", "sha2", "time", @@ -620,9 +646,9 @@ dependencies = [ [[package]] name = "aws-smithy-async" -version = "1.2.1" +version = "1.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62220bc6e97f946ddd51b5f1361f78996e704677afc518a4ff66b7a72ea1378c" +checksum = "127fcfad33b7dfc531141fda7e1c402ac65f88aca5511a4d31e2e3d2cd01ce9c" dependencies = [ "futures-util", "pin-project-lite", @@ -631,38 +657,69 @@ dependencies = [ [[package]] name = "aws-smithy-http" -version = "0.60.11" +version = "0.62.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c8bc3e8fdc6b8d07d976e301c02fe553f72a39b7a9fea820e023268467d7ab6" +checksum = "445d5d720c99eed0b4aa674ed00d835d9b1427dd73e04adaf2f94c6b2d6f9fca" dependencies = [ "aws-smithy-runtime-api", "aws-smithy-types", "bytes", "bytes-utils", "futures-core", + "futures-util", "http 0.2.12", + "http 1.3.1", "http-body 0.4.6", - "once_cell", "percent-encoding", "pin-project-lite", "pin-utils", "tracing", ] +[[package]] +name = "aws-smithy-http-client" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "623254723e8dfd535f566ee7b2381645f8981da086b5c4aa26c0c41582bb1d2c" +dependencies = [ + "aws-smithy-async", + "aws-smithy-runtime-api", + "aws-smithy-types", + "h2 0.3.27", + "h2 0.4.12", + "http 0.2.12", + "http-body 0.4.6", + "hyper 0.14.32", + "hyper-rustls 0.24.2", + "pin-project-lite", + "rustls 0.21.12", + "tokio", + "tracing", +] + [[package]] name = "aws-smithy-json" -version = "0.60.7" +version = "0.61.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4683df9469ef09468dad3473d129960119a0d3593617542b7d52086c8486f2d6" +checksum = "2db31f727935fc63c6eeae8b37b438847639ec330a9161ece694efba257e0c54" dependencies = [ "aws-smithy-types", ] +[[package]] +name = "aws-smithy-observability" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d1881b1ea6d313f9890710d65c158bdab6fb08c91ea825f74c1c8c357baf4cc" +dependencies = [ + "aws-smithy-runtime-api", +] + [[package]] name = "aws-smithy-query" -version = "0.60.7" +version = "0.60.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2fbd61ceb3fe8a1cb7352e42689cec5335833cd9f94103a61e98f9bb61c64bb" +checksum = "d28a63441360c477465f80c7abac3b9c4d075ca638f982e605b7dc2a2c7156c9" dependencies = [ "aws-smithy-types", "urlencoding", @@ -670,42 +727,39 @@ dependencies = [ [[package]] name = "aws-smithy-runtime" -version = "1.7.3" +version = "1.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be28bd063fa91fd871d131fc8b68d7cd4c5fa0869bea68daca50dcb1cbd76be2" +checksum = "0bbe9d018d646b96c7be063dd07987849862b0e6d07c778aad7d93d1be6c1ef0" dependencies = [ "aws-smithy-async", "aws-smithy-http", + "aws-smithy-http-client", + "aws-smithy-observability", "aws-smithy-runtime-api", "aws-smithy-types", "bytes", - "fastrand 2.2.0", - "h2 0.3.26", + "fastrand 2.3.0", "http 0.2.12", + "http 1.3.1", "http-body 0.4.6", "http-body 1.0.1", - "httparse", - "hyper 0.14.31", - "hyper-rustls 0.24.2", - "once_cell", "pin-project-lite", "pin-utils", - "rustls 0.21.12", "tokio", "tracing", ] [[package]] name = "aws-smithy-runtime-api" -version = "1.7.3" +version = "1.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92165296a47a812b267b4f41032ff8069ab7ff783696d217f0994a0d7ab585cd" +checksum = "ec7204f9fd94749a7c53b26da1b961b4ac36bf070ef1e0b94bb09f79d4f6c193" dependencies = [ "aws-smithy-async", "aws-smithy-types", "bytes", "http 0.2.12", - "http 1.1.0", + "http 1.3.1", "pin-project-lite", "tokio", "tracing", @@ -714,16 +768,16 @@ dependencies = [ [[package]] name = "aws-smithy-types" -version = "1.2.9" +version = "1.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fbd94a32b3a7d55d3806fe27d98d3ad393050439dd05eb53ece36ec5e3d3510" +checksum = "25f535879a207fce0db74b679cfc3e91a3159c8144d717d55f5832aea9eef46e" dependencies = [ "base64-simd", "bytes", "bytes-utils", "futures-core", "http 0.2.12", - "http 1.1.0", + "http 1.3.1", "http-body 0.4.6", "http-body 1.0.1", "http-body-util", @@ -740,18 +794,18 @@ dependencies = [ [[package]] name = "aws-smithy-xml" -version = "0.60.9" +version = "0.60.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab0b0166827aa700d3dc519f72f8b3a91c35d0b8d042dc5d643a91e6f80648fc" +checksum = "eab77cdd036b11056d2a30a7af7b775789fb024bf216acc13884c6c97752ae56" dependencies = [ "xmlparser", ] [[package]] name = "aws-types" -version = "1.3.3" +version = "1.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5221b91b3e441e6675310829fd8984801b772cb1546ef6c0e54dec9f1ac13fef" +checksum = "d79fb68e3d7fe5d4833ea34dc87d2e97d26d3086cb3da660bb6b1f76d98680b6" dependencies = [ "aws-credential-types", "aws-smithy-async", @@ -771,7 +825,7 @@ dependencies = [ "axum-core", "bytes", "futures-util", - "http 1.1.0", + "http 1.3.1", "http-body 1.0.1", "http-body-util", "itoa", @@ -782,7 +836,7 @@ dependencies = [ "pin-project-lite", "rustversion", "serde", - "sync_wrapper 1.0.1", + "sync_wrapper 1.0.2", "tower 0.5.2", "tower-layer", "tower-service", @@ -797,13 +851,13 @@ dependencies = [ "async-trait", "bytes", "futures-util", - "http 1.1.0", + "http 1.3.1", "http-body 1.0.1", "http-body-util", "mime", "pin-project-lite", "rustversion", - "sync_wrapper 1.0.1", + "sync_wrapper 1.0.2", "tower-layer", "tower-service", ] @@ -818,13 +872,13 @@ dependencies = [ "bytes", "dyn-clone", "futures", - "getrandom 0.2.15", + "getrandom 0.2.16", "http-types", "once_cell", "paste", "pin-project", "rand 0.8.5", - "reqwest 0.12.9", + "reqwest 0.12.24", "rustc_version", "serde", "serde_json", @@ -845,14 +899,14 @@ dependencies = [ "bytes", "dyn-clone", "futures", - "getrandom 0.2.15", + "getrandom 0.2.16", "hmac", "http-types", "once_cell", "paste", "pin-project", "rand 0.8.5", - "reqwest 0.12.9", + "reqwest 0.12.24", "rustc_version", "serde", "serde_json", @@ -938,26 +992,26 @@ dependencies = [ [[package]] name = "backon" -version = "1.5.2" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "592277618714fbcecda9a02ba7a8781f319d26532a88553bbacc77ba5d2b3a8d" +checksum = "cffb0e931875b666fc4fcb20fee52e9bbd1ef836fd9e9e04ec21555f9f85f7ef" dependencies = [ - "fastrand 2.2.0", + "fastrand 2.3.0", ] [[package]] name = "backtrace" -version = "0.3.74" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6" dependencies = [ - "addr2line 0.24.2", + "addr2line", "cfg-if", "libc", "miniz_oxide", - "object 0.36.5", + "object", "rustc-demangle", - "windows-targets 0.52.6", + "windows-link 0.2.1", ] [[package]] @@ -996,9 +1050,9 @@ dependencies = [ [[package]] name = "base64ct" -version = "1.6.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba" [[package]] name = "beef" @@ -1101,16 +1155,25 @@ dependencies = [ "generic-array", ] +[[package]] +name = "block2" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5" +dependencies = [ + "objc2", +] + [[package]] name = "blocking" -version = "1.6.1" +version = "1.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "703f41c54fc768e63e091340b424302bb1c29ef4aa0c7f10fe849dfb114d29ea" +checksum = "e83f8d02be6967315521be875afa792a316e28d57b5a2d401897e2a7921b7f21" dependencies = [ - "async-channel 2.3.1", + "async-channel 2.5.0", "async-task", "futures-io", - "futures-lite 2.5.0", + "futures-lite 2.6.1", "piper", ] @@ -1159,9 +1222,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.16.0" +version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" dependencies = [ "allocator-api2", ] @@ -1190,18 +1253,18 @@ dependencies = [ [[package]] name = "bytemuck" -version = "1.19.0" +version = "1.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8334215b81e418a0a7bdb8ef0849474f40bb10c8b71f1c4ed315cff49f32494d" +checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4" dependencies = [ "bytemuck_derive", ] [[package]] name = "bytemuck_derive" -version = "1.8.0" +version = "1.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcfcc3cd946cb52f0bbfdbbcfa2f4e24f75ebb6c0e1002f7c25904fada18b9ec" +checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff" dependencies = [ "proc-macro2", "quote", @@ -1216,9 +1279,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.8.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" dependencies = [ "serde", ] @@ -1235,11 +1298,11 @@ dependencies = [ [[package]] name = "camino" -version = "1.1.9" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3" +checksum = "276a59bf2b2c967788139340c9f0c5b12d7fd6630315c15c217e559de85d2609" dependencies = [ - "serde", + "serde_core", ] [[package]] @@ -1258,7 +1321,7 @@ dependencies = [ "metal 0.27.0", "num-traits", "num_cpus", - "rand 0.9.1", + "rand 0.9.2", "rand_distr", "rayon", "safetensors 0.4.5", @@ -1266,7 +1329,7 @@ dependencies = [ "ug", "ug-cuda", "ug-metal", - "yoke", + "yoke 0.7.5", "zip", ] @@ -1319,7 +1382,7 @@ dependencies = [ "candle-nn", "fancy-regex", "num-traits", - "rand 0.9.1", + "rand 0.9.2", "rayon", "serde", "serde_json", @@ -1329,9 +1392,9 @@ dependencies = [ [[package]] name = "cap-fs-ext" -version = "3.4.4" +version = "3.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e41cc18551193fe8fa6f15c1e3c799bc5ec9e2cfbfaa8ed46f37013e3e6c173c" +checksum = "d5528f85b1e134ae811704e41ef80930f56e795923f866813255bc342cc20654" dependencies = [ "cap-primitives", "cap-std", @@ -1341,21 +1404,21 @@ dependencies = [ [[package]] name = "cap-net-ext" -version = "3.4.4" +version = "3.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f83833816c66c986e913b22ac887cec216ea09301802054316fc5301809702c" +checksum = "20a158160765c6a7d0d8c072a53d772e4cb243f38b04bfcf6b4939cfbe7482e7" dependencies = [ "cap-primitives", "cap-std", - "rustix 1.0.5", + "rustix 1.1.2", "smallvec", ] [[package]] name = "cap-primitives" -version = "3.4.4" +version = "3.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a1e394ed14f39f8bc26f59d4c0c010dbe7f0a1b9bafff451b1f98b67c8af62a" +checksum = "b6cf3aea8a5081171859ef57bc1606b1df6999df4f1110f8eef68b30098d1d3a" dependencies = [ "ambient-authority", "fs-set-times", @@ -1363,7 +1426,7 @@ dependencies = [ "io-lifetimes", "ipnet", "maybe-owned", - "rustix 1.0.5", + "rustix 1.1.2", "rustix-linux-procfs", "windows-sys 0.59.0", "winx", @@ -1371,9 +1434,9 @@ dependencies = [ [[package]] name = "cap-rand" -version = "3.4.4" +version = "3.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0acb89ccf798a28683f00089d0630dfaceec087234eae0d308c05ddeaa941b40" +checksum = "d8144c22e24bbcf26ade86cb6501a0916c46b7e4787abdb0045a467eb1645a1d" dependencies = [ "ambient-authority", "rand 0.8.5", @@ -1381,35 +1444,35 @@ dependencies = [ [[package]] name = "cap-std" -version = "3.4.4" +version = "3.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07c0355ca583dd58f176c3c12489d684163861ede3c9efa6fd8bba314c984189" +checksum = "b6dc3090992a735d23219de5c204927163d922f42f575a0189b005c62d37549a" dependencies = [ "cap-primitives", "io-extras", "io-lifetimes", - "rustix 1.0.5", + "rustix 1.1.2", ] [[package]] name = "cap-time-ext" -version = "3.4.4" +version = "3.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "491af520b8770085daa0466978c75db90368c71896523f2464214e38359b1a5b" +checksum = "def102506ce40c11710a9b16e614af0cde8e76ae51b1f48c04b8d79f4b671a80" dependencies = [ "ambient-authority", "cap-primitives", "iana-time-zone", "once_cell", - "rustix 1.0.5", + "rustix 1.1.2", "winx", ] [[package]] name = "cargo-platform" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24b1f0365a6c6bb4020cd05806fd0d33c44d38046b8bd7f0e40814b9763cabfc" +checksum = "e35af189006b9c0f00a064685c727031e3ed2d8020f7ba284d78cc2671bd36ea" dependencies = [ "serde", ] @@ -1443,7 +1506,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a969e13a7589e9e3e4207e153bae624ade2b5622fb4684a4923b23ec3d57719" dependencies = [ "serde", - "toml", + "toml 0.8.23", +] + +[[package]] +name = "castaway" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dec551ab6e7578819132c713a93c022a05d60159dc86e7a7050223577484c55a" +dependencies = [ + "rustversion", ] [[package]] @@ -1457,9 +1529,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.41" +version = "1.2.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac9fe6cdbb24b6ade63616c0a0688e45bb56732262c158df3c0c4bea4ca47cb7" +checksum = "37521ac7aabe3d13122dc382493e20c9416f299d2ccd5b3a5340a2570cdeb0f3" dependencies = [ "find-msvc-tools", "jobserver", @@ -1469,9 +1541,9 @@ dependencies = [ [[package]] name = "cfg-if" -version = "1.0.0" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "cfg_aliases" @@ -1481,17 +1553,16 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chrono" -version = "0.4.38" +version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2" dependencies = [ - "android-tzdata", "iana-time-zone", "js-sys", "num-traits", "serde", "wasm-bindgen", - "windows-targets 0.52.6", + "windows-link 0.2.1", ] [[package]] @@ -1523,23 +1594,23 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.20" +version = "4.5.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" +checksum = "4c26d721170e0295f191a69bd9a1f93efcdb0aff38684b61ab5750468972e5f5" dependencies = [ "clap_builder", - "clap_derive 4.5.18", + "clap_derive 4.5.49", ] [[package]] name = "clap_builder" -version = "4.5.20" +version = "4.5.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" +checksum = "75835f0c7bf681bfd05abe44e965760fea999a5286c6eb2d59883634fd02011a" dependencies = [ "anstream", "anstyle", - "clap_lex 0.7.2", + "clap_lex 0.7.6", "strsim 0.11.1", ] @@ -1558,9 +1629,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.18" +version = "4.5.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" +checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671" dependencies = [ "heck 0.5.0", "proc-macro2", @@ -1579,15 +1650,15 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.2" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" +checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d" [[package]] name = "clearscreen" -version = "4.0.1" +version = "4.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c41dc435a7b98e4608224bbf65282309f5403719df9113621b30f8b6f74e2f4" +checksum = "85a8ab73a1c02b0c15597b22e09c7dc36e63b2f601f9d1e83ac0c3decd38b1ae" dependencies = [ "nix 0.29.0", "terminfo", @@ -1598,24 +1669,27 @@ dependencies = [ [[package]] name = "cmake" -version = "0.1.51" +version = "0.1.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb1e43aa7fd152b1f968787f7dbcdeb306d1867ff373c69955211876c053f91a" +checksum = "e7caa3f9de89ddbe2c607f4101924c5abec803763ae9534e4f4d7d8f84aa81f0" dependencies = [ "cc", ] [[package]] name = "cobs" -version = "0.2.3" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15" +checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1" +dependencies = [ + "thiserror 2.0.17", +] [[package]] name = "colorchoice" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" [[package]] name = "combine" @@ -1633,14 +1707,13 @@ dependencies = [ [[package]] name = "comfy-table" -version = "7.1.1" +version = "7.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b34115915337defe99b2aff5c2ce6771e5fbc4079f4b506301f5cf394c8452f7" +checksum = "b03b7db8e0b4b2fdad6c551e634134e99ec000e5c8c3b6856c65e8bbaded7a3b" dependencies = [ "crossterm", - "strum 0.26.3", - "strum_macros 0.26.4", - "unicode-width 0.1.14", + "unicode-segmentation", + "unicode-width 0.2.2", ] [[package]] @@ -1655,6 +1728,38 @@ dependencies = [ "winapi", ] +[[package]] +name = "compact_str" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb1325a1cece981e8a296ab8f0f9b63ae357bd0784a9faaf548cc7b480707a" +dependencies = [ + "castaway", + "cfg-if", + "itoa", + "rustversion", + "ryu", + "serde", + "static_assertions", +] + +[[package]] +name = "compression-codecs" +version = "0.4.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef8a506ec4b81c460798f572caead636d57d3d7e940f998160f52bd254bf2d23" +dependencies = [ + "compression-core", + "flate2", + "memchr", +] + +[[package]] +name = "compression-core" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e47641d3deaf41fb1538ac1f54735925e275eaf3bf4d55c81b137fba797e5cbb" + [[package]] name = "concurrent-queue" version = "2.5.0" @@ -1679,7 +1784,7 @@ dependencies = [ "rust-ini", "serde", "serde_json", - "toml", + "toml 0.8.23", "yaml-rust2", ] @@ -1702,7 +1807,7 @@ dependencies = [ "flate2", "json5", "libtest-mimic", - "reqwest 0.12.9", + "reqwest 0.12.24", "serde", "tar", "test-environment", @@ -1710,15 +1815,15 @@ dependencies = [ [[package]] name = "console" -version = "0.15.8" +version = "0.15.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb" +checksum = "054ccb5b10f9f2cbf51eb355ca1d05c2d279ce1804688d0db74b4733a5aeafd8" dependencies = [ "encode_unicode", - "lazy_static 1.5.0", "libc", - "unicode-width 0.1.14", - "windows-sys 0.52.0", + "once_cell", + "unicode-width 0.2.2", + "windows-sys 0.59.0", ] [[package]] @@ -1742,16 +1847,16 @@ version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" dependencies = [ - "getrandom 0.2.15", + "getrandom 0.2.16", "once_cell", "tiny-keccak", ] [[package]] name = "const_fn" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "373e9fafaa20882876db20562275ff58d50e0caa2590077fe7ce7bef90211d0d" +checksum = "2f8a2ca5ac02d09563609681103aada9e1777d54fc57a5acd7a41404f9c93b6e" [[package]] name = "convert_case" @@ -1774,9 +1879,9 @@ dependencies = [ [[package]] name = "core-foundation" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" +checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" dependencies = [ "core-foundation-sys", "libc", @@ -1801,54 +1906,54 @@ dependencies = [ [[package]] name = "cpp_demangle" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96e58d342ad113c2b878f16d5d034c03be492ae460cdbc02b7f0f2284d310c7d" +checksum = "f2bb79cb74d735044c972aae58ed0aaa9a837e85b01106a54c39e42e97f62253" dependencies = [ "cfg-if", ] [[package]] name = "cpufeatures" -version = "0.2.15" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ca741a962e1b0bff6d724a1a0958b686406e853bb14061f218562e1896f95e6" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" dependencies = [ "libc", ] [[package]] name = "cranelift-assembler-x64" -version = "0.124.1" +version = "0.124.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3e8ca189363907c025c5debe2bfe56c8c18503d4575d750f87e4ccbbfbd8681" +checksum = "f6e2df3d5caad11e71bb0b70115a5210c3af4a0bcb2893f78ee9311b1b266b05" dependencies = [ "cranelift-assembler-x64-meta", ] [[package]] name = "cranelift-assembler-x64-meta" -version = "0.124.1" +version = "0.124.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e169461bfd463df68b01b196522f263c905eadc852f6e57fd4ce4c5d76115ead" +checksum = "b63e87985fc9166a2541b05fd5f913a398cff9aec6b13ebca865253cdee15806" dependencies = [ "cranelift-srcgen", ] [[package]] name = "cranelift-bforest" -version = "0.124.1" +version = "0.124.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a98298338375075287834defe333d552847110f3a04db0ce19bd308b4c40fbb" +checksum = "3b5364dfe182d4b89af2f4bd0dafc8f6c590bbf0216ee8ce60bfd8893c3d14a6" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-bitset" -version = "0.124.1" +version = "0.124.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edf5f49a2e2ae284db75437a49cc13220a7fb394983d5545af1209ab0bbadee3" +checksum = "3067ca8c10796434497a5faac73d949b5ac0008ed572013debe88694bfef426e" dependencies = [ "serde", "serde_derive", @@ -1856,9 +1961,9 @@ dependencies = [ [[package]] name = "cranelift-codegen" -version = "0.124.1" +version = "0.124.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c354d6db9e344f647f38c88849c482c6014b79a295aca23fa82f73b62caeda2d" +checksum = "8eb420cc46d7f0956e2e3d9e6389036c612ada3542a29edc6f5deedf86d568ba" dependencies = [ "bumpalo", "cranelift-assembler-x64", @@ -1869,8 +1974,8 @@ dependencies = [ "cranelift-control", "cranelift-entity", "cranelift-isle", - "gimli 0.32.0", - "hashbrown 0.15.2", + "gimli", + "hashbrown 0.15.5", "log", "pulley-interpreter", "regalloc2", @@ -1883,9 +1988,9 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.124.1" +version = "0.124.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bb8008396957de750e26d0b40a76bea6e5623d970a5bfe4266ef0a79ccb8341" +checksum = "440d31dd36e477fb6292821b593da65df60328bca1046ea5881f424aa5a44b5d" dependencies = [ "cranelift-assembler-x64-meta", "cranelift-codegen-shared", @@ -1896,24 +2001,24 @@ dependencies = [ [[package]] name = "cranelift-codegen-shared" -version = "0.124.1" +version = "0.124.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98ecb53eafe1ad1f7d7f7d0585ae5d42b2050978fa812216b0420d4752eb41cb" +checksum = "f0b342ef4835787577f6e7553747cdd902797509eb5af733cd89e5ce97cea0f0" [[package]] name = "cranelift-control" -version = "0.124.1" +version = "0.124.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9c43ac27fe178cadb17e7f4cf1320ba89b8875cc2bdee265cccfca49bc76c95" +checksum = "b34de54534b61c3f3e475558cf19c90b2a7a758c7018e557e5d1a47b9a1fbb03" dependencies = [ "arbitrary", ] [[package]] name = "cranelift-entity" -version = "0.124.1" +version = "0.124.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15513ee4bf648d366654c6a9864fe870ca64f1eed4acabf9139056e68b3d44dc" +checksum = "b3d7bf1aae1800d053aa965381dcb01054404d0bcd8ea5ffe65bb855b8e3f654" dependencies = [ "cranelift-bitset", "serde", @@ -1922,9 +2027,9 @@ dependencies = [ [[package]] name = "cranelift-frontend" -version = "0.124.1" +version = "0.124.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5e4399d31f06b50fcb3fa0117ff4c393c22e521574eecf524cf932fc99cd78f" +checksum = "36158c03d70e1f443cc2d6d9adc838fc0a031b166f3861534e9cb77742380e2a" dependencies = [ "cranelift-codegen", "log", @@ -1934,15 +2039,15 @@ dependencies = [ [[package]] name = "cranelift-isle" -version = "0.124.1" +version = "0.124.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a751ec2b7c2f281274a3798e37ba2344b55f60789e67aaa10d6bbea3f3f8a6b" +checksum = "4fa194bbc189c965454f3a94c1acb6c89d63d5d0b183e60edc17db758bfbe519" [[package]] name = "cranelift-native" -version = "0.124.1" +version = "0.124.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "546500d7cb424c423e118dfddc169aa61ed611c47fc1cf48783ed4e3f9800619" +checksum = "1c469bb98ffe9f38a1a5ada0427ab096f0f1b9a22a30149fc705205c56cf8985" dependencies = [ "cranelift-codegen", "libc", @@ -1951,15 +2056,15 @@ dependencies = [ [[package]] name = "cranelift-srcgen" -version = "0.124.1" +version = "0.124.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edeb6b718b23108a123ad1c8eecf6fa34d21a6b5518fc340dda80ce5bdf42377" +checksum = "12d694cd4c6b28fb8a4d0cf5b58d532b6b3b6e4afb2b65603e2ab8dc35bf18bd" [[package]] name = "crc32fast" -version = "1.4.2" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" dependencies = [ "cfg-if", ] @@ -1988,9 +2093,9 @@ dependencies = [ [[package]] name = "crossbeam-deque" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" dependencies = [ "crossbeam-epoch", "crossbeam-utils", @@ -2007,29 +2112,30 @@ dependencies = [ [[package]] name = "crossbeam-queue" -version = "0.3.11" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" +checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.20" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crossterm" -version = "0.27.0" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df" +checksum = "d8b9f2e4c67f833b660cdb0a3523065869fb35570177239812ed4c905aeff87b" dependencies = [ "bitflags 2.10.0", "crossterm_winapi", - "libc", + "document-features", "parking_lot", + "rustix 1.1.2", "winapi", ] @@ -2044,9 +2150,9 @@ dependencies = [ [[package]] name = "crunchy" -version = "0.2.2" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" [[package]] name = "crypto-bigint" @@ -2072,12 +2178,13 @@ dependencies = [ [[package]] name = "ctrlc" -version = "3.4.5" +version = "3.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90eeab0aa92f3f9b4e87f258c72b139c207d251f9cbc1080a0086b86a8870dd3" +checksum = "73736a89c4aff73035ba2ed2e565061954da00d4970fc9ac25dcc85a2a20d790" dependencies = [ - "nix 0.29.0", - "windows-sys 0.59.0", + "dispatch2", + "nix 0.30.1", + "windows-sys 0.61.2", ] [[package]] @@ -2102,12 +2209,22 @@ dependencies = [ [[package]] name = "darling" -version = "0.20.10" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" +dependencies = [ + "darling_core 0.20.11", + "darling_macro 0.20.11", +] + +[[package]] +name = "darling" +version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" +checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" dependencies = [ - "darling_core 0.20.10", - "darling_macro 0.20.10", + "darling_core 0.21.3", + "darling_macro 0.21.3", ] [[package]] @@ -2126,9 +2243,23 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.10" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim 0.11.1", + "syn 2.0.108", +] + +[[package]] +name = "darling_core" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4" dependencies = [ "fnv", "ident_case", @@ -2151,51 +2282,72 @@ dependencies = [ [[package]] name = "darling_macro" -version = "0.20.10" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ - "darling_core 0.20.10", + "darling_core 0.20.11", "quote", "syn 2.0.108", ] +[[package]] +name = "darling_macro" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" +dependencies = [ + "darling_core 0.21.3", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "dary_heap" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06d2e3287df1c007e74221c49ca10a95d557349e54b3a75dc2fb14712c751f04" +dependencies = [ + "serde", +] + [[package]] name = "dbus" -version = "0.9.7" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bb21987b9fb1613058ba3843121dd18b163b254d8a6e797e144cbac14d96d1b" +checksum = "190b6255e8ab55a7b568df5a883e9497edc3e4821c06396612048b430e5ad1e9" dependencies = [ "libc", "libdbus-sys", - "winapi", + "windows-sys 0.59.0", ] [[package]] name = "dbus-secret-service" -version = "4.0.3" +version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42a16374481d92aed73ae45b1f120207d8e71d24fb89f357fadbd8f946fd84b" +checksum = "708b509edf7889e53d7efb0ffadd994cc6c2345ccb62f55cfd6b0682165e4fa6" dependencies = [ "aes", "block-padding", "cbc", "dbus", - "futures-util", + "fastrand 2.3.0", "hkdf", "num", "once_cell", - "rand 0.8.5", "sha2", + "zeroize", ] [[package]] name = "deadpool" -version = "0.12.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ed5957ff93768adf7a65ab167a17835c3d2c3c50d084fe305174c112f468e2f" +checksum = "0be2b1d1d6ec8d846f05e137292d0b89133caf95ef33695424c09568bdd39b1b" dependencies = [ "deadpool-runtime", + "lazy_static 1.5.0", "num_cpus", "tokio", ] @@ -2208,7 +2360,7 @@ checksum = "3d697d376cbfa018c23eb4caab1fd1883dd9c906a8c034e8d9a3cb06a7e0bef9" dependencies = [ "async-trait", "deadpool", - "getrandom 0.2.15", + "getrandom 0.2.16", "tokio", "tokio-postgres", "tracing", @@ -2234,9 +2386,9 @@ dependencies = [ [[package]] name = "der" -version = "0.7.9" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" +checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" dependencies = [ "const-oid", "pem-rfc7468", @@ -2245,19 +2397,19 @@ dependencies = [ [[package]] name = "deranged" -version = "0.3.11" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587" dependencies = [ "powerfmt", - "serde", + "serde_core", ] [[package]] name = "derive_arbitrary" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30542c1ad912e0e3d22a1935c290e12e8a29d704a420177a31faad4a601a0800" +checksum = "1e567bd82dcff979e4b03460c307b3cdc9e96fde3d73bed1496d2bc75d9dd62a" dependencies = [ "proc-macro2", "quote", @@ -2300,7 +2452,7 @@ version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" dependencies = [ - "darling 0.20.10", + "darling 0.20.11", "proc-macro2", "quote", "syn 2.0.108", @@ -2414,8 +2566,8 @@ checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" dependencies = [ "libc", "option-ext", - "redox_users 0.5.0", - "windows-sys 0.60.2", + "redox_users 0.5.2", + "windows-sys 0.61.2", ] [[package]] @@ -2429,6 +2581,18 @@ dependencies = [ "winapi", ] +[[package]] +name = "dispatch2" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec" +dependencies = [ + "bitflags 2.10.0", + "block2", + "libc", + "objc2", +] + [[package]] name = "displaydoc" version = "0.2.5" @@ -2476,23 +2640,26 @@ dependencies = [ "const-random", ] -[[package]] -name = "doc-comment" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" - [[package]] name = "docker_credential" -version = "1.3.1" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31951f49556e34d90ed28342e1df7e1cb7a229c4cab0aecc627b5d91edd41d07" +checksum = "1d89dfcba45b4afad7450a99b39e751590463e45c04728cf555d36bb66940de8" dependencies = [ "base64 0.21.7", "serde", "serde_json", ] +[[package]] +name = "document-features" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61" +dependencies = [ + "litrs", +] + [[package]] name = "dotenvy" version = "0.15.7" @@ -2507,9 +2674,9 @@ checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" [[package]] name = "dyn-clone" -version = "1.0.17" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" +checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" [[package]] name = "dyn-stack" @@ -2523,13 +2690,20 @@ dependencies = [ [[package]] name = "dyn-stack" -version = "0.13.0" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "490bd48eb68fffcfed519b4edbfd82c69cbe741d175b84f0e0cbe8c57cbe0bdd" +checksum = "1c4713e43e2886ba72b8271aa66c93d722116acf7a75555cce11dcde84388fe8" dependencies = [ "bytemuck", + "dyn-stack-macros", ] +[[package]] +name = "dyn-stack-macros" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1d926b4d407d372f141f93bb444696142c29d32962ccbd3531117cf3aa0bfa9" + [[package]] name = "ecdsa" version = "0.16.9" @@ -2546,9 +2720,9 @@ dependencies = [ [[package]] name = "either" -version = "1.13.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] name = "elliptic-curve" @@ -2584,9 +2758,9 @@ checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" [[package]] name = "encode_unicode" -version = "0.3.6" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" +checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" [[package]] name = "encoding_rs" @@ -2623,9 +2797,9 @@ dependencies = [ [[package]] name = "enumflags2" -version = "0.7.10" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d232db7f5956f3f14313dc2f87985c58bd2c695ce124c8cdd984e08e15ac133d" +checksum = "1027f7680c853e056ebcec683615fb6fbbc07dbaa13b4d5d9442b146ded4ecef" dependencies = [ "enumflags2_derive", "serde", @@ -2633,9 +2807,9 @@ dependencies = [ [[package]] name = "enumflags2_derive" -version = "0.7.10" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de0d48a183585823424a4ce1aa132d174a6a81bd540895822eb4c8373a8e49e8" +checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827" dependencies = [ "proc-macro2", "quote", @@ -2663,18 +2837,18 @@ dependencies = [ [[package]] name = "equivalent" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" -version = "0.3.11" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "976dd42dc7e85965fe702eb8164f21f450704bdde31faefd6471dba214cb594e" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -2722,9 +2896,9 @@ dependencies = [ [[package]] name = "event-listener" -version = "5.3.1" +version = "5.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba" +checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" dependencies = [ "concurrent-queue", "parking", @@ -2733,11 +2907,11 @@ dependencies = [ [[package]] name = "event-listener-strategy" -version = "0.5.2" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" +checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" dependencies = [ - "event-listener 5.3.1", + "event-listener 5.4.1", "pin-project-lite", ] @@ -2756,6 +2930,25 @@ dependencies = [ "syn 2.0.108", ] +[[package]] +name = "fake-opentelemetry-collector" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ce713bed1dfc379216421ebf0c4ee2268b5cb4d7894bed8a96d267834590916" +dependencies = [ + "futures", + "hex", + "opentelemetry", + "opentelemetry-otlp", + "opentelemetry-proto", + "opentelemetry_sdk", + "serde", + "tokio", + "tokio-stream", + "tonic", + "tracing", +] + [[package]] name = "fallible-iterator" version = "0.2.0" @@ -2806,26 +2999,26 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "fd-lock" -version = "4.0.2" +version = "4.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e5768da2206272c81ef0b5e951a41862938a6070da63bcea197899942d3b947" +checksum = "0ce92ff622d6dadf7349484f42c93271a0d49b7cc4d466a936405bacbe10aa78" dependencies = [ "cfg-if", - "rustix 0.38.40", - "windows-sys 0.52.0", + "rustix 1.1.2", + "windows-sys 0.59.0", ] [[package]] name = "ff" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" dependencies = [ "rand_core 0.6.4", "subtle", @@ -2843,14 +3036,14 @@ dependencies = [ [[package]] name = "filetime" -version = "0.2.25" +version = "0.2.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" +checksum = "bc0505cd1b6fa6580283f6bdf70a73fcf4aba1184038c90902b92b3dd0df63ed" dependencies = [ "cfg-if", "libc", "libredox", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -2867,9 +3060,9 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.1.0" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11faaf5a5236997af9848be0bef4db95824b1d534ebc64d0f0c6cf3e67bd38dc" +checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb" dependencies = [ "crc32fast", "miniz_oxide", @@ -2894,9 +3087,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "foldhash" -version = "0.1.3" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f81ec6369c545a7d40e4589b5597581fa1c441fe1cce96dd1de43159910a36a2" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" [[package]] name = "foreign-types" @@ -2960,13 +3153,13 @@ dependencies = [ [[package]] name = "fs-set-times" -version = "0.20.1" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "033b337d725b97690d86893f9de22b67b80dcc4e9ad815f348254c38119db8fb" +checksum = "94e7099f6313ecacbe1256e8ff9d617b75d1bcb16a6fddef94866d225a01a14a" dependencies = [ "io-lifetimes", - "rustix 0.38.40", - "windows-sys 0.52.0", + "rustix 1.1.2", + "windows-sys 0.59.0", ] [[package]] @@ -3065,11 +3258,11 @@ dependencies = [ [[package]] name = "futures-lite" -version = "2.5.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cef40d21ae2c515b51041df9ed313ed21e572df340ea58a922a0aefe7e8891a1" +checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad" dependencies = [ - "fastrand 2.2.0", + "fastrand 2.3.0", "futures-core", "futures-io", "parking", @@ -3165,7 +3358,7 @@ version = "0.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab96b703d31950f1aeddded248bc95543c9efc7ac9c4a21fda8703a83ee35451" dependencies = [ - "dyn-stack 0.13.0", + "dyn-stack 0.13.2", "gemm-c32 0.18.2", "gemm-c64 0.18.2", "gemm-common 0.18.2", @@ -3175,7 +3368,7 @@ dependencies = [ "num-complex", "num-traits", "paste", - "raw-cpuid 11.5.0", + "raw-cpuid 11.6.0", "seq-macro", ] @@ -3200,12 +3393,12 @@ version = "0.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6db9fd9f40421d00eea9dd0770045a5603b8d684654816637732463f4073847" dependencies = [ - "dyn-stack 0.13.0", + "dyn-stack 0.13.2", "gemm-common 0.18.2", "num-complex", "num-traits", "paste", - "raw-cpuid 11.5.0", + "raw-cpuid 11.6.0", "seq-macro", ] @@ -3230,12 +3423,12 @@ version = "0.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfcad8a3d35a43758330b635d02edad980c1e143dc2f21e6fd25f9e4eada8edf" dependencies = [ - "dyn-stack 0.13.0", + "dyn-stack 0.13.2", "gemm-common 0.18.2", "num-complex", "num-traits", "paste", - "raw-cpuid 11.5.0", + "raw-cpuid 11.6.0", "seq-macro", ] @@ -3266,15 +3459,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a352d4a69cbe938b9e2a9cb7a3a63b7e72f9349174a2752a558a8a563510d0f3" dependencies = [ "bytemuck", - "dyn-stack 0.13.0", + "dyn-stack 0.13.2", "half", "libm", "num-complex", "num-traits", "once_cell", "paste", - "pulp 0.21.4", - "raw-cpuid 11.5.0", + "pulp 0.21.5", + "raw-cpuid 11.6.0", "rayon", "seq-macro", "sysctl 0.6.0", @@ -3304,14 +3497,14 @@ version = "0.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cff95ae3259432f3c3410eaa919033cd03791d81cebd18018393dc147952e109" dependencies = [ - "dyn-stack 0.13.0", + "dyn-stack 0.13.2", "gemm-common 0.18.2", "gemm-f32 0.18.2", "half", "num-complex", "num-traits", "paste", - "raw-cpuid 11.5.0", + "raw-cpuid 11.6.0", "rayon", "seq-macro", ] @@ -3337,12 +3530,12 @@ version = "0.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc8d3d4385393304f407392f754cd2dc4b315d05063f62cf09f47b58de276864" dependencies = [ - "dyn-stack 0.13.0", + "dyn-stack 0.13.2", "gemm-common 0.18.2", "num-complex", "num-traits", "paste", - "raw-cpuid 11.5.0", + "raw-cpuid 11.6.0", "seq-macro", ] @@ -3367,34 +3560,20 @@ version = "0.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35b2a4f76ce4b8b16eadc11ccf2e083252d8237c1b589558a49b0183545015bd" dependencies = [ - "dyn-stack 0.13.0", + "dyn-stack 0.13.2", "gemm-common 0.18.2", "num-complex", "num-traits", "paste", - "raw-cpuid 11.5.0", + "raw-cpuid 11.6.0", "seq-macro", ] -[[package]] -name = "generator" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d18470a76cb7f8ff746cf1f7470914f900252ec36bbc40b569d74b1258446827" -dependencies = [ - "cc", - "cfg-if", - "libc", - "log", - "rustversion", - "windows", -] - [[package]] name = "generic-array" -version = "0.14.7" +version = "0.14.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2" dependencies = [ "typenum", "version_check", @@ -3414,34 +3593,36 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ "cfg-if", "js-sys", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi 0.11.1+wasi-snapshot-preview1", "wasm-bindgen", ] [[package]] name = "getrandom" -version = "0.3.2" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", + "js-sys", "libc", "r-efi", - "wasi 0.14.2+wasi-0.2.4", + "wasip2", + "wasm-bindgen", ] [[package]] name = "getset" -version = "0.1.3" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f636605b743120a8d32ed92fc27b6cde1a769f8f936c065151eb66f88ded513c" +checksum = "9cf0fc11e47561d47397154977bc219f4cf809b2974facc3ccb3b89e2436f912" dependencies = [ "proc-macro-error2", "proc-macro2", @@ -3451,15 +3632,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.31.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" - -[[package]] -name = "gimli" -version = "0.32.0" +version = "0.32.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93563d740bc9ef04104f9ed6f86f1e3275c2cdafb95664e26584b9ca807a8ffe" +checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" dependencies = [ "fallible-iterator 0.3.0", "indexmap 2.12.0", @@ -3477,7 +3652,7 @@ dependencies = [ "gix-utils", "itoa", "thiserror 2.0.17", - "winnow 0.7.13", + "winnow", ] [[package]] @@ -3498,7 +3673,7 @@ dependencies = [ "smallvec", "thiserror 2.0.17", "unicode-bom", - "winnow 0.7.13", + "winnow", ] [[package]] @@ -3548,7 +3723,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67a0637149b4ef24d3ea55f81f77231401c8463fae6da27331c987957eb597c7" dependencies = [ "bstr", - "fastrand 2.2.0", + "fastrand 2.3.0", "gix-features", "gix-path", "gix-utils", @@ -3619,7 +3794,7 @@ dependencies = [ "itoa", "smallvec", "thiserror 2.0.17", - "winnow 0.7.13", + "winnow", ] [[package]] @@ -3653,7 +3828,7 @@ dependencies = [ "gix-validate", "memmap2", "thiserror 2.0.17", - "winnow 0.7.13", + "winnow", ] [[package]] @@ -3693,7 +3868,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "befcdbdfb1238d2854591f760a48711bed85e72d80a10e8f2f93f656746ef7c5" dependencies = [ - "fastrand 2.2.0", + "fastrand 2.3.0", "unicode-normalization", ] @@ -3709,15 +3884,15 @@ dependencies = [ [[package]] name = "glob" -version = "0.3.1" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" [[package]] name = "globset" -version = "0.4.15" +version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15f1ce686646e7f1e19bf7d5533fe443a45dbfb990e00629110797578b42fb19" +checksum = "52dfc19153a48bde0cbd630453615c8151bce3a5adfac7a0aebfbf0a1e1f57e3" dependencies = [ "aho-corasick", "bstr", @@ -3726,6 +3901,18 @@ dependencies = [ "regex-syntax", ] +[[package]] +name = "gloo-timers" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994" +dependencies = [ + "futures-channel", + "futures-core", + "js-sys", + "wasm-bindgen", +] + [[package]] name = "group" version = "0.13.0" @@ -3739,9 +3926,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.26" +version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" +checksum = "0beca50380b1fc32983fc1cb4587bfa4bb9e78fc259aad4a0032d2080309222d" dependencies = [ "bytes", "fnv", @@ -3758,16 +3945,16 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.6" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" +checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386" dependencies = [ "atomic-waker", "bytes", "fnv", "futures-core", "futures-sink", - "http 1.1.0", + "http 1.3.1", "indexmap 2.12.0", "slab", "tokio", @@ -3777,16 +3964,17 @@ dependencies = [ [[package]] name = "half" -version = "2.6.0" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" dependencies = [ "bytemuck", "cfg-if", "crunchy", "num-traits", - "rand 0.9.1", + "rand 0.9.2", "rand_distr", + "zerocopy", ] [[package]] @@ -3813,15 +4001,15 @@ version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ - "ahash 0.8.11", + "ahash 0.8.12", "allocator-api2", ] [[package]] name = "hashbrown" -version = "0.15.2" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ "allocator-api2", "equivalent", @@ -3850,7 +4038,7 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" dependencies = [ - "hashbrown 0.15.2", + "hashbrown 0.15.5", ] [[package]] @@ -3895,15 +4083,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" - -[[package]] -name = "hermit-abi" -version = "0.4.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" [[package]] name = "hex" @@ -3931,11 +4113,11 @@ dependencies = [ [[package]] name = "home" -version = "0.5.9" +version = "0.5.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -3951,9 +4133,9 @@ dependencies = [ [[package]] name = "http" -version = "1.1.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" dependencies = [ "bytes", "fnv", @@ -3987,18 +4169,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", - "http 1.1.0", + "http 1.3.1", ] [[package]] name = "http-body-util" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" dependencies = [ "bytes", - "futures-util", - "http 1.1.0", + "futures-core", + "http 1.3.1", "http-body 1.0.1", "pin-project-lite", ] @@ -4025,9 +4207,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.9.5" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" [[package]] name = "httpdate" @@ -4037,28 +4219,28 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "humantime" -version = "2.1.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" +checksum = "135b12329e5e3ce057a9f972339ea52bc954fe1e9358ef27f95e89716fbc5424" [[package]] name = "hyper" -version = "0.14.31" +version = "0.14.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c08302e8fa335b151b788c775ff56e7a03ae64ff85c548ee820fecb70356e85" +checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7" dependencies = [ "bytes", "futures-channel", "futures-core", "futures-util", - "h2 0.3.26", + "h2 0.3.27", "http 0.2.12", "http-body 0.4.6", "httparse", "httpdate", "itoa", "pin-project-lite", - "socket2 0.5.7", + "socket2 0.5.10", "tokio", "tower-service", "tracing", @@ -4067,20 +4249,22 @@ dependencies = [ [[package]] name = "hyper" -version = "1.5.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbbff0a806a4728c99295b254c8838933b5b082d75e3cb70c8dab21fdfbcfa9a" +checksum = "eb3aa54a13a0dfe7fbe3a59e0c76093041720fdc77b110cc0fc260fafb4dc51e" dependencies = [ + "atomic-waker", "bytes", "futures-channel", - "futures-util", - "h2 0.4.6", - "http 1.1.0", + "futures-core", + "h2 0.4.12", + "http 1.3.1", "http-body 1.0.1", "httparse", "httpdate", "itoa", "pin-project-lite", + "pin-utils", "smallvec", "tokio", "want", @@ -4094,7 +4278,7 @@ checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ "futures-util", "http 0.2.12", - "hyper 0.14.31", + "hyper 0.14.32", "log", "rustls 0.21.12", "rustls-native-certs 0.6.3", @@ -4110,32 +4294,31 @@ checksum = "399c78f9338483cb7e630c8474b07268983c6bd5acee012e4211f9f7bb21b070" dependencies = [ "futures-util", "http 0.2.12", - "hyper 0.14.31", + "hyper 0.14.32", "log", "rustls 0.22.4", "rustls-native-certs 0.7.3", "rustls-pki-types", "tokio", "tokio-rustls 0.25.0", - "webpki-roots", + "webpki-roots 0.26.11", ] [[package]] name = "hyper-rustls" -version = "0.27.3" +version = "0.27.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" +checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" dependencies = [ - "futures-util", - "http 1.1.0", - "hyper 1.5.0", + "http 1.3.1", + "hyper 1.7.0", "hyper-util", - "rustls 0.23.18", + "rustls 0.23.34", "rustls-pki-types", "tokio", - "tokio-rustls 0.26.0", + "tokio-rustls 0.26.4", "tower-service", - "webpki-roots", + "webpki-roots 1.0.4", ] [[package]] @@ -4144,7 +4327,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0" dependencies = [ - "hyper 1.5.0", + "hyper 1.7.0", "hyper-util", "pin-project-lite", "tokio", @@ -4158,7 +4341,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" dependencies = [ "bytes", - "hyper 0.14.31", + "hyper 0.14.32", "native-tls", "tokio", "tokio-native-tls", @@ -4172,7 +4355,7 @@ checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ "bytes", "http-body-util", - "hyper 1.5.0", + "hyper 1.7.0", "hyper-util", "native-tls", "tokio", @@ -4182,35 +4365,43 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.10" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" +checksum = "3c6995591a8f1380fcb4ba966a252a4b29188d51d2b89e3a252f5305be65aea8" dependencies = [ + "base64 0.22.1", "bytes", "futures-channel", + "futures-core", "futures-util", - "http 1.1.0", + "http 1.3.1", "http-body 1.0.1", - "hyper 1.5.0", + "hyper 1.7.0", + "ipnet", + "libc", + "percent-encoding", "pin-project-lite", - "socket2 0.5.7", + "socket2 0.6.1", + "system-configuration 0.6.1", "tokio", "tower-service", "tracing", + "windows-registry", ] [[package]] name = "iana-time-zone" -version = "0.1.61" +version = "0.1.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" +checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", + "log", "wasm-bindgen", - "windows-core 0.52.0", + "windows-core 0.62.2", ] [[package]] @@ -4224,21 +4415,22 @@ dependencies = [ [[package]] name = "icu_collections" -version = "1.5.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" dependencies = [ "displaydoc", - "yoke", + "potential_utf", + "yoke 0.8.1", "zerofrom", "zerovec", ] [[package]] -name = "icu_locid" -version = "1.5.0" +name = "icu_locale_core" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" dependencies = [ "displaydoc", "litemap", @@ -4247,99 +4439,61 @@ dependencies = [ "zerovec", ] -[[package]] -name = "icu_locid_transform" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" -dependencies = [ - "displaydoc", - "icu_locid", - "icu_locid_transform_data", - "icu_provider", - "tinystr", - "zerovec", -] - -[[package]] -name = "icu_locid_transform_data" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" - [[package]] name = "icu_normalizer" -version = "1.5.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" dependencies = [ - "displaydoc", "icu_collections", "icu_normalizer_data", "icu_properties", "icu_provider", "smallvec", - "utf16_iter", - "utf8_iter", - "write16", "zerovec", ] [[package]] name = "icu_normalizer_data" -version = "1.5.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" +checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" [[package]] name = "icu_properties" -version = "1.5.1" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +checksum = "e93fcd3157766c0c8da2f8cff6ce651a31f0810eaa1c51ec363ef790bbb5fb99" dependencies = [ - "displaydoc", "icu_collections", - "icu_locid_transform", + "icu_locale_core", "icu_properties_data", "icu_provider", - "tinystr", + "zerotrie", "zerovec", ] [[package]] name = "icu_properties_data" -version = "1.5.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" +checksum = "02845b3647bb045f1100ecd6480ff52f34c35f82d9880e029d329c21d1054899" [[package]] name = "icu_provider" -version = "1.5.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" dependencies = [ "displaydoc", - "icu_locid", - "icu_provider_macros", - "stable_deref_trait", - "tinystr", + "icu_locale_core", "writeable", - "yoke", + "yoke 0.8.1", "zerofrom", + "zerotrie", "zerovec", ] -[[package]] -name = "icu_provider_macros" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.108", -] - [[package]] name = "id-arena" version = "2.2.1" @@ -4365,9 +4519,9 @@ dependencies = [ [[package]] name = "idna_adapter" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" dependencies = [ "icu_normalizer", "icu_properties", @@ -4375,9 +4529,9 @@ dependencies = [ [[package]] name = "ignore" -version = "0.4.23" +version = "0.4.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d89fd380afde86567dfba715db065673989d6253f42b88179abd3eae47bda4b" +checksum = "d3d782a365a015e0f5c04902246139249abf769125006fbe7649e2ee88169b4a" dependencies = [ "crossbeam-deque", "globset", @@ -4447,14 +4601,14 @@ dependencies = [ [[package]] name = "indicatif" -version = "0.17.9" +version = "0.17.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbf675b85ed934d3c67b5c5469701eec7db22689d0a2139d856e0925fa28b281" +checksum = "183b3088984b400f4cfac3620d5e076c84da5364016b4f49473de574b2586235" dependencies = [ "console", "number_prefix", "portable-atomic", - "unicode-width 0.2.0", + "unicode-width 0.2.2", "web-time", ] @@ -4486,9 +4640,9 @@ dependencies = [ [[package]] name = "inout" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" dependencies = [ "block-padding", "generic-array", @@ -4505,19 +4659,19 @@ dependencies = [ [[package]] name = "io-extras" -version = "0.18.3" +version = "0.18.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d45fd7584f9b67ac37bc041212d06bfac0700b36456b05890d36a3b626260eb" +checksum = "2285ddfe3054097ef4b2fe909ef8c3bcd1ea52a8f0d274416caebeef39f04a65" dependencies = [ "io-lifetimes", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "io-lifetimes" -version = "2.0.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a611371471e98973dbcab4e0ec66c31a10bc356eeb4d54a0e05eac8158fe38c" +checksum = "06432fb54d3be7964ecd3649233cddf80db2832f47fec34c01f65b3d9d774983" [[package]] name = "ip_network" @@ -4543,26 +4697,36 @@ checksum = "8e537132deb99c0eb4b752f0346b6a836200eaaa3516dd7e5514b63930a09e5d" [[package]] name = "ipnet" -version = "2.10.1" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" + +[[package]] +name = "iri-string" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" +checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2" +dependencies = [ + "memchr", + "serde", +] [[package]] name = "is-terminal" -version = "0.4.13" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b" +checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46" dependencies = [ - "hermit-abi 0.4.0", + "hermit-abi 0.5.2", "libc", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] name = "is_terminal_polyfill" -version = "1.70.1" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" [[package]] name = "itertools" @@ -4582,15 +4746,6 @@ dependencies = [ "either", ] -[[package]] -name = "itertools" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" -dependencies = [ - "either", -] - [[package]] name = "itertools" version = "0.14.0" @@ -4602,9 +4757,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "ittapi" @@ -4669,19 +4824,21 @@ dependencies = [ [[package]] name = "jobserver" -version = "0.1.32" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" dependencies = [ + "getrandom 0.3.4", "libc", ] [[package]] name = "js-sys" -version = "0.3.72" +version = "0.3.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" +checksum = "b011eec8cc36da2aab2d5cff675ec18454fad408585853910a202391cf9f8e65" dependencies = [ + "once_cell", "wasm-bindgen", ] @@ -4736,9 +4893,9 @@ dependencies = [ [[package]] name = "keyring" -version = "3.6.2" +version = "3.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1961983669d57bdfe6c0f3ef8e4c229b5ef751afcc7d87e4271d2f71f6ccfa8b" +checksum = "eebcc3aff044e5944a8fbaf69eb277d11986064cba30c468730e8b9909fb551c" dependencies = [ "byteorder", "dbus-secret-service", @@ -4746,9 +4903,10 @@ dependencies = [ "log", "secret-service", "security-framework 2.11.1", - "security-framework 3.2.0", - "windows-sys 0.59.0", + "security-framework 3.5.1", + "windows-sys 0.60.2", "zbus", + "zeroize", ] [[package]] @@ -4781,6 +4939,15 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "kv-log-macro" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" +dependencies = [ + "log", +] + [[package]] name = "lazy_static" version = "0.2.11" @@ -4813,15 +4980,15 @@ checksum = "db13adb97ab515a3691f56e4dbab09283d0b86cb45abd991d8634a9d6f501760" [[package]] name = "libc" -version = "0.2.172" +version = "0.2.177" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" +checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" [[package]] name = "libdbus-sys" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06085512b750d640299b79be4bad3d2fa90a9c00b1fd9e1b46364f66f0485c72" +checksum = "5cbe856efeb50e4681f010e9aaa2bf0a644e10139e54cde10fc83a307c23bd9f" dependencies = [ "pkg-config", ] @@ -4848,25 +5015,25 @@ dependencies = [ [[package]] name = "libloading" -version = "0.8.5" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" dependencies = [ "cfg-if", - "windows-targets 0.52.6", + "windows-link 0.2.1", ] [[package]] name = "libm" -version = "0.2.11" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" +checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" [[package]] name = "libredox" -version = "0.1.3" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb" dependencies = [ "bitflags 2.10.0", "libc", @@ -4887,7 +5054,7 @@ dependencies = [ "fallible-iterator 0.3.0", "futures", "http 0.2.12", - "hyper 0.14.31", + "hyper 0.14.32", "hyper-rustls 0.25.0", "libsql-hrana", "libsql-sqlite3-parser", @@ -4924,9 +5091,9 @@ dependencies = [ "indexmap 2.12.0", "log", "memchr", - "phf", + "phf 0.11.3", "phf_codegen", - "phf_shared", + "phf_shared 0.11.3", "uncased", ] @@ -4947,7 +5114,7 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cc0bda45ed5b3a2904262c1bb91e526127aa70e7ef3758aba2ef93cf896b9b58" dependencies = [ - "clap 4.5.20", + "clap 4.5.51", "escape8259", "termcolor", "threadpool", @@ -4965,23 +5132,22 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.4.14" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "linux-raw-sys" -version = "0.9.4" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" +checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" [[package]] name = "liquid" -version = "0.26.9" +version = "0.26.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cdcc72b82748f47c2933c172313f5a9aea5b2c4eb3fa4c66b4ea55bb60bb4b1" +checksum = "2a494c3f9dad3cb7ed16f1c51812cbe4b29493d6c2e5cd1e2b87477263d9534d" dependencies = [ - "doc-comment", "liquid-core", "liquid-derive", "liquid-lib", @@ -4990,15 +5156,14 @@ dependencies = [ [[package]] name = "liquid-core" -version = "0.26.9" +version = "0.26.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2752e978ffc53670f3f2e8b3ef09f348d6f7b5474a3be3f8a5befe5382e4effb" +checksum = "fc623edee8a618b4543e8e8505584f4847a4e51b805db1af6d9af0a3395d0d57" dependencies = [ "anymap2", - "itertools 0.13.0", + "itertools 0.14.0", "kstring", "liquid-derive", - "num-traits", "pest", "pest_derive", "regex", @@ -5008,9 +5173,9 @@ dependencies = [ [[package]] name = "liquid-derive" -version = "0.26.8" +version = "0.26.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b51f1d220e3fa869e24cfd75915efe3164bd09bb11b3165db3f37f57bf673e3" +checksum = "de66c928222984aea59fcaed8ba627f388aaac3c1f57dcb05cc25495ef8faefe" dependencies = [ "proc-macro2", "quote", @@ -5019,13 +5184,12 @@ dependencies = [ [[package]] name = "liquid-lib" -version = "0.26.9" +version = "0.26.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59b1a298d3d2287ee5b1e43840d885b8fdfc37d3f4e90d82aacfd04d021618da" +checksum = "9befeedd61f5995bc128c571db65300aeb50d62e4f0542c88282dbcb5f72372a" dependencies = [ - "itertools 0.13.0", + "itertools 0.14.0", "liquid-core", - "once_cell", "percent-encoding", "regex", "time", @@ -5034,40 +5198,48 @@ dependencies = [ [[package]] name = "litemap" -version = "0.7.3" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" + +[[package]] +name = "litrs" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" +checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" [[package]] name = "lock_api" -version = "0.4.12" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" dependencies = [ - "autocfg", "scopeguard", ] [[package]] name = "log" -version = "0.4.27" +version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" +checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" +dependencies = [ + "value-bag", +] [[package]] name = "logos" -version = "0.14.2" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c6b6e02facda28ca5fb8dbe4b152496ba3b1bd5a4b40bb2b1b2d8ad74e0f39b" +checksum = "7251356ef8cb7aec833ddf598c6cb24d17b689d20b993f9d11a3d764e34e6458" dependencies = [ "logos-derive", ] [[package]] name = "logos-codegen" -version = "0.14.2" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b32eb6b5f26efacd015b000bfc562186472cd9b34bdba3f6b264e2a052676d10" +checksum = "59f80069600c0d66734f5ff52cc42f2dabd6b29d205f333d61fd7832e9e9963f" dependencies = [ "beef", "fnv", @@ -5080,49 +5252,42 @@ dependencies = [ [[package]] name = "logos-derive" -version = "0.14.2" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e5d0c5463c911ef55624739fc353238b4e310f0144be1f875dc42fec6bfd5ec" +checksum = "24fb722b06a9dc12adb0963ed585f19fc61dc5413e6a9be9422ef92c091e731d" dependencies = [ "logos-codegen", ] -[[package]] -name = "loom" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "419e0dc8046cb947daa77eb95ae174acfbddb7673b4151f56d1eed8e93fbfaca" -dependencies = [ - "cfg-if", - "generator", - "scoped-tls", - "tracing", - "tracing-subscriber", -] - [[package]] name = "lru" version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" dependencies = [ - "hashbrown 0.15.2", + "hashbrown 0.15.5", ] +[[package]] +name = "lru-slab" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" + [[package]] name = "mach2" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709" +checksum = "d640282b302c0bb0a2a8e0233ead9035e3bed871f0b7e81fe4a1ec829765db44" dependencies = [ "libc", ] [[package]] name = "macro_rules_attribute" -version = "0.2.0" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a82271f7bc033d84bbca59a3ce3e4159938cb08a9c3aebbe54d215131518a13" +checksum = "65049d7923698040cd0b1ddcced9b0eb14dd22c5f86ae59c3740eab64a676520" dependencies = [ "macro_rules_attribute-proc_macro", "paste", @@ -5130,9 +5295,9 @@ dependencies = [ [[package]] name = "macro_rules_attribute-proc_macro" -version = "0.2.0" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8dd856d451cc0da70e2ef2ce95a18e39a93b7558bedf10201ad28503f918568" +checksum = "670fdfda89751bc4a84ac13eaa63e205cf0fd22b4c9a5fbfa085b63c1f1d3a30" [[package]] name = "malloc_buf" @@ -5176,24 +5341,24 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.4" +version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" [[package]] name = "memfd" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2cffa4ad52c6f791f4f8b15f0c05f9824b2ced1160e88cc393d64fff9a8ac64" +checksum = "ad38eb12aea514a0466ea40a80fd8cc83637065948eb4a426e4aa46261175227" dependencies = [ - "rustix 0.38.40", + "rustix 1.1.2", ] [[package]] name = "memmap2" -version = "0.9.5" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd3f7eed9d3848f8b98834af67102b720745c4ec028fcd0aa0239277e7de374f" +checksum = "744133e4a0e0a658e1374cf3bf8e415c4052a15a111acd372764c55b4177d490" dependencies = [ "libc", "stable_deref_trait", @@ -5240,21 +5405,20 @@ dependencies = [ [[package]] name = "miette" -version = "7.2.0" +version = "7.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4edc8853320c2a0dab800fbda86253c8938f6ea88510dc92c5f1ed20e794afc1" +checksum = "5f98efec8807c63c752b5bd61f862c165c115b0a35685bdcfd9238c7aeb592b7" dependencies = [ "cfg-if", "miette-derive", - "thiserror 1.0.69", "unicode-width 0.1.14", ] [[package]] name = "miette-derive" -version = "7.2.0" +version = "7.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf09caffaac8068c346b6df2a7fc27a177fd20b39421a39ce0a211bde679a6c" +checksum = "db5b29714e950dbb20d5e6f74f9dcec4edbcc1067bb7f8ed198c097b8c1a818b" dependencies = [ "proc-macro2", "quote", @@ -5275,59 +5439,60 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.8.5" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e3e04debbb59698c15bacbb6d93584a8c0ca9cc3213cb423d31f760d8843ce5" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ "adler2", + "simd-adler32", ] [[package]] name = "mio" -version = "1.0.4" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" +checksum = "69d83b0086dc8ecf3ce9ae2874b2d1290252e2a30720bea58a5c6639b0092873" dependencies = [ "libc", "log", - "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.59.0", + "wasi 0.11.1+wasi-snapshot-preview1", + "windows-sys 0.61.2", ] [[package]] name = "moka" -version = "0.12.10" +version = "0.12.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9321642ca94a4282428e6ea4af8cc2ca4eac48ac7a6a4ea8f33f76d0ce70926" +checksum = "8261cd88c312e0004c1d51baad2980c66528dfdb2bee62003e643a4d8f86b077" dependencies = [ "crossbeam-channel", "crossbeam-epoch", "crossbeam-utils", - "loom", + "equivalent", "parking_lot", "portable-atomic", "rustc_version", "smallvec", "tagptr", - "thiserror 1.0.69", "uuid", ] [[package]] name = "monostate" -version = "0.1.13" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d208407d7552cd041d8cdb69a1bc3303e029c598738177a3d87082004dc0e1e" +checksum = "3341a273f6c9d5bef1908f17b7267bbab0e95c9bf69a0d4dcf8e9e1b2c76ef67" dependencies = [ "monostate-impl", "serde", + "serde_core", ] [[package]] name = "monostate-impl" -version = "0.1.13" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7ce64b975ed4f123575d11afd9491f2e37bbd5813fbfbc0f09ae1fbddea74e0" +checksum = "e4db6d5580af57bf992f59068d4ea26fd518574ff48d7639b255a36f9de6e7e9" dependencies = [ "proc-macro2", "quote", @@ -5336,9 +5501,9 @@ dependencies = [ [[package]] name = "multimap" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "defc4c55412d89136f966bbb339008b474350e5e6e78d2714439c386b3137a03" +checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084" [[package]] name = "mysql_async" @@ -5362,7 +5527,7 @@ dependencies = [ "rand 0.8.5", "serde", "serde_json", - "socket2 0.5.7", + "socket2 0.5.10", "thiserror 2.0.17", "tokio", "tokio-native-tls", @@ -5404,9 +5569,9 @@ dependencies = [ [[package]] name = "native-tls" -version = "0.2.12" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" +checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" dependencies = [ "libc", "log", @@ -5488,11 +5653,11 @@ checksum = "f5438dd2b2ff4c6df6e1ce22d825ed2fa93ee2922235cc45186991717f0a892d" [[package]] name = "normpath" -version = "1.3.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8911957c4b1549ac0dc74e30db9c8b0e66ddcd6d7acc33098f4c63a64a6d7ed" +checksum = "bf23ab2b905654b4cb177e30b629937b3868311d4e1cba859f899c041046e69b" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -5525,7 +5690,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -5611,28 +5776,29 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" dependencies = [ - "hermit-abi 0.3.9", + "hermit-abi 0.5.2", "libc", ] [[package]] name = "num_enum" -version = "0.7.3" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" +checksum = "b1207a7e20ad57b847bbddc6776b968420d38292bbfe2089accff5e19e82454c" dependencies = [ "num_enum_derive", + "rustversion", ] [[package]] name = "num_enum_derive" -version = "0.7.3" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" +checksum = "ff32365de1b6743cb203b710788263c44a03de03802daf96092f2da4fe6ba4d7" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -5663,7 +5829,7 @@ checksum = "c38841cdd844847e3e7c8d29cef9dcfed8877f8f56f9071f77843ecf3baf937f" dependencies = [ "base64 0.13.1", "chrono", - "getrandom 0.2.15", + "getrandom 0.2.16", "http 0.2.12", "rand 0.8.5", "serde", @@ -5684,6 +5850,21 @@ dependencies = [ "objc_exception", ] +[[package]] +name = "objc2" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c2599ce0ec54857b29ce62166b0ed9b4f6f1a70ccc9a71165b6154caca8c05" +dependencies = [ + "objc2-encode", +] + +[[package]] +name = "objc2-encode" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" + [[package]] name = "objc_exception" version = "0.1.2" @@ -5693,15 +5874,6 @@ dependencies = [ "cc", ] -[[package]] -name = "object" -version = "0.36.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" -dependencies = [ - "memchr", -] - [[package]] name = "object" version = "0.37.3" @@ -5709,7 +5881,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" dependencies = [ "crc32fast", - "hashbrown 0.15.2", + "hashbrown 0.15.5", "indexmap 2.12.0", "memchr", ] @@ -5723,14 +5895,14 @@ dependencies = [ "bytes", "chrono", "futures-util", - "http 1.1.0", + "http 1.3.1", "http-auth", "jwt 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.5.0", "oci-spec", "olpc-cjson", "regex", - "reqwest 0.12.9", + "reqwest 0.12.24", "serde", "serde_json", "sha2", @@ -5748,13 +5920,13 @@ dependencies = [ "bytes", "chrono", "futures-util", - "http 1.1.0", + "http 1.3.1", "http-auth", "jwt 0.16.0 (git+https://github.com/vdice/rust-jwt?rev=c5b596d28a39dd428350b445d5c5829ba6352f02)", "lazy_static 1.5.0", "olpc-cjson", "regex", - "reqwest 0.12.9", + "reqwest 0.12.24", "serde", "serde_json", "sha2", @@ -5772,13 +5944,13 @@ dependencies = [ "bytes", "chrono", "futures-util", - "http 1.1.0", + "http 1.3.1", "http-auth", "jwt 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.5.0", "olpc-cjson", "regex", - "reqwest 0.12.9", + "reqwest 0.12.24", "serde", "serde_json", "sha2", @@ -5838,6 +6010,12 @@ version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +[[package]] +name = "once_cell_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" + [[package]] name = "onig" version = "6.5.1" @@ -5888,9 +6066,9 @@ dependencies = [ [[package]] name = "openssl-probe" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" +checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" [[package]] name = "openssl-sys" @@ -5938,9 +6116,9 @@ checksum = "a8863faf2910030d139fb48715ad5ff2f35029fc5f244f6d5f689ddcf4d26253" dependencies = [ "async-trait", "bytes", - "http 1.1.0", + "http 1.3.1", "opentelemetry", - "reqwest 0.12.9", + "reqwest 0.12.24", "tracing", ] @@ -5952,17 +6130,16 @@ checksum = "5bef114c6d41bea83d6dc60eb41720eedd0261a67af57b66dd2b84ac46c01d91" dependencies = [ "async-trait", "futures-core", - "http 1.1.0", + "http 1.3.1", "opentelemetry", "opentelemetry-http", "opentelemetry-proto", "opentelemetry_sdk", - "prost 0.13.3", - "reqwest 0.12.9", + "prost 0.13.5", + "reqwest 0.12.24", "thiserror 2.0.17", "tokio", "tonic", - "tracing", ] [[package]] @@ -5973,7 +6150,7 @@ checksum = "56f8870d3024727e99212eb3bb1762ec16e255e3e6f58eeb3dc8db1aa226746d" dependencies = [ "opentelemetry", "opentelemetry_sdk", - "prost 0.13.3", + "prost 0.13.5", "tonic", ] @@ -5983,6 +6160,7 @@ version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "84dfad6042089c7fc1f6118b7040dc2eb4ab520abbf410b79dc481032af39570" dependencies = [ + "async-std", "async-trait", "futures-channel", "futures-executor", @@ -6041,9 +6219,9 @@ checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" [[package]] name = "outref" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4030760ffd992bef45b0ae3f10ce1aba99e33464c90d14dd7c039884963ddc7a" +checksum = "1a80800c0488c3a21695ea981a54918fbb37abf04f4d0720c453632255e2ff0e" [[package]] name = "p256" @@ -6065,9 +6243,9 @@ checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" [[package]] name = "parking_lot" -version = "0.12.3" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" dependencies = [ "lock_api", "parking_lot_core", @@ -6075,15 +6253,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.10" +version = "0.9.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-targets 0.52.6", + "windows-link 0.2.1", ] [[package]] @@ -6112,9 +6290,9 @@ dependencies = [ [[package]] name = "pathdiff" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d61c5ce1153ab5b689d0c074c4e7fc613e942dfb7dd9eea5ab202d2ad91fe361" +checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" [[package]] name = "pbjson" @@ -6155,12 +6333,12 @@ dependencies = [ [[package]] name = "pem" -version = "3.0.4" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e459365e590736a54c3fa561947c84837534b8e9af6fc5bf781307e82658fae" +checksum = "1d30c53c26bc5b31a98cd02d20f25a7c8567146caf63ed593a9d87b2775291be" dependencies = [ "base64 0.22.1", - "serde", + "serde_core", ] [[package]] @@ -6180,20 +6358,19 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "pest" -version = "2.7.14" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879952a81a83930934cbf1786752d6dedc3b1f29e8f8fb2ad1d0a36f377cf442" +checksum = "989e7521a040efde50c3ab6bbadafbe15ab6dc042686926be59ac35d74607df4" dependencies = [ "memchr", - "thiserror 1.0.69", "ucd-trie", ] [[package]] name = "pest_derive" -version = "2.7.14" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d214365f632b123a47fd913301e14c946c61d1c183ee245fa76eb752e59a02dd" +checksum = "187da9a3030dbafabbbfb20cb323b976dc7b7ce91fcd84f2f74d6e31d378e2de" dependencies = [ "pest", "pest_generator", @@ -6201,9 +6378,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.14" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb55586734301717aea2ac313f50b2eb8f60d2fc3dc01d190eefa2e625f60c4e" +checksum = "49b401d98f5757ebe97a26085998d6c0eecec4995cad6ab7fc30ffdf4b052843" dependencies = [ "pest", "pest_meta", @@ -6214,11 +6391,10 @@ dependencies = [ [[package]] name = "pest_meta" -version = "2.7.14" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b75da2a70cf4d9cb76833c990ac9cd3923c9a8905a8929789ce347c84564d03d" +checksum = "72f27a2cfee9f9039c4d86faa5af122a0ac3851441a34865b8a043b46be0065a" dependencies = [ - "once_cell", "pest", "sha2", ] @@ -6235,57 +6411,76 @@ dependencies = [ [[package]] name = "phf" -version = "0.11.2" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" +dependencies = [ + "phf_shared 0.11.3", +] + +[[package]] +name = "phf" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +checksum = "c1562dc717473dbaa4c1f85a36410e03c047b2e7df7f45ee938fbef64ae7fadf" dependencies = [ - "phf_shared", + "phf_shared 0.13.1", + "serde", ] [[package]] name = "phf_codegen" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a" +checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a" dependencies = [ "phf_generator", - "phf_shared", + "phf_shared 0.11.3", ] [[package]] name = "phf_generator" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" +checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" dependencies = [ - "phf_shared", + "phf_shared 0.11.3", "rand 0.8.5", ] [[package]] name = "phf_shared" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" dependencies = [ "siphasher", "uncased", ] +[[package]] +name = "phf_shared" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e57fef6bc5981e38c2ce2d63bfa546861309f875b8a75f092d1d54ae2d64f266" +dependencies = [ + "siphasher", +] + [[package]] name = "pin-project" -version = "1.1.7" +version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be57f64e946e500c8ee36ef6331845d40a93055567ec57e8fae13efd33759b95" +checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.7" +version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" +checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", @@ -6311,7 +6506,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" dependencies = [ "atomic-waker", - "fastrand 2.2.0", + "fastrand 2.3.0", "futures-io", ] @@ -6327,23 +6522,22 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" [[package]] name = "polling" -version = "3.7.4" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a604568c3202727d1507653cb121dbd627a58684eb09a820fd746bee38b4442f" +checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" dependencies = [ "cfg-if", "concurrent-queue", - "hermit-abi 0.4.0", + "hermit-abi 0.5.2", "pin-project-lite", - "rustix 0.38.40", - "tracing", - "windows-sys 0.59.0", + "rustix 1.1.2", + "windows-sys 0.61.2", ] [[package]] @@ -6363,9 +6557,9 @@ dependencies = [ [[package]] name = "postcard" -version = "1.0.10" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f7f0a8d620d71c457dd1d47df76bb18960378da56af4527aaa10f515eee732e" +checksum = "6764c3b5dd454e283a30e6dfe78e9b31096d9e32036b5d1eaac7a6119ccb9a24" dependencies = [ "cobs", "embedded-io 0.4.0", @@ -6375,11 +6569,10 @@ dependencies = [ [[package]] name = "postgres-native-tls" -version = "0.5.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d442770e2b1e244bb5eb03b31c79b65bb2568f413b899eaba850fa945a65954" +checksum = "ac73153d92e4bde922bd6f1dfba7f1ab8132266c031153b55e20a1521cd36d49" dependencies = [ - "futures", "native-tls", "tokio", "tokio-native-tls", @@ -6388,9 +6581,9 @@ dependencies = [ [[package]] name = "postgres-protocol" -version = "0.6.7" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acda0ebdebc28befa84bee35e651e4c5f09073d668c7aed4cf7e23c3cda84b23" +checksum = "fbef655056b916eb868048276cfd5d6a7dea4f81560dfd047f97c8c6fe3fcfd4" dependencies = [ "base64 0.22.1", "byteorder", @@ -6399,22 +6592,22 @@ dependencies = [ "hmac", "md-5", "memchr", - "rand 0.8.5", + "rand 0.9.2", "sha2", "stringprep", ] [[package]] name = "postgres-types" -version = "0.2.8" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f66ea23a2d0e5734297357705193335e0a957696f34bed2f2faefacb2fec336f" +checksum = "ef4605b7c057056dd35baeb6ac0c0338e4975b1f2bef0f65da953285eb007095" dependencies = [ "bytes", "chrono", "fallible-iterator 0.2.0", "postgres-protocol", - "serde", + "serde_core", "serde_json", "uuid", ] @@ -6429,6 +6622,15 @@ dependencies = [ "postgres-types", ] +[[package]] +name = "potential_utf" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" +dependencies = [ + "zerovec", +] + [[package]] name = "powerfmt" version = "0.2.0" @@ -6437,9 +6639,9 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" -version = "0.2.20" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" dependencies = [ "zerocopy", ] @@ -6456,9 +6658,9 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.25" +version = "0.2.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", "syn 2.0.108", @@ -6475,11 +6677,11 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "3.2.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" +checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" dependencies = [ - "toml_edit", + "toml_edit 0.23.7", ] [[package]] @@ -6584,12 +6786,12 @@ dependencies = [ [[package]] name = "prost" -version = "0.13.3" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b0487d90e047de87f984913713b85c601c05609aad5b0df4b4573fbf69aa13f" +checksum = "2796faa41db3ec313a31f7624d9286acf277b52de526150b7e69f3debf891ee5" dependencies = [ "bytes", - "prost-derive 0.13.3", + "prost-derive 0.13.5", ] [[package]] @@ -6628,12 +6830,12 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.13.3" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9552f850d5f0964a4e4d0bf306459ac29323ddfbae05e35a7c0d35cb0803cc5" +checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d" dependencies = [ "anyhow", - "itertools 0.13.0", + "itertools 0.14.0", "proc-macro2", "quote", "syn 2.0.108", @@ -6725,9 +6927,9 @@ dependencies = [ [[package]] name = "pulley-interpreter" -version = "37.0.1" +version = "37.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4338089093bf5f2f50e77602a4b8bb938e16bead1419ed9cd6484c9ef7050b10" +checksum = "6cff3cc2c3a933419d4989b9dcdee724ebc9ee4cdc1f175dbaeef71d3b963336" dependencies = [ "cranelift-bitset", "log", @@ -6737,9 +6939,9 @@ dependencies = [ [[package]] name = "pulley-macros" -version = "37.0.1" +version = "37.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23e93c268176831e893721022bb923f41b892b3c9e41875f276025fddb1a0ea8" +checksum = "a56fca4a86a359a71f35f188de13bdfa9dc5b56a36d236fa98cb0db601ef4d21" dependencies = [ "proc-macro2", "quote", @@ -6760,9 +6962,9 @@ dependencies = [ [[package]] name = "pulp" -version = "0.21.4" +version = "0.21.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95fb7a99b37aaef4c7dd2fd15a819eb8010bfc7a2c2155230d51f497316cad6d" +checksum = "96b86df24f0a7ddd5e4b95c94fc9ed8a98f1ca94d3b01bdce2824097e7835907" dependencies = [ "bytemuck", "cfg-if", @@ -6774,51 +6976,57 @@ dependencies = [ [[package]] name = "quinn" -version = "0.11.5" +version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c7c5fdde3cdae7203427dc4f0a68fe0ed09833edc525a03456b153b79828684" +checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" dependencies = [ "bytes", + "cfg_aliases", "pin-project-lite", "quinn-proto", "quinn-udp", "rustc-hash", - "rustls 0.23.18", - "socket2 0.5.7", - "thiserror 1.0.69", + "rustls 0.23.34", + "socket2 0.6.1", + "thiserror 2.0.17", "tokio", "tracing", + "web-time", ] [[package]] name = "quinn-proto" -version = "0.11.8" +version = "0.11.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fadfaed2cd7f389d0161bb73eeb07b7b78f8691047a6f3e73caaeae55310a4a6" +checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" dependencies = [ "bytes", - "rand 0.8.5", + "getrandom 0.3.4", + "lru-slab", + "rand 0.9.2", "ring", "rustc-hash", - "rustls 0.23.18", + "rustls 0.23.34", + "rustls-pki-types", "slab", - "thiserror 1.0.69", + "thiserror 2.0.17", "tinyvec", "tracing", + "web-time", ] [[package]] name = "quinn-udp" -version = "0.5.7" +version = "0.5.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d5a626c6807713b15cac82a6acaccd6043c9a5408c24baae07611fec3f243da" +checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2 0.5.7", + "socket2 0.6.1", "tracing", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -6832,9 +7040,9 @@ dependencies = [ [[package]] name = "r-efi" -version = "5.2.0" +version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" [[package]] name = "radium" @@ -6878,9 +7086,9 @@ dependencies = [ [[package]] name = "rand" -version = "0.9.1" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" dependencies = [ "rand_chacha 0.9.0", "rand_core 0.9.3", @@ -6931,7 +7139,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.15", + "getrandom 0.2.16", ] [[package]] @@ -6940,7 +7148,7 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" dependencies = [ - "getrandom 0.3.2", + "getrandom 0.3.4", ] [[package]] @@ -6950,7 +7158,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8615d50dcf34fa31f7ab52692afec947c4dd0ab803cc87cb3b0b4570ff7463" dependencies = [ "num-traits", - "rand 0.9.1", + "rand 0.9.2", ] [[package]] @@ -6982,18 +7190,18 @@ dependencies = [ [[package]] name = "raw-cpuid" -version = "11.5.0" +version = "11.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6df7ab838ed27997ba19a4664507e6f82b41fe6e20be42929332156e5e85146" +checksum = "498cd0dc59d73224351ee52a95fee0f1a617a2eae0e7d9d720cc622c73a54186" dependencies = [ "bitflags 2.10.0", ] [[package]] name = "rayon" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" dependencies = [ "either", "rayon-core", @@ -7001,20 +7209,20 @@ dependencies = [ [[package]] name = "rayon-cond" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "059f538b55efd2309c9794130bc149c6a553db90e9d99c2030785c82f0bd7df9" +checksum = "2964d0cf57a3e7a06e8183d14a8b527195c706b7983549cd5462d5aa3747438f" dependencies = [ "either", - "itertools 0.11.0", + "itertools 0.14.0", "rayon", ] [[package]] name = "rayon-core" -version = "1.12.1" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" dependencies = [ "crossbeam-deque", "crossbeam-utils", @@ -7028,9 +7236,9 @@ checksum = "03251193000f4bd3b042892be858ee50e8b3719f2b08e5833ac4353724632430" [[package]] name = "redis" -version = "0.32.5" +version = "0.32.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cd3650deebc68526b304898b192fa4102a4ef0b9ada24da096559cb60e0eef8" +checksum = "014cc767fefab6a3e798ca45112bccad9c6e0e218fbd49720042716c73cfef44" dependencies = [ "arc-swap", "backon", @@ -7046,7 +7254,7 @@ dependencies = [ "pin-project-lite", "ryu", "sha1_smol", - "socket2 0.6.0", + "socket2 0.6.1", "tokio", "tokio-native-tls", "tokio-util", @@ -7055,9 +7263,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.7" +version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ "bitflags 2.10.0", ] @@ -7068,31 +7276,51 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ - "getrandom 0.2.15", + "getrandom 0.2.16", "libredox", "thiserror 1.0.69", ] [[package]] name = "redox_users" -version = "0.5.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b" +checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" dependencies = [ - "getrandom 0.2.15", + "getrandom 0.2.16", "libredox", "thiserror 2.0.17", ] +[[package]] +name = "ref-cast" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + [[package]] name = "regalloc2" -version = "0.13.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68e18e1ef763167dc6718c28a5585e62f907590a21028b8e87be1318f19ef1cb" +checksum = "efd8138ce7c3d7c13be4f61893154b5d711bd798d2d7be3ecb8dcc7e7a06ca98" dependencies = [ "allocator-api2", "bumpalo", - "hashbrown 0.15.2", + "hashbrown 0.15.5", "log", "rustc-hash", "smallvec", @@ -7100,9 +7328,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.11.1" +version = "1.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" dependencies = [ "aho-corasick", "memchr", @@ -7112,9 +7340,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.9" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" dependencies = [ "aho-corasick", "memchr", @@ -7123,15 +7351,15 @@ dependencies = [ [[package]] name = "regex-lite" -version = "0.1.6" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53a49587ad06b26609c52e423de037e7f57f20d53535d66e08c695f347df952a" +checksum = "8d942b98df5e658f56f20d592c7f868833fe38115e65c33003d8cd224b0155da" [[package]] name = "regex-syntax" -version = "0.8.5" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" [[package]] name = "rend" @@ -7153,10 +7381,10 @@ dependencies = [ "encoding_rs", "futures-core", "futures-util", - "h2 0.3.26", + "h2 0.3.27", "http 0.2.12", "http-body 0.4.6", - "hyper 0.14.31", + "hyper 0.14.32", "hyper-tls 0.5.0", "ipnet", "js-sys", @@ -7186,9 +7414,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.12.9" +version = "0.12.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a77c62af46e79de0a562e1a9849205ffcb7fc1238876e9bd743357570e04046f" +checksum = "9d0946410b9f7b082a427e4ef5c8ff541a88b357bc6c637c40db3a68ac70a36f" dependencies = [ "async-compression", "base64 0.22.1", @@ -7197,44 +7425,40 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "h2 0.4.6", - "http 1.1.0", + "h2 0.4.12", + "http 1.3.1", "http-body 1.0.1", "http-body-util", - "hyper 1.5.0", - "hyper-rustls 0.27.3", + "hyper 1.7.0", + "hyper-rustls 0.27.7", "hyper-tls 0.6.0", "hyper-util", - "ipnet", "js-sys", "log", "mime", "native-tls", - "once_cell", "percent-encoding", "pin-project-lite", "quinn", - "rustls 0.23.18", - "rustls-pemfile 2.2.0", + "rustls 0.23.34", "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", - "sync_wrapper 1.0.1", - "system-configuration 0.6.1", + "sync_wrapper 1.0.2", "tokio", "tokio-native-tls", - "tokio-rustls 0.26.0", - "tokio-socks", + "tokio-rustls 0.26.4", "tokio-util", + "tower 0.5.2", + "tower-http", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", "wasm-streams", "web-sys", - "webpki-roots", - "windows-registry", + "webpki-roots 1.0.4", ] [[package]] @@ -7255,7 +7479,7 @@ checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", "cfg-if", - "getrandom 0.2.15", + "getrandom 0.2.16", "libc", "untrusted", "windows-sys 0.52.0", @@ -7320,23 +7544,23 @@ dependencies = [ [[package]] name = "rpassword" -version = "7.3.1" +version = "7.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80472be3c897911d0137b2d2b9055faf6eeac5b14e324073d83bc17b191d7e3f" +checksum = "66d4c8b64f049c6721ec8ccec37ddfc3d641c4a7fca57e8f2a89de509c73df39" dependencies = [ "libc", "rtoolbox", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] name = "rtoolbox" -version = "0.0.2" +version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c247d24e63230cdb56463ae328478bd5eac8b8faa8c69461a77e8e323afac90e" +checksum = "a7cc970b249fbe527d6e02e0a227762c9108b2f49d81094fe357ffc6d14d7f6f" dependencies = [ "libc", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -7396,9 +7620,9 @@ dependencies = [ [[package]] name = "rust_decimal" -version = "1.37.2" +version = "1.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b203a6425500a03e0919c42d3c47caca51e79f1132046626d2c8871c5092035d" +checksum = "35affe401787a9bd846712274d97654355d21b2a2c092a3139aabe31e9022282" dependencies = [ "arrayvec", "borsh", @@ -7413,15 +7637,15 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.24" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" [[package]] name = "rustc-hash" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" [[package]] name = "rustc_version" @@ -7434,15 +7658,15 @@ dependencies = [ [[package]] name = "rustify" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d375f36613139ffb8d55ead633a4904c74ffa1279cbdd2b96a037184cb56d932" +checksum = "759a090a17ce545d1adcffcc48207d5136c8984d8153bd8247b1ad4a71e49f5f" dependencies = [ "anyhow", "async-trait", "bytes", - "http 1.1.0", - "reqwest 0.12.9", + "http 1.3.1", + "reqwest 0.12.24", "rustify_derive", "serde", "serde_json", @@ -7454,9 +7678,9 @@ dependencies = [ [[package]] name = "rustify_derive" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7345f32672da54338227b727bd578c897859ddfaad8952e0b0d787fb4e58f07d" +checksum = "f07d43b2dbdbd99aaed648192098f0f413b762f0f352667153934ef3955f1793" dependencies = [ "proc-macro2", "quote", @@ -7468,28 +7692,28 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.40" +version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99e4ea3e1cdc4b559b8e5650f9c8e5998e3e5c1343b4eaf034565f32318d63c0" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ "bitflags 2.10.0", "errno", "libc", - "linux-raw-sys 0.4.14", - "windows-sys 0.52.0", + "linux-raw-sys 0.4.15", + "windows-sys 0.59.0", ] [[package]] name = "rustix" -version = "1.0.5" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d97817398dd4bb2e6da002002db259209759911da105da92bec29ccb12cf58bf" +checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" dependencies = [ "bitflags 2.10.0", "errno", "libc", - "linux-raw-sys 0.9.4", - "windows-sys 0.59.0", + "linux-raw-sys 0.11.0", + "windows-sys 0.61.2", ] [[package]] @@ -7499,7 +7723,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2fc84bf7e9aa16c4f2c758f27412dc9841341e16aa682d9c7ac308fe3ee12056" dependencies = [ "once_cell", - "rustix 1.0.5", + "rustix 1.1.2", ] [[package]] @@ -7530,15 +7754,15 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.18" +version = "0.23.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c9cc1d47e243d655ace55ed38201c19ae02c148ae56412ab8750e8f0166ab7f" +checksum = "6a9586e9ee2b4f8fab52a0048ca7334d7024eef48e2cb9407e3497bb7cab7fa7" dependencies = [ "log", "once_cell", "ring", "rustls-pki-types", - "rustls-webpki 0.102.8", + "rustls-webpki 0.103.8", "subtle", "zeroize", ] @@ -7588,10 +7812,11 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.12.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +checksum = "94182ad936a0c91c324cd46c6511b9510ed16af436d7b5bab34beab0afd55f7a" dependencies = [ + "web-time", "zeroize", ] @@ -7616,17 +7841,28 @@ dependencies = [ "untrusted", ] +[[package]] +name = "rustls-webpki" +version = "0.103.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ffdfa2f5286e2247234e03f680868ac2815974dc39e00ea15adc445d0aafe52" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + [[package]] name = "rustversion" -version = "1.0.18" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "ryu" -version = "1.0.18" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] name = "safetensors" @@ -7675,11 +7911,11 @@ checksum = "ece8e78b2f38ec51c51f5d475df0a7187ba5111b2a28bdc761ee05b075d40a71" [[package]] name = "schannel" -version = "0.1.26" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" +checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -7696,6 +7932,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.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1317c3bf3e7df961da95b0a56a172a02abead31276215a0497241a7624b487ce" +dependencies = [ + "dyn-clone", + "ref-cast", + "serde", + "serde_json", +] + [[package]] name = "schemars_derive" version = "0.8.22" @@ -7708,12 +7968,6 @@ dependencies = [ "syn 2.0.108", ] -[[package]] -name = "scoped-tls" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" - [[package]] name = "scopeguard" version = "1.2.0" @@ -7794,12 +8048,12 @@ dependencies = [ [[package]] name = "security-framework" -version = "3.2.0" +version = "3.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271720403f46ca04f7ba6f55d438f8bd878d6b8ca0a1046e8228c4145bcbb316" +checksum = "b3297343eaf830f66ede390ea39da1d462b6b0c1b000f420d0a83f898bbbe6ef" dependencies = [ "bitflags 2.10.0", - "core-foundation 0.10.0", + "core-foundation 0.10.1", "core-foundation-sys", "libc", "security-framework-sys", @@ -7807,9 +8061,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.14.0" +version = "2.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" +checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0" dependencies = [ "core-foundation-sys", "libc", @@ -7817,18 +8071,19 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.23" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" dependencies = [ "serde", + "serde_core", ] [[package]] name = "seq-macro" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3f0bf26fd526d2a95683cd0f87bf103b8539e2ca1ef48ce002d67aad59aa0b4" +checksum = "1bc711410fbe7399f390ca1c3b60ad0f53f80e95c5eb935e52268a0e2cd49acc" [[package]] name = "serde" @@ -7883,33 +8138,36 @@ dependencies = [ [[package]] name = "serde_ignored" -version = "0.1.10" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8e319a36d1b52126a0d608f24e93b2d81297091818cd70625fcf50a15d84ddf" +checksum = "115dffd5f3853e06e746965a20dcbae6ee747ae30b543d91b0e089668bb07798" dependencies = [ "serde", + "serde_core", ] [[package]] name = "serde_json" -version = "1.0.132" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" dependencies = [ "itoa", "memchr", "ryu", "serde", + "serde_core", ] [[package]] name = "serde_path_to_error" -version = "0.1.16" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af99884400da37c88f5e9146b7f1fd0fbcae8f6eec4e9da38b67d05486f814a6" +checksum = "10a9ff822e371bb5403e391ecd83e182e0e77ba7f6fe0160b795797109d1b457" dependencies = [ "itoa", "serde", + "serde_core", ] [[package]] @@ -7934,9 +8192,9 @@ dependencies = [ [[package]] name = "serde_repr" -version = "0.1.19" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" +checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" dependencies = [ "proc-macro2", "quote", @@ -7945,9 +8203,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.8" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" dependencies = [ "serde", ] @@ -7966,17 +8224,18 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.11.0" +version = "3.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e28bdad6db2b8340e449f7108f020b3b092e8583a9e3fb82713e1d4e71fe817" +checksum = "aa66c845eee442168b2c8134fec70ac50dc20e760769c8ba0ad1319ca1959b04" dependencies = [ "base64 0.22.1", "chrono", "hex", "indexmap 1.9.3", "indexmap 2.12.0", - "serde", - "serde_derive", + "schemars 0.9.0", + "schemars 1.0.5", + "serde_core", "serde_json", "serde_with_macros", "time", @@ -7984,11 +8243,11 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.11.0" +version = "3.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d846214a9854ef724f3da161b426242d8de7c1fc7de2f89bb1efcb154dca79d" +checksum = "b91a903660542fced4e99881aa481bdbaec1634568ee02e0b8bd57c64cb38955" dependencies = [ - "darling 0.20.10", + "darling 0.21.3", "proc-macro2", "quote", "syn 2.0.108", @@ -8036,9 +8295,9 @@ checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d" [[package]] name = "sha2" -version = "0.10.8" +version = "0.10.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", "cpufeatures", @@ -8047,9 +8306,9 @@ dependencies = [ [[package]] name = "sha256" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18278f6a914fa3070aa316493f7d2ddfb9ac86ebc06fa3b83bffda487e9065b0" +checksum = "f880fc8562bdeb709793f00eb42a2ad0e672c4f883bbe59122b926eca935c8f6" dependencies = [ "async-trait", "bytes", @@ -8081,9 +8340,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" -version = "1.4.2" +version = "1.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +checksum = "b2a4719bff48cee6b39d12c020eeb490953ad2443b7055bd0b21fca26bd8c28b" dependencies = [ "libc", ] @@ -8098,6 +8357,12 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + [[package]] name = "simdutf8" version = "0.1.5" @@ -8106,15 +8371,15 @@ checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" [[package]] name = "similar" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1de1d4f81173b03af4c0cbed3c898f6bff5b870e4a7f5d6f4057d62a7a4b686e" +checksum = "bbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daa" [[package]] name = "siphasher" -version = "0.3.11" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" +checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" [[package]] name = "sized-chunks" @@ -8128,12 +8393,9 @@ dependencies = [ [[package]] name = "slab" -version = "0.4.9" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] +checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" [[package]] name = "smallvec" @@ -8188,9 +8450,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.7" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" dependencies = [ "libc", "windows-sys 0.52.0", @@ -8198,19 +8460,19 @@ dependencies = [ [[package]] name = "socket2" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" +checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] name = "spdx" -version = "0.10.6" +version = "0.10.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47317bbaf63785b53861e1ae2d11b80d6b624211d42cb20efcd210ee6f8a14bc" +checksum = "c3e17e880bafaeb362a7b751ec46bdc5b61445a188f80e0606e68167cd540fa3" dependencies = [ "smallvec", ] @@ -8234,7 +8496,7 @@ dependencies = [ "spin-factors-test", "spin-locked-app", "tokio", - "toml", + "toml 0.8.23", ] [[package]] @@ -8250,7 +8512,7 @@ dependencies = [ "subprocess", "terminal", "tokio", - "toml", + "toml 0.8.23", "topological-sort", "tracing", ] @@ -8271,11 +8533,12 @@ dependencies = [ "conformance-tests", "ctrlc", "dialoguer", + "fake-opentelemetry-collector", "futures", "hex", - "http 1.1.0", + "http 1.3.1", "http-body-util", - "hyper 1.5.0", + "hyper 1.7.0", "hyper-util", "indicatif", "itertools 0.14.0", @@ -8287,10 +8550,10 @@ dependencies = [ "pretty_assertions", "redis", "regex", - "reqwest 0.12.9", + "reqwest 0.12.24", "rpassword", "runtime-tests", - "schemars", + "schemars 0.8.22", "semver", "serde", "serde_json", @@ -8321,7 +8584,7 @@ dependencies = [ "test-environment", "testing-framework", "tokio", - "toml", + "toml 0.8.23", "tracing", "url", "uuid", @@ -8350,14 +8613,14 @@ dependencies = [ "anyhow", "async-trait", "cap-std", - "rand 0.9.1", + "rand 0.9.2", "rand_chacha 0.3.1", "rand_core 0.6.4", "serde", "serde_json", "tempfile", "tokio", - "toml", + "toml 0.8.23", "tracing", "wasm-encoder 0.239.0", "wasm-metadata 0.239.0", @@ -8411,7 +8674,7 @@ dependencies = [ "anyhow", "async-trait", "glob", - "reqwest 0.12.9", + "reqwest 0.12.24", "serde", "similar", "spin-common", @@ -8419,8 +8682,8 @@ dependencies = [ "tempfile", "terminal", "tokio", - "toml", - "toml_edit", + "toml 0.8.23", + "toml_edit 0.22.27", "tracing", "ui-testing", ] @@ -8448,7 +8711,7 @@ dependencies = [ "spin-manifest", "spin-serde", "tokio", - "toml", + "toml 0.8.23", "tracing", "wac-graph", "wac-types", @@ -8469,7 +8732,7 @@ dependencies = [ "spin-locked-app", "thiserror 2.0.17", "tokio", - "toml", + "toml 0.8.23", ] [[package]] @@ -8479,6 +8742,7 @@ dependencies = [ "anyhow", "serde", "spin-core", + "spin-factor-otel", "spin-factors", "spin-factors-test", "spin-key-value-redis", @@ -8490,7 +8754,7 @@ dependencies = [ "tempfile", "thiserror 2.0.17", "tokio", - "toml", + "toml 0.8.23", "tracing", ] @@ -8501,6 +8765,7 @@ dependencies = [ "anyhow", "async-trait", "serde", + "spin-factor-otel", "spin-factors", "spin-factors-test", "spin-llm-local", @@ -8509,27 +8774,47 @@ dependencies = [ "spin-telemetry", "spin-world", "tokio", - "toml", + "toml 0.8.23", "tracing", "url", ] +[[package]] +name = "spin-factor-otel" +version = "3.6.0-pre0" +dependencies = [ + "anyhow", + "indexmap 2.12.0", + "opentelemetry", + "opentelemetry-otlp", + "opentelemetry_sdk", + "spin-core", + "spin-factors", + "spin-resource-table", + "spin-telemetry", + "spin-world", + "toml 0.5.11", + "tracing", + "tracing-opentelemetry", +] + [[package]] name = "spin-factor-outbound-http" version = "3.6.0-pre0" dependencies = [ "anyhow", "bytes", - "http 1.1.0", + "http 1.3.1", "http-body 1.0.1", "http-body-util", - "hyper 1.5.0", + "hyper 1.7.0", "hyper-util", "pin-project-lite", - "reqwest 0.12.9", - "rustls 0.23.18", + "reqwest 0.12.24", + "rustls 0.23.34", "serde", "spin-common", + "spin-factor-otel", "spin-factor-outbound-networking", "spin-factor-variables", "spin-factors", @@ -8537,7 +8822,7 @@ dependencies = [ "spin-telemetry", "spin-world", "tokio", - "tokio-rustls 0.26.0", + "tokio-rustls 0.26.4", "tower-service", "tracing", "wasmtime", @@ -8552,6 +8837,7 @@ dependencies = [ "anyhow", "rumqttc", "spin-core", + "spin-factor-otel", "spin-factor-outbound-networking", "spin-factor-variables", "spin-factors", @@ -8569,6 +8855,7 @@ dependencies = [ "anyhow", "mysql_async", "spin-core", + "spin-factor-otel", "spin-factor-outbound-networking", "spin-factor-variables", "spin-factors", @@ -8586,9 +8873,9 @@ version = "3.6.0-pre0" dependencies = [ "anyhow", "futures-util", - "http 1.1.0", + "http 1.3.1", "ip_network", - "rustls 0.23.18", + "rustls 0.23.34", "rustls-pki-types", "serde", "spin-factor-variables", @@ -8601,11 +8888,11 @@ dependencies = [ "spin-serde", "tempfile", "tokio", - "toml", + "toml 0.8.23", "tracing", "url", "wasmtime-wasi", - "webpki-roots", + "webpki-roots 0.26.11", ] [[package]] @@ -8623,6 +8910,7 @@ dependencies = [ "rust_decimal", "serde_json", "spin-core", + "spin-factor-otel", "spin-factor-outbound-networking", "spin-factor-variables", "spin-factors", @@ -8642,6 +8930,7 @@ dependencies = [ "anyhow", "redis", "spin-core", + "spin-factor-otel", "spin-factor-outbound-networking", "spin-factor-variables", "spin-factors", @@ -8657,6 +8946,7 @@ name = "spin-factor-sqlite" version = "3.6.0-pre0" dependencies = [ "async-trait", + "spin-factor-otel", "spin-factors", "spin-factors-test", "spin-locked-app", @@ -8671,6 +8961,7 @@ name = "spin-factor-variables" version = "3.6.0-pre0" dependencies = [ "spin-expressions", + "spin-factor-otel", "spin-factors", "spin-factors-test", "spin-telemetry", @@ -8702,7 +8993,7 @@ dependencies = [ "spin-app", "spin-factors-derive", "thiserror 2.0.17", - "toml", + "toml 0.8.23", "wasmtime", ] @@ -8738,7 +9029,7 @@ dependencies = [ "spin-loader", "spin-telemetry", "tempfile", - "toml", + "toml 0.8.23", ] [[package]] @@ -8746,9 +9037,9 @@ name = "spin-http" version = "3.6.0-pre0" dependencies = [ "anyhow", - "http 1.1.0", + "http 1.3.1", "http-body-util", - "hyper 1.5.0", + "hyper 1.7.0", "indexmap 2.12.0", "percent-encoding", "routefinder", @@ -8757,7 +9048,7 @@ dependencies = [ "spin-factor-outbound-http", "spin-http-routes", "terminal", - "toml", + "toml 0.8.23", "tracing", "wasmtime", "wasmtime-wasi", @@ -8800,7 +9091,7 @@ dependencies = [ "azure_data_cosmos", "azure_identity 0.21.0", "futures", - "reqwest 0.12.9", + "reqwest 0.12.24", "serde", "spin-factor-key-value", ] @@ -8839,7 +9130,7 @@ dependencies = [ "candle-core", "candle-nn", "candle-transformers", - "rand 0.9.1", + "rand 0.9.2", "safetensors 0.5.3", "serde", "serde_json", @@ -8856,7 +9147,7 @@ name = "spin-llm-remote-http" version = "3.6.0-pre0" dependencies = [ "anyhow", - "reqwest 0.12.9", + "reqwest 0.12.24", "serde", "serde_json", "spin-telemetry", @@ -8873,7 +9164,7 @@ dependencies = [ "futures", "glob", "path-absolutize", - "reqwest 0.12.9", + "reqwest 0.12.24", "semver", "serde", "serde_json", @@ -8887,7 +9178,7 @@ dependencies = [ "tempfile", "terminal", "tokio", - "toml", + "toml 0.8.23", "tracing", "ui-testing", "wasm-pkg-client", @@ -8913,14 +9204,14 @@ dependencies = [ "anyhow", "glob", "indexmap 2.12.0", - "schemars", + "schemars 0.8.22", "semver", "serde", "serde_json", "spin-serde", "terminal", "thiserror 2.0.17", - "toml", + "toml 0.8.23", "ui-testing", "url", "wasm-pkg-common", @@ -8941,7 +9232,7 @@ dependencies = [ "futures-util", "itertools 0.14.0", "oci-distribution 0.11.0 (git+https://github.com/fermyon/oci-distribution?rev=7b291a39f74d1a3c9499d934a56cae6580fc8e37)", - "reqwest 0.12.9", + "reqwest 0.12.24", "serde", "serde_json", "spin-common", @@ -8967,7 +9258,7 @@ version = "3.6.0-pre0" dependencies = [ "anyhow", "futures-util", - "http 1.1.0", + "http 1.3.1", "ip_network", "ip_network_table", "spin-expressions", @@ -8986,7 +9277,7 @@ dependencies = [ "fd-lock", "flate2", "path-absolutize", - "reqwest 0.12.9", + "reqwest 0.12.24", "semver", "serde", "serde_json", @@ -9014,6 +9305,7 @@ dependencies = [ "spin-expressions", "spin-factor-key-value", "spin-factor-llm", + "spin-factor-otel", "spin-factor-outbound-http", "spin-factor-outbound-mqtt", "spin-factor-outbound-mysql", @@ -9038,7 +9330,7 @@ dependencies = [ "spin-world", "tempfile", "tokio", - "toml", + "toml 0.8.23", ] [[package]] @@ -9050,6 +9342,7 @@ dependencies = [ "spin-common", "spin-factor-key-value", "spin-factor-llm", + "spin-factor-otel", "spin-factor-outbound-http", "spin-factor-outbound-mqtt", "spin-factor-outbound-mysql", @@ -9075,7 +9368,7 @@ dependencies = [ "anyhow", "base64 0.22.1", "indexmap 2.12.0", - "schemars", + "schemars 0.8.22", "semver", "serde", "wasm-pkg-common", @@ -9090,7 +9383,7 @@ dependencies = [ "spin-factors", "spin-sqlite-inproc", "spin-sqlite-libsql", - "toml", + "toml 0.8.23", ] [[package]] @@ -9123,7 +9416,7 @@ version = "3.6.0-pre0" dependencies = [ "anyhow", "http 0.2.12", - "http 1.1.0", + "http 1.3.1", "opentelemetry", "opentelemetry-appender-tracing", "opentelemetry-otlp", @@ -9153,7 +9446,7 @@ dependencies = [ "path-absolutize", "pathdiff", "regex", - "reqwest 0.12.9", + "reqwest 0.12.24", "semver", "serde", "spin-common", @@ -9162,8 +9455,8 @@ dependencies = [ "tempfile", "terminal", "tokio", - "toml", - "toml_edit", + "toml 0.8.23", + "toml_edit 0.22.27", "url", "walkdir", ] @@ -9203,18 +9496,19 @@ dependencies = [ "anyhow", "clap 3.2.25", "futures", - "http 1.1.0", + "http 1.3.1", "http-body 1.0.1", "http-body-util", - "hyper 1.5.0", + "hyper 1.7.0", "hyper-util", "pin-project-lite", - "rustls 0.23.18", + "rustls 0.23.34", "rustls-pki-types", "serde", "serde_json", "spin-app", "spin-core", + "spin-factor-otel", "spin-factor-outbound-http", "spin-factor-outbound-networking", "spin-factor-wasi", @@ -9226,7 +9520,7 @@ dependencies = [ "spin-world", "terminal", "tokio", - "tokio-rustls 0.26.0", + "tokio-rustls 0.26.4", "tracing", "wasmtime", "wasmtime-wasi", @@ -9287,7 +9581,7 @@ dependencies = [ "spin-expressions", "spin-factors", "tempfile", - "toml", + "toml 0.8.23", ] [[package]] @@ -9305,7 +9599,10 @@ dependencies = [ name = "spin-world" version = "3.6.0-pre0" dependencies = [ + "anyhow", "async-trait", + "opentelemetry", + "opentelemetry_sdk", "wasmtime", ] @@ -9333,9 +9630,9 @@ dependencies = [ [[package]] name = "stable_deref_trait" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] name = "static_assertions" @@ -9450,9 +9747,9 @@ checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" [[package]] name = "sync_wrapper" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" dependencies = [ "futures-core", ] @@ -9471,9 +9768,9 @@ dependencies = [ [[package]] name = "synstructure" -version = "0.13.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", @@ -9552,17 +9849,17 @@ dependencies = [ [[package]] name = "system-interface" -version = "0.27.2" +version = "0.27.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b858526d22750088a9b3cf2e3c2aacebd5377f13adeec02860c30d09113010a6" +checksum = "cc4592f674ce18521c2a81483873a49596655b179f71c5e05d10c1fe66c78745" dependencies = [ "bitflags 2.10.0", "cap-fs-ext", "cap-std", "fd-lock", "io-lifetimes", - "rustix 0.38.40", - "windows-sys 0.52.0", + "rustix 0.38.44", + "windows-sys 0.59.0", "winx", ] @@ -9580,9 +9877,9 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tar" -version = "0.4.43" +version = "0.4.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c65998313f8e17d0d553d28f91a0df93e4dbbbf770279c7bc21ca0f09ea1a1f6" +checksum = "1d863878d212c87a19c1a610eb53bb01fe12951c0501cf5a0d65f724914a667a" dependencies = [ "filetime", "libc", @@ -9591,15 +9888,15 @@ dependencies = [ [[package]] name = "target-lexicon" -version = "0.13.1" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc12939a1c9b9d391e0b7135f72fd30508b73450753e28341fed159317582a77" +checksum = "df7f62577c25e07834649fc3b39fafdc597c0a3527dc1c60129201ccfcbaa50c" [[package]] name = "temp-dir" -version = "0.1.14" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc1ee6eef34f12f765cb94725905c6312b6610ab2b0940889cfe58dae7bc3c72" +checksum = "83176759e9416cf81ee66cb6508dbfe9c96f20b8b56265a39917551c23c70964" [[package]] name = "tempfile" @@ -9607,11 +9904,11 @@ version = "3.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" dependencies = [ - "fastrand 2.2.0", - "getrandom 0.3.2", + "fastrand 2.3.0", + "getrandom 0.3.4", "once_cell", - "rustix 1.0.5", - "windows-sys 0.60.2", + "rustix 1.1.2", + "windows-sys 0.61.2", ] [[package]] @@ -9638,7 +9935,7 @@ checksum = "d4ea810f0692f9f51b382fff5893887bb4580f5fa246fde546e0b13e7fcee662" dependencies = [ "fnv", "nom", - "phf", + "phf 0.11.3", "phf_codegen", ] @@ -9667,7 +9964,7 @@ dependencies = [ "anyhow", "fslock", "regex", - "reqwest 0.12.9", + "reqwest 0.12.24", "temp-dir", "tokio", ] @@ -9677,11 +9974,11 @@ name = "testing-framework" version = "0.1.0" dependencies = [ "anyhow", - "http 1.1.0", + "http 1.3.1", "http-body-util", "log", "nix 0.29.0", - "reqwest 0.12.9", + "reqwest 0.12.24", "spin-app", "spin-http", "spin-loader", @@ -9694,9 +9991,9 @@ dependencies = [ [[package]] name = "textwrap" -version = "0.16.1" +version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9" +checksum = "c13547615a44dc9c452a8a534638acdf07120d4b6847c8178705da06306a3057" [[package]] name = "thiserror" @@ -9740,12 +10037,11 @@ dependencies = [ [[package]] name = "thread_local" -version = "1.1.8" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" dependencies = [ "cfg-if", - "once_cell", ] [[package]] @@ -9759,9 +10055,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.36" +version = "0.3.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d" dependencies = [ "deranged", "itoa", @@ -9777,15 +10073,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.2" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" +checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b" [[package]] name = "time-macros" -version = "0.2.18" +version = "0.2.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3" dependencies = [ "num-conv", "time-core", @@ -9811,9 +10107,9 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.7.6" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" dependencies = [ "displaydoc", "zerovec", @@ -9821,9 +10117,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.8.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" dependencies = [ "tinyvec_macros", ] @@ -9836,23 +10132,25 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokenizers" -version = "0.21.1" +version = "0.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3169b3195f925496c895caee7978a335d49218488ef22375267fba5a46a40bd7" +checksum = "a620b996116a59e184c2fa2dfd8251ea34a36d0a514758c6f966386bd2e03476" dependencies = [ + "ahash 0.8.12", "aho-corasick", + "compact_str", + "dary_heap", "derive_builder 0.20.2", "esaxx-rs", - "getrandom 0.2.15", + "getrandom 0.3.4", "indicatif", - "itertools 0.13.0", - "lazy_static 1.5.0", + "itertools 0.14.0", "log", "macro_rules_attribute", "monostate", "onig", "paste", - "rand 0.8.5", + "rand 0.9.2", "rayon", "rayon-cond", "regex", @@ -9868,27 +10166,26 @@ dependencies = [ [[package]] name = "tokio" -version = "1.45.1" +version = "1.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75ef51a33ef1da925cea3e4eb122833cb377c61439ca401b770f54902b806779" +checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" dependencies = [ - "backtrace", "bytes", "libc", "mio", "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2 0.5.7", + "socket2 0.6.1", "tokio-macros", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] name = "tokio-macros" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ "proc-macro2", "quote", @@ -9907,9 +10204,9 @@ dependencies = [ [[package]] name = "tokio-postgres" -version = "0.7.12" +version = "0.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b5d3742945bc7d7f210693b0c58ae542c6fd47b17adbbda0885f3dcb34a6bdb" +checksum = "2b40d66d9b2cfe04b628173409368e58247e8eddbbd3b0e6c6ba1d09f20f6c9e" dependencies = [ "async-trait", "byteorder", @@ -9920,12 +10217,12 @@ dependencies = [ "log", "parking_lot", "percent-encoding", - "phf", + "phf 0.13.1", "pin-project-lite", "postgres-protocol", "postgres-types", - "rand 0.8.5", - "socket2 0.5.7", + "rand 0.9.2", + "socket2 0.6.1", "tokio", "tokio-util", "whoami", @@ -9954,32 +10251,19 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" -dependencies = [ - "rustls 0.23.18", - "rustls-pki-types", - "tokio", -] - -[[package]] -name = "tokio-socks" -version = "0.5.2" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d4770b8024672c1101b3f6733eab95b18007dbe0847a8afe341fcf79e06043f" +checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" dependencies = [ - "either", - "futures-util", - "thiserror 1.0.69", + "rustls 0.23.34", "tokio", ] [[package]] name = "tokio-stream" -version = "0.1.16" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" +checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" dependencies = [ "futures-core", "pin-project-lite", @@ -9988,9 +10272,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.12" +version = "0.7.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" +checksum = "2efa149fe76073d6e8fd97ef4f4eca7b67f599660115591483572e406e165594" dependencies = [ "bytes", "futures-core", @@ -10002,39 +10286,85 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.19" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "serde", +] + +[[package]] +name = "toml" +version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" +checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" dependencies = [ "indexmap 2.12.0", "serde", "serde_spanned", - "toml_datetime", - "toml_edit", + "toml_datetime 0.6.11", + "toml_edit 0.22.27", ] [[package]] name = "toml_datetime" -version = "0.6.8" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" dependencies = [ "serde", ] +[[package]] +name = "toml_datetime" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2cdb639ebbc97961c51720f858597f7f24c4fc295327923af55b74c3c724533" +dependencies = [ + "serde_core", +] + [[package]] name = "toml_edit" -version = "0.22.22" +version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ "indexmap 2.12.0", "serde", "serde_spanned", - "toml_datetime", - "winnow 0.6.20", + "toml_datetime 0.6.11", + "toml_write", + "winnow", +] + +[[package]] +name = "toml_edit" +version = "0.23.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6485ef6d0d9b5d0ec17244ff7eb05310113c3f316f2d14200d4de56b3cb98f8d" +dependencies = [ + "indexmap 2.12.0", + "toml_datetime 0.7.3", + "toml_parser", + "winnow", +] + +[[package]] +name = "toml_parser" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0cbe268d35bdb4bb5a56a2de88d0ad0eb70af5384a99d648cd4b3d04039800e" +dependencies = [ + "winnow", ] +[[package]] +name = "toml_write" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" + [[package]] name = "tonic" version = "0.12.3" @@ -10046,17 +10376,17 @@ dependencies = [ "axum", "base64 0.22.1", "bytes", - "h2 0.4.6", - "http 1.1.0", + "h2 0.4.12", + "http 1.3.1", "http-body 1.0.1", "http-body-util", - "hyper 1.5.0", + "hyper 1.7.0", "hyper-timeout", "hyper-util", "percent-encoding", "pin-project", - "prost 0.13.3", - "socket2 0.5.7", + "prost 0.13.5", + "socket2 0.5.10", "tokio", "tokio-stream", "tower 0.4.13", @@ -10100,7 +10430,26 @@ dependencies = [ "futures-core", "futures-util", "pin-project-lite", - "sync_wrapper 1.0.1", + "sync_wrapper 1.0.2", + "tokio", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-http" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" +dependencies = [ + "bitflags 2.10.0", + "bytes", + "futures-util", + "http 1.3.1", + "http-body 1.0.1", + "iri-string", + "pin-project-lite", + "tower 0.5.2", "tower-layer", "tower-service", ] @@ -10131,9 +10480,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.28" +version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" +checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" dependencies = [ "proc-macro2", "quote", @@ -10142,9 +10491,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.33" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" +checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" dependencies = [ "once_cell", "valuable", @@ -10218,15 +10567,15 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "twox-hash" -version = "2.1.0" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7b17f197b3050ba473acf9181f7b1d3b66d1cf7356c6cc57886662276e65908" +checksum = "9ea3136b675547379c4bd395ca6b938e5ad3c3d20fad76e7fe85f9e0d011419c" [[package]] name = "typenum" -version = "1.17.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" [[package]] name = "tz-rs" @@ -10272,7 +10621,7 @@ dependencies = [ "serde", "thiserror 1.0.69", "tracing", - "yoke", + "yoke 0.7.5", ] [[package]] @@ -10324,15 +10673,15 @@ dependencies = [ [[package]] name = "unicase" -version = "2.8.0" +version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e51b68083f157f853b6379db119d1c1be0e6e4dec98101079dec41f6f5cf6df" +checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" [[package]] name = "unicode-bidi" -version = "0.3.17" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" +checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" [[package]] name = "unicode-bom" @@ -10342,15 +10691,15 @@ checksum = "7eec5d1121208364f6793f7d2e222bf75a915c19557537745b195b253dd64217" [[package]] name = "unicode-ident" -version = "1.0.13" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" [[package]] name = "unicode-normalization" -version = "0.1.24" +version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" +checksum = "5fd4f6878c9cb28d874b009da9e8d183b5abc80117c40bbd187a1fde336be6e8" dependencies = [ "tinyvec", ] @@ -10366,9 +10715,9 @@ dependencies = [ [[package]] name = "unicode-properties" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0" +checksum = "7df058c713841ad818f1dc5d3fd88063241cc61f49f5fbea4b951e8cf5a8d71d" [[package]] name = "unicode-segmentation" @@ -10384,9 +10733,9 @@ checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" [[package]] name = "unicode-width" -version = "0.2.0" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" [[package]] name = "unicode-xid" @@ -10430,12 +10779,6 @@ version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" -[[package]] -name = "utf16_iter" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" - [[package]] name = "utf8_iter" version = "1.0.4" @@ -10450,30 +10793,38 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.11.0" +version = "1.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" +checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2" dependencies = [ - "getrandom 0.2.15", + "getrandom 0.3.4", + "js-sys", + "wasm-bindgen", ] [[package]] name = "valuable" -version = "0.1.0" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + +[[package]] +name = "value-bag" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" +checksum = "943ce29a8a743eb10d6082545d861b24f9d1b160b7d741e0f2cdf726bec909c5" [[package]] name = "vaultrs" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a769a71e45deef489beed23167f79ee75d41f482b5e3d96ddab833f24fd07e51" +checksum = "f81eb4d9221ca29bad43d4b6871b6d2e7656e1af2cfca624a87e5d17880d831d" dependencies = [ "async-trait", "bytes", "derive_builder 0.12.0", - "http 1.1.0", - "reqwest 0.12.9", + "http 1.3.1", + "reqwest 0.12.24", "rustify", "rustify_derive", "serde", @@ -10598,7 +10949,7 @@ dependencies = [ "async-recursion", "async-trait", "bytes", - "clap 4.5.20", + "clap 4.5.51", "dialoguer", "dirs 5.0.1", "futures-util", @@ -10610,7 +10961,7 @@ dependencies = [ "once_cell", "pathdiff", "ptree", - "reqwest 0.12.9", + "reqwest 0.12.24", "secrecy", "semver", "serde", @@ -10719,17 +11070,17 @@ checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" [[package]] name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] -name = "wasi" -version = "0.14.2+wasi-0.2.4" +name = "wasip2" +version = "1.0.1+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" dependencies = [ - "wit-bindgen-rt", + "wit-bindgen", ] [[package]] @@ -10740,47 +11091,35 @@ checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" [[package]] name = "wasm-bindgen" -version = "0.2.95" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" +checksum = "da95793dfc411fbbd93f5be7715b0578ec61fe87cb1a42b12eb625caa5c5ea60" dependencies = [ "cfg-if", "once_cell", + "rustversion", "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.95" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" -dependencies = [ - "bumpalo", - "log", - "once_cell", - "proc-macro2", - "quote", - "syn 2.0.108", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.45" +version = "0.4.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc7ec4f8827a71586374db3e87abdb5a2bb3a15afed140221307c3ec06b1f63b" +checksum = "551f88106c6d5e7ccc7cd9a16f312dd3b5d36ea8b4954304657d5dfba115d4a0" dependencies = [ "cfg-if", "js-sys", + "once_cell", "wasm-bindgen", "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.95" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" +checksum = "04264334509e04a7bf8690f2384ef5265f05143a4bff3889ab7a3269adab59c2" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -10788,22 +11127,25 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.95" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" +checksum = "420bc339d9f322e562942d52e115d57e950d12d88983a14c79b86859ee6c7ebc" dependencies = [ + "bumpalo", "proc-macro2", "quote", "syn 2.0.108", - "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.95" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" +checksum = "76f218a38c84bcb33c25ec7059b07847d465ce0e0a76b995e134a45adcb6af76" +dependencies = [ + "unicode-ident", +] [[package]] name = "wasm-compose" @@ -10866,6 +11208,16 @@ dependencies = [ "wasmparser 0.239.0", ] +[[package]] +name = "wasm-encoder" +version = "0.240.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06d642d8c5ecc083aafe9ceb32809276a304547a3a6eeecceb5d8152598bc71f" +dependencies = [ + "leb128fmt", + "wasmparser 0.240.0", +] + [[package]] name = "wasm-metadata" version = "0.224.1" @@ -10936,7 +11288,7 @@ dependencies = [ "futures-util", "oci-client", "oci-wasm", - "reqwest 0.12.9", + "reqwest 0.12.24", "secrecy", "serde", "serde_json", @@ -10944,7 +11296,7 @@ dependencies = [ "thiserror 1.0.69", "tokio", "tokio-util", - "toml", + "toml 0.8.23", "tracing", "tracing-subscriber", "url", @@ -10966,14 +11318,14 @@ dependencies = [ "bytes", "etcetera", "futures-util", - "http 1.1.0", + "http 1.3.1", "semver", "serde", "serde_json", "sha2", "thiserror 1.0.69", "tokio", - "toml", + "toml 0.8.23", ] [[package]] @@ -11007,7 +11359,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04f17a5917c2ddd3819e84c661fae0d6ba29d7b9c1f0e96c708c65a9c4188e11" dependencies = [ "bitflags 2.10.0", - "hashbrown 0.15.2", + "hashbrown 0.15.5", "indexmap 2.12.0", "semver", ] @@ -11019,7 +11371,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "161296c618fa2d63f6ed5fffd1112937e803cb9ec71b32b01a76321555660917" dependencies = [ "bitflags 2.10.0", - "hashbrown 0.15.2", + "hashbrown 0.15.5", "indexmap 2.12.0", "semver", "serde", @@ -11032,12 +11384,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c9d90bb93e764f6beabf1d02028c70a2156a6583e63ac4218dd07ef733368b0" dependencies = [ "bitflags 2.10.0", - "hashbrown 0.15.2", + "hashbrown 0.15.5", "indexmap 2.12.0", "semver", "serde", ] +[[package]] +name = "wasmparser" +version = "0.240.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b722dcf61e0ea47440b53ff83ccb5df8efec57a69d150e4f24882e4eba7e24a4" +dependencies = [ + "bitflags 2.10.0", + "indexmap 2.12.0", + "semver", +] + [[package]] name = "wasmprinter" version = "0.2.80" @@ -11061,11 +11424,11 @@ dependencies = [ [[package]] name = "wasmtime" -version = "37.0.1" +version = "37.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eae1ef7649330697f0374eca8af0a437cf349605afce261bb64ba66fa0663c80" +checksum = "1092d79769b1f888940a572ed881eec18f837cb96201985eb5928226759ebc3e" dependencies = [ - "addr2line 0.25.0", + "addr2line", "anyhow", "async-trait", "bitflags 2.10.0", @@ -11076,20 +11439,20 @@ dependencies = [ "encoding_rs", "futures", "fxprof-processed-profile", - "gimli 0.32.0", - "hashbrown 0.15.2", + "gimli", + "hashbrown 0.15.5", "indexmap 2.12.0", "ittapi", "libc", "log", "mach2", "memfd", - "object 0.37.3", + "object", "once_cell", "postcard", "pulley-interpreter", "rayon", - "rustix 1.0.5", + "rustix 1.1.2", "semver", "serde", "serde_derive", @@ -11118,18 +11481,18 @@ dependencies = [ [[package]] name = "wasmtime-environ" -version = "37.0.1" +version = "37.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6bf9ff7210fa31880e7cf3cfa1b83648c777090aa11ac1c448dff11e6c466a2" +checksum = "484db5c4dd06e96559217b60893b5dbb9fe3cd28489c83a4257b277c9ead959c" dependencies = [ "anyhow", "cpp_demangle", "cranelift-bitset", "cranelift-entity", - "gimli 0.32.0", + "gimli", "indexmap 2.12.0", "log", - "object 0.37.3", + "object", "postcard", "rustc-demangle", "semver", @@ -11145,38 +11508,38 @@ dependencies = [ [[package]] name = "wasmtime-internal-asm-macros" -version = "37.0.1" +version = "37.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "761159dea98c5f585497f715d9d80b38baa7c6334cf9e033a76d01b291719416" +checksum = "60d3903b8db592bb4f5e847bd6dc38f485791d4d9ebc9e2df167d3c7f072115c" dependencies = [ "cfg-if", ] [[package]] name = "wasmtime-internal-cache" -version = "37.0.1" +version = "37.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ea7c17c1d771c923f63c08bd79d6714ca8bb503cf4ecb6f39d82043280020bd" +checksum = "5ab11f58f3b24a4a47d7d99b45ca22635c33cf26acdda1fe77612180e7285e2f" dependencies = [ "anyhow", "base64 0.22.1", "directories-next", "log", "postcard", - "rustix 1.0.5", + "rustix 1.1.2", "serde", "serde_derive", "sha2", - "toml", + "toml 0.8.23", "windows-sys 0.60.2", "zstd", ] [[package]] name = "wasmtime-internal-component-macro" -version = "37.0.1" +version = "37.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd634b96656a0740f2b5fdb01e69bfc670bafbb292436826022a26153b33e818" +checksum = "73c7d26d0c0d6da9f35dd56e3651a84bc4741646803e78886a3144aaf15c941e" dependencies = [ "anyhow", "proc-macro2", @@ -11189,15 +11552,15 @@ dependencies = [ [[package]] name = "wasmtime-internal-component-util" -version = "37.0.1" +version = "37.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a29a22837e16da7263e3622a7451917684971f65d21f4f9b97049babfacee37" +checksum = "bb62647125f7a0833cefb9a8862bc7886d206fe4e7131201bddd8d3979abbb02" [[package]] name = "wasmtime-internal-cranelift" -version = "37.0.1" +version = "37.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da2055ee07c1782ec3bb96bd7b91328e003de1a327eb02c48c2dfc937f490547" +checksum = "d802c0a214c82fbf3e60ead87bf4d5dff7fc957c9a4449ceeae74bd89283ee57" dependencies = [ "anyhow", "cfg-if", @@ -11206,10 +11569,10 @@ dependencies = [ "cranelift-entity", "cranelift-frontend", "cranelift-native", - "gimli 0.32.0", + "gimli", "itertools 0.14.0", "log", - "object 0.37.3", + "object", "pulley-interpreter", "smallvec", "target-lexicon", @@ -11223,15 +11586,15 @@ dependencies = [ [[package]] name = "wasmtime-internal-fiber" -version = "37.0.1" +version = "37.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "781b52cb6e688a6a50b90051b20a87a841c35638a18e309e00fed9daca7e36aa" +checksum = "43fdeb4c50dbbb3ebf01f7e6d270ba4239c8db5ff1e68725386abad2e5250be4" dependencies = [ "anyhow", "cc", "cfg-if", "libc", - "rustix 1.0.5", + "rustix 1.1.2", "wasmtime-internal-asm-macros", "wasmtime-internal-versioned-export-macros", "windows-sys 0.60.2", @@ -11239,21 +11602,21 @@ dependencies = [ [[package]] name = "wasmtime-internal-jit-debug" -version = "37.0.1" +version = "37.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b771527002767c3c84f7edee5255925c1dce5fd41e9de5b46aeaaee6e5242971" +checksum = "4fe059ecd3f572ec2f616f036e5f31a88649a5f16e4838147cb3af6c3b5cedd5" dependencies = [ "cc", - "object 0.37.3", - "rustix 1.0.5", + "object", + "rustix 1.1.2", "wasmtime-internal-versioned-export-macros", ] [[package]] name = "wasmtime-internal-jit-icache-coherence" -version = "37.0.1" +version = "37.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4aea2b284343796fbbe749c36db092b43809762f8b9e46626561a8be4003dd85" +checksum = "4a03f55a9dbfa30f2ed269fa9735c2994b8423461d45c3ca08aa7a103daeff20" dependencies = [ "anyhow", "cfg-if", @@ -11263,37 +11626,37 @@ dependencies = [ [[package]] name = "wasmtime-internal-math" -version = "37.0.1" +version = "37.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a058122e659373c3648a71de03436105f213037d8016bb68550c259d4b37931" +checksum = "ed7f491d2c7f1be3f6e5485ab5a26f26f177860c8b5c16d3ab87df4b24f28e40" dependencies = [ "libm", ] [[package]] name = "wasmtime-internal-slab" -version = "37.0.1" +version = "37.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65cafe64859a9df2b2391bb4cc1139eace115c02ba363e22cfd19eb675282f5a" +checksum = "ce79a933dd9c5fdcc1ce1f6b46e89e72ccb6767619557f0468d97fbfb0475db6" [[package]] name = "wasmtime-internal-unwinder" -version = "37.0.1" +version = "37.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be561ffc6e3dcbd07b49d463af1a325412e58550d1514fbfb6c37e1bf4c80928" +checksum = "b0e12be7ff91e956c6e7cee17654982669493c4aaa861e3536f7b1c22999519d" dependencies = [ "anyhow", "cfg-if", "cranelift-codegen", "log", - "object 0.37.3", + "object", ] [[package]] name = "wasmtime-internal-versioned-export-macros" -version = "37.0.1" +version = "37.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d16a0ea81107fc7e269d504bb586296eaf9c4d79d99aaa4f4135d18bc6fbc86" +checksum = "67d114c747409b6f76ddf86deb2c5976f809baed3eea8fdca493063ea182246b" dependencies = [ "proc-macro2", "quote", @@ -11302,15 +11665,15 @@ dependencies = [ [[package]] name = "wasmtime-internal-winch" -version = "37.0.1" +version = "37.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a99416e4805ffc48b718b5b967d3bda44aa8765c7bfcc6993f8b5819e8427cb6" +checksum = "0dc9d9e984025efce72ec4b90b95790e857f2fef7601c317abedf61226e21585" dependencies = [ "anyhow", "cranelift-codegen", - "gimli 0.32.0", + "gimli", "log", - "object 0.37.3", + "object", "target-lexicon", "wasmparser 0.239.0", "wasmtime-environ", @@ -11320,9 +11683,9 @@ dependencies = [ [[package]] name = "wasmtime-internal-wit-bindgen" -version = "37.0.1" +version = "37.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d04509ae5bfb09b509e22ce83168add9b2a92dc7a902d68f31d391c9b23a36d6" +checksum = "2fb054d6661ef694d1d90e1c01233cb8ef0d7f84b73980709d3facef1373e189" dependencies = [ "anyhow", "bitflags 2.10.0", @@ -11333,9 +11696,9 @@ dependencies = [ [[package]] name = "wasmtime-wasi" -version = "37.0.1" +version = "37.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78179e5f067030bcc032cb4c149bbe92688e3fc9960b9d45eb06c38b817e6b8b" +checksum = "da6617d09fda0be82e11227418e5561c67a8469709215d7c05a9d9f4d2192dc7" dependencies = [ "anyhow", "async-trait", @@ -11350,7 +11713,7 @@ dependencies = [ "futures", "io-extras", "io-lifetimes", - "rustix 1.0.5", + "rustix 1.1.2", "system-interface", "thiserror 2.0.17", "tokio", @@ -11364,18 +11727,18 @@ dependencies = [ [[package]] name = "wasmtime-wasi-http" -version = "37.0.1" +version = "37.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1c3083c447bc7cbeb1128068d3fef0768ff6fb346409a574466aa3e4e458d1e" +checksum = "3822921e191aa0b6aaf7015f12dad4703e54dad0a9b41b68d846c79ea19e7d21" dependencies = [ "anyhow", "async-trait", "bytes", "futures", - "http 1.1.0", + "http 1.3.1", "http-body 1.0.1", "http-body-util", - "hyper 1.5.0", + "hyper 1.7.0", "rustls 0.22.4", "tokio", "tokio-rustls 0.25.0", @@ -11384,14 +11747,14 @@ dependencies = [ "wasmtime", "wasmtime-wasi", "wasmtime-wasi-io", - "webpki-roots", + "webpki-roots 0.26.11", ] [[package]] name = "wasmtime-wasi-io" -version = "37.0.1" +version = "37.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa0974abaf5ec96584ed75928689a95e79b553182939337fa284779cb6b8a4e3" +checksum = "fdca5f5ac3e7814f184f44e49add8e99a3e92bc1ceb45c05ba013b2822b7b705" dependencies = [ "anyhow", "async-trait", @@ -11411,24 +11774,24 @@ dependencies = [ [[package]] name = "wast" -version = "239.0.0" +version = "240.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9139176fe8a2590e0fb174cdcaf373b224cb93c3dde08e4297c1361d2ba1ea5d" +checksum = "b0efe1c93db4ac562b9733e3dca19ed7fc878dba29aef22245acf84f13da4a19" dependencies = [ "bumpalo", "leb128fmt", "memchr", - "unicode-width 0.2.0", - "wasm-encoder 0.239.0", + "unicode-width 0.2.2", + "wasm-encoder 0.240.0", ] [[package]] name = "wat" -version = "1.239.0" +version = "1.240.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e1c941927d34709f255558166f8901a2005f8ab4a9650432e9281b7cc6f3b75" +checksum = "4ec9b6eab7ecd4d639d78515e9ea491c9bacf494aa5eda10823bd35992cf8c1e" dependencies = [ - "wast 239.0.0", + "wast 240.0.0", ] [[package]] @@ -11517,9 +11880,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.72" +version = "0.3.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112" +checksum = "3a1f95c0d03a47f4ae1f7a64643a6bb97465d9b740f0fa8f90ea33915c99a9a1" dependencies = [ "js-sys", "wasm-bindgen", @@ -11537,41 +11900,49 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.26.6" +version = "0.26.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" +dependencies = [ + "webpki-roots 1.0.4", +] + +[[package]] +name = "webpki-roots" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841c67bff177718f1d4dfefde8d8f0e78f9b6589319ba88312f567fc5841a958" +checksum = "b2878ef029c47c6e8cf779119f20fcf52bde7ad42a731b2a304bc221df17571e" dependencies = [ "rustls-pki-types", ] [[package]] name = "which" -version = "7.0.3" +version = "8.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d643ce3fd3e5b54854602a080f34fb10ab75e0b813ee32d00ca2b44fa74762" +checksum = "d3fabb953106c3c8eea8306e4393700d7657561cb43122571b172bbfb7c7ba1d" dependencies = [ - "either", "env_home", - "rustix 1.0.5", + "rustix 1.1.2", "winsafe", ] [[package]] name = "whoami" -version = "1.5.2" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "372d5b87f58ec45c384ba03563b03544dc5fadc3983e434b286913f5b4a9bb6d" +checksum = "5d4a4db5077702ca3015d3d02d74974948aba2ad9e12ab7df718ee64ccd7e97d" dependencies = [ - "redox_syscall", + "libredox", "wasite", "web-sys", ] [[package]] name = "wiggle" -version = "37.0.1" +version = "37.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b35aad501cfca310289a22bdc95c571c15047967b02295a4df56de391b4d90ef" +checksum = "7e45c8d34846d01d20157c00cd61e207e4f4d8889cfc69b45d43e5114834e71e" dependencies = [ "anyhow", "async-trait", @@ -11584,9 +11955,9 @@ dependencies = [ [[package]] name = "wiggle-generate" -version = "37.0.1" +version = "37.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66a1516334f2191ef393f754a8689f0c2193cf304828725b4708d377c6b0a185" +checksum = "772a63dfce3a1bce1cc019720e43603633c5a2cb84291bec77f438ec38b55bf2" dependencies = [ "anyhow", "heck 0.5.0", @@ -11598,9 +11969,9 @@ dependencies = [ [[package]] name = "wiggle-macro" -version = "37.0.1" +version = "37.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c6a0b969afcee961240d696375f29e3c42e6a55e2fcf9a1798f500fe0fdd242" +checksum = "3636c0c0352f54b28f45d1327784176e134009db4230024be6509966c88adf74" dependencies = [ "proc-macro2", "quote", @@ -11626,11 +11997,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.9" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -11641,14 +12012,14 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "winch-codegen" -version = "37.0.1" +version = "37.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20581fd07c028fc1c151cd5c15719da62dfd852502c1751df8a93a0637a86791" +checksum = "61aeea98b13a9d2f537b9aec71a168397aefd5a3faebdc6b3d96ff7df4592e59" dependencies = [ "anyhow", "cranelift-assembler-x64", "cranelift-codegen", - "gimli 0.32.0", + "gimli", "regalloc2", "smallvec", "target-lexicon", @@ -11668,7 +12039,7 @@ dependencies = [ "windows-collections", "windows-core 0.61.2", "windows-future", - "windows-link", + "windows-link 0.1.3", "windows-numerics", ] @@ -11683,24 +12054,28 @@ dependencies = [ [[package]] name = "windows-core" -version = "0.52.0" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" dependencies = [ - "windows-targets 0.52.6", + "windows-implement", + "windows-interface", + "windows-link 0.1.3", + "windows-result 0.3.4", + "windows-strings 0.4.2", ] [[package]] name = "windows-core" -version = "0.61.2" +version = "0.62.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" dependencies = [ "windows-implement", "windows-interface", - "windows-link", - "windows-result 0.3.4", - "windows-strings 0.4.2", + "windows-link 0.2.1", + "windows-result 0.4.1", + "windows-strings 0.5.1", ] [[package]] @@ -11710,15 +12085,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" dependencies = [ "windows-core 0.61.2", - "windows-link", + "windows-link 0.1.3", "windows-threading", ] [[package]] name = "windows-implement" -version = "0.60.0" +version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", @@ -11727,9 +12102,9 @@ dependencies = [ [[package]] name = "windows-interface" -version = "0.59.1" +version = "0.59.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", @@ -11742,6 +12117,12 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + [[package]] name = "windows-numerics" version = "0.2.0" @@ -11749,55 +12130,54 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" dependencies = [ "windows-core 0.61.2", - "windows-link", + "windows-link 0.1.3", ] [[package]] name = "windows-registry" -version = "0.2.0" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" +checksum = "5b8a9ed28765efc97bbc954883f4e6796c33a06546ebafacbabee9696967499e" dependencies = [ - "windows-result 0.2.0", - "windows-strings 0.1.0", - "windows-targets 0.52.6", + "windows-link 0.1.3", + "windows-result 0.3.4", + "windows-strings 0.4.2", ] [[package]] name = "windows-result" -version = "0.2.0" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" dependencies = [ - "windows-targets 0.52.6", + "windows-link 0.1.3", ] [[package]] name = "windows-result" -version = "0.3.4" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" dependencies = [ - "windows-link", + "windows-link 0.2.1", ] [[package]] name = "windows-strings" -version = "0.1.0" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" dependencies = [ - "windows-result 0.2.0", - "windows-targets 0.52.6", + "windows-link 0.1.3", ] [[package]] name = "windows-strings" -version = "0.4.2" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" dependencies = [ - "windows-link", + "windows-link 0.2.1", ] [[package]] @@ -11833,7 +12213,16 @@ version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" dependencies = [ - "windows-targets 0.53.3", + "windows-targets 0.53.5", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link 0.2.1", ] [[package]] @@ -11869,19 +12258,19 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.53.3" +version = "0.53.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" dependencies = [ - "windows-link", - "windows_aarch64_gnullvm 0.53.0", - "windows_aarch64_msvc 0.53.0", - "windows_i686_gnu 0.53.0", - "windows_i686_gnullvm 0.53.0", - "windows_i686_msvc 0.53.0", - "windows_x86_64_gnu 0.53.0", - "windows_x86_64_gnullvm 0.53.0", - "windows_x86_64_msvc 0.53.0", + "windows-link 0.2.1", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", ] [[package]] @@ -11890,7 +12279,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" dependencies = [ - "windows-link", + "windows-link 0.1.3", ] [[package]] @@ -11907,9 +12296,9 @@ checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_gnullvm" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" [[package]] name = "windows_aarch64_msvc" @@ -11925,9 +12314,9 @@ checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_aarch64_msvc" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" [[package]] name = "windows_i686_gnu" @@ -11943,9 +12332,9 @@ checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnu" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" [[package]] name = "windows_i686_gnullvm" @@ -11955,9 +12344,9 @@ checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_gnullvm" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" [[package]] name = "windows_i686_msvc" @@ -11973,9 +12362,9 @@ checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_i686_msvc" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" [[package]] name = "windows_x86_64_gnu" @@ -11991,9 +12380,9 @@ checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnu" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" [[package]] name = "windows_x86_64_gnullvm" @@ -12009,9 +12398,9 @@ checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_gnullvm" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" [[package]] name = "windows_x86_64_msvc" @@ -12027,18 +12416,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "windows_x86_64_msvc" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" - -[[package]] -name = "winnow" -version = "0.6.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" -dependencies = [ - "memchr", -] +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" [[package]] name = "winnow" @@ -12067,22 +12447,19 @@ checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904" [[package]] name = "winx" -version = "0.36.3" +version = "0.36.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9643b83820c0cd246ecabe5fa454dd04ba4fa67996369466d0747472d337346" +checksum = "3f3fd376f71958b862e7afb20cfe5a22830e1963462f3a17f49d82a6c1d1f42d" dependencies = [ "bitflags 2.10.0", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] -name = "wit-bindgen-rt" -version = "0.39.0" +name = "wit-bindgen" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" -dependencies = [ - "bitflags 2.10.0", -] +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" [[package]] name = "wit-component" @@ -12221,17 +12598,11 @@ dependencies = [ "wast 35.0.2", ] -[[package]] -name = "write16" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" - [[package]] name = "writeable" -version = "0.5.5" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" +checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" [[package]] name = "wyz" @@ -12244,13 +12615,12 @@ dependencies = [ [[package]] name = "xattr" -version = "1.3.1" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8da84f1a25939b27f6820d92aed108f83ff920fdf11a7b19366c27c4cda81d4f" +checksum = "32e45ad4206f6d2479085147f02bc2ef834ac85886624a23575ae137c8aa8156" dependencies = [ "libc", - "linux-raw-sys 0.4.14", - "rustix 0.38.40", + "rustix 1.1.2", ] [[package]] @@ -12288,26 +12658,49 @@ checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" [[package]] name = "yoke" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5" +checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" dependencies = [ "serde", "stable_deref_trait", - "yoke-derive", + "yoke-derive 0.7.5", + "zerofrom", +] + +[[package]] +name = "yoke" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" +dependencies = [ + "stable_deref_trait", + "yoke-derive 0.8.1", "zerofrom", ] [[package]] name = "yoke-derive" -version = "0.7.4" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", + "synstructure 0.13.2", +] + +[[package]] +name = "yoke-derive" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" +checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" dependencies = [ "proc-macro2", "quote", "syn 2.0.108", - "synstructure 0.13.1", + "synstructure 0.13.2", ] [[package]] @@ -12327,7 +12720,7 @@ dependencies = [ "async-trait", "blocking", "enumflags2", - "event-listener 5.3.1", + "event-listener 5.4.1", "futures-core", "futures-sink", "futures-util", @@ -12374,19 +12767,18 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.7.35" +version = "0.8.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c" dependencies = [ - "byteorder", "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.35" +version = "0.8.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" dependencies = [ "proc-macro2", "quote", @@ -12395,47 +12787,72 @@ dependencies = [ [[package]] name = "zerofrom" -version = "0.1.4" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" dependencies = [ "zerofrom-derive", ] [[package]] name = "zerofrom-derive" -version = "0.1.4" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", "syn 2.0.108", - "synstructure 0.13.1", + "synstructure 0.13.2", ] [[package]] name = "zeroize" -version = "1.8.1" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "zerotrie" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" +dependencies = [ + "displaydoc", + "yoke 0.8.1", + "zerofrom", +] [[package]] name = "zerovec" -version = "0.10.4" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" dependencies = [ - "yoke", + "yoke 0.8.1", "zerofrom", "zerovec-derive", ] [[package]] name = "zerovec-derive" -version = "0.10.3" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ "proc-macro2", "quote", @@ -12459,27 +12876,27 @@ dependencies = [ [[package]] name = "zstd" -version = "0.13.2" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcf2b778a664581e31e389454a7072dab1647606d44f7feea22cd5abb9c9f3f9" +checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a" dependencies = [ "zstd-safe", ] [[package]] name = "zstd-safe" -version = "7.2.1" +version = "7.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54a3ab4db68cea366acc5c897c7b4d4d1b8994a9cd6e6f841f8964566a419059" +checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d" dependencies = [ "zstd-sys", ] [[package]] name = "zstd-sys" -version = "2.0.13+zstd.1.5.6" +version = "2.0.16+zstd.1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa" +checksum = "91e19ebc2adc8f83e43039e79776e3fda8ca919132d68a1fed6a5faca2683748" dependencies = [ "cc", "pkg-config", diff --git a/Cargo.toml b/Cargo.toml index ccf892d0cb..44890a52cf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -84,6 +84,7 @@ openssl = { version = "0.10" } anyhow = { workspace = true, features = ["backtrace"] } conformance = { path = "tests/conformance-tests" } conformance-tests = { workspace = true } +fake-opentelemetry-collector = "0.26" hex = "0.4" http-body-util = { workspace = true } hyper = { workspace = true } @@ -144,6 +145,10 @@ hyper-util = { version = "0.1", features = ["tokio"] } indexmap = "2" itertools = "0.14" lazy_static = "1.5" +opentelemetry = "0.28" +# The default `reqwest-blocking-client` causes a runtime panic +opentelemetry-otlp = { version = "0.28", default-features = false, features = ["http-proto", "reqwest-client", "logs"]} +opentelemetry_sdk = {version = "0.28", features = ["experimental_metrics_periodicreader_with_async_runtime", "experimental_trace_batch_span_processor_with_async_runtime", "experimental_logs_batch_log_processor_with_async_runtime"]} path-absolutize = "3" pin-project-lite = "0.2.16" quote = "1" @@ -172,6 +177,7 @@ toml_edit = "0.22" tower-service = "0.3.3" tracing = { version = "0.1.41", features = ["log"] } url = "2.5.7" +tracing-opentelemetry = "0.29" walkdir = "2" wasm-encoder = "0.239.0" wasm-metadata = "0.239.0" diff --git a/crates/factor-key-value/Cargo.toml b/crates/factor-key-value/Cargo.toml index 8327737bd1..f0bdd6a2b9 100644 --- a/crates/factor-key-value/Cargo.toml +++ b/crates/factor-key-value/Cargo.toml @@ -8,6 +8,7 @@ edition = { workspace = true } anyhow = { workspace = true } serde = { workspace = true } spin-core = { path = "../core" } +spin-factor-otel = { path = "../factor-otel" } spin-factors = { path = "../factors" } spin-locked-app = { path = "../locked-app" } spin-resource-table = { path = "../table" } diff --git a/crates/factor-key-value/src/host.rs b/crates/factor-key-value/src/host.rs index ada4ece9b2..a7aef7005c 100644 --- a/crates/factor-key-value/src/host.rs +++ b/crates/factor-key-value/src/host.rs @@ -1,6 +1,7 @@ use super::{Cas, SwapError}; use anyhow::{Context, Result}; use spin_core::{async_trait, wasmtime::component::Resource}; +use spin_factor_otel::OtelContext; use spin_resource_table::Table; use spin_telemetry::traces::{self, Blame}; use spin_world::v2::key_value; @@ -49,23 +50,26 @@ pub struct KeyValueDispatch { manager: Arc, stores: Table>, compare_and_swaps: Table>, + otel_context: Option, } impl KeyValueDispatch { pub fn new(allowed_stores: HashSet, manager: Arc) -> Self { - Self::new_with_capacity(allowed_stores, manager, DEFAULT_STORE_TABLE_CAPACITY) + Self::new_with_capacity(allowed_stores, manager, DEFAULT_STORE_TABLE_CAPACITY, None) } pub fn new_with_capacity( allowed_stores: HashSet, manager: Arc, capacity: u32, + otel_context: Option, ) -> Self { Self { allowed_stores, manager, stores: Table::new(capacity), compare_and_swaps: Table::new(capacity), + otel_context, } } @@ -113,6 +117,9 @@ impl key_value::Host for KeyValueDispatch {} impl key_value::HostStore for KeyValueDispatch { #[instrument(name = "spin_key_value.open", skip(self), err, fields(otel.kind = "client", kv.backend=self.manager.summary(&name).unwrap_or("unknown".to_string())))] async fn open(&mut self, name: String) -> Result, Error>> { + if let Some(otel_context) = self.otel_context.as_ref() { + otel_context.reparent_tracing_span() + } Ok(async { if self.allowed_stores.contains(&name) { let store = self.manager.get(&name).await?; @@ -135,6 +142,9 @@ impl key_value::HostStore for KeyValueDispatch { store: Resource, key: String, ) -> Result>, Error>> { + if let Some(otel_context) = self.otel_context.as_ref() { + otel_context.reparent_tracing_span() + } let store = self.get_store(store)?; Ok(store.get(&key).await.map_err(track_error_on_span)) } @@ -146,6 +156,9 @@ impl key_value::HostStore for KeyValueDispatch { key: String, value: Vec, ) -> Result> { + if let Some(otel_context) = self.otel_context.as_ref() { + otel_context.reparent_tracing_span() + } let store = self.get_store(store)?; Ok(store.set(&key, &value).await.map_err(track_error_on_span)) } @@ -156,6 +169,9 @@ impl key_value::HostStore for KeyValueDispatch { store: Resource, key: String, ) -> Result> { + if let Some(otel_context) = self.otel_context.as_ref() { + otel_context.reparent_tracing_span() + } let store = self.get_store(store)?; Ok(store.delete(&key).await.map_err(track_error_on_span)) } @@ -166,6 +182,9 @@ impl key_value::HostStore for KeyValueDispatch { store: Resource, key: String, ) -> Result> { + if let Some(otel_context) = self.otel_context.as_ref() { + otel_context.reparent_tracing_span() + } let store = self.get_store(store)?; Ok(store.exists(&key).await.map_err(track_error_on_span)) } @@ -175,6 +194,9 @@ impl key_value::HostStore for KeyValueDispatch { &mut self, store: Resource, ) -> Result, Error>> { + if let Some(otel_context) = self.otel_context.as_ref() { + otel_context.reparent_tracing_span() + } let store = self.get_store(store)?; Ok(store.get_keys().await.map_err(track_error_on_span)) } diff --git a/crates/factor-key-value/src/lib.rs b/crates/factor-key-value/src/lib.rs index 792ea18b92..62929a75ff 100644 --- a/crates/factor-key-value/src/lib.rs +++ b/crates/factor-key-value/src/lib.rs @@ -8,6 +8,7 @@ use std::{ }; use anyhow::ensure; +use spin_factor_otel::OtelContext; use spin_factors::{ ConfigureAppContext, Factor, FactorData, FactorInstanceBuilder, InitContext, PrepareContext, RuntimeFactors, @@ -87,7 +88,7 @@ impl Factor for KeyValueFactor { fn prepare( &self, - ctx: PrepareContext, + mut ctx: PrepareContext, ) -> anyhow::Result { let app_state = ctx.app_state(); let allowed_stores = app_state @@ -95,9 +96,11 @@ impl Factor for KeyValueFactor { .get(ctx.app_component().id()) .expect("component should be in component_stores") .clone(); + let otel_context = OtelContext::from_prepare_context(&mut ctx)?; Ok(InstanceBuilder { store_manager: app_state.store_manager.clone(), allowed_stores, + otel_context, }) } } @@ -177,6 +180,7 @@ pub struct InstanceBuilder { store_manager: Arc, /// The allowed stores for this component instance. allowed_stores: HashSet, + otel_context: OtelContext, } impl FactorInstanceBuilder for InstanceBuilder { @@ -186,11 +190,13 @@ impl FactorInstanceBuilder for InstanceBuilder { let Self { store_manager, allowed_stores, + otel_context, } = self; Ok(KeyValueDispatch::new_with_capacity( allowed_stores, store_manager, u32::MAX, + Some(otel_context), )) } } diff --git a/crates/factor-llm/Cargo.toml b/crates/factor-llm/Cargo.toml index c43a7bbd6c..61121c6a49 100644 --- a/crates/factor-llm/Cargo.toml +++ b/crates/factor-llm/Cargo.toml @@ -17,6 +17,7 @@ llm-cublas = ["llm", "spin-llm-local/cublas"] anyhow = { workspace = true } async-trait = { workspace = true } serde = { workspace = true } +spin-factor-otel = { path = "../factor-otel" } spin-factors = { path = "../factors" } spin-llm-local = { path = "../llm-local", optional = true } spin-llm-remote-http = { path = "../llm-remote-http" } diff --git a/crates/factor-llm/src/host.rs b/crates/factor-llm/src/host.rs index 63a5525146..61c49b5313 100644 --- a/crates/factor-llm/src/host.rs +++ b/crates/factor-llm/src/host.rs @@ -13,6 +13,8 @@ impl v2::Host for InstanceState { prompt: String, params: Option, ) -> Result { + self.otel_context.reparent_tracing_span(); + if !self.allowed_models.contains(&model) { return Err(access_denied_error(&model)); } @@ -40,6 +42,8 @@ impl v2::Host for InstanceState { model: v1::EmbeddingModel, data: Vec, ) -> Result { + self.otel_context.reparent_tracing_span(); + if !self.allowed_models.contains(&model) { return Err(access_denied_error(&model)); } diff --git a/crates/factor-llm/src/lib.rs b/crates/factor-llm/src/lib.rs index 4f43feac68..b3e5c6a700 100644 --- a/crates/factor-llm/src/lib.rs +++ b/crates/factor-llm/src/lib.rs @@ -5,6 +5,7 @@ use std::collections::{HashMap, HashSet}; use std::sync::Arc; use async_trait::async_trait; +use spin_factor_otel::OtelContext; use spin_factors::{ ConfigureAppContext, Factor, FactorData, PrepareContext, RuntimeFactors, SelfInstanceBuilder, }; @@ -73,7 +74,7 @@ impl Factor for LlmFactor { fn prepare( &self, - ctx: PrepareContext, + mut ctx: PrepareContext, ) -> anyhow::Result { let allowed_models = ctx .app_state() @@ -82,10 +83,12 @@ impl Factor for LlmFactor { .cloned() .unwrap_or_default(); let engine = ctx.app_state().engine.clone(); + let otel_context = OtelContext::from_prepare_context(&mut ctx)?; Ok(InstanceState { engine, allowed_models, + otel_context, }) } } @@ -100,6 +103,7 @@ pub struct AppState { pub struct InstanceState { engine: Arc>, pub allowed_models: Arc>, + otel_context: OtelContext, } /// The runtime configuration for the LLM factor. diff --git a/crates/factor-otel/Cargo.toml b/crates/factor-otel/Cargo.toml new file mode 100644 index 0000000000..1dcdb98c82 --- /dev/null +++ b/crates/factor-otel/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "spin-factor-otel" +version = { workspace = true } +authors = { workspace = true } +edition = { workspace = true } + +[dependencies] +anyhow = { workspace = true } +indexmap = "2.2.6" +opentelemetry = { workspace = true } +opentelemetry_sdk = { workspace = true } +opentelemetry-otlp = { workspace = true } +spin-core = { path = "../core" } +spin-factors = { path = "../factors" } +spin-resource-table = { path = "../table" } +spin-telemetry = { path = "../telemetry" } +spin-world = { path = "../world" } +tracing = { workspace = true } +tracing-opentelemetry = { workspace = true } + +[dev-dependencies] +toml = "0.5" + +[lints] +workspace = true diff --git a/crates/factor-otel/src/host.rs b/crates/factor-otel/src/host.rs new file mode 100644 index 0000000000..8ece27d5b1 --- /dev/null +++ b/crates/factor-otel/src/host.rs @@ -0,0 +1,87 @@ +use crate::InstanceState; +use anyhow::anyhow; +use anyhow::Result; +use opentelemetry::trace::TraceContextExt; +use opentelemetry_sdk::error::OTelSdkError; +use opentelemetry_sdk::metrics::exporter::PushMetricExporter; +use opentelemetry_sdk::trace::SpanProcessor; +use spin_world::wasi; +use tracing_opentelemetry::OpenTelemetrySpanExt; + +impl wasi::otel::tracing::Host for InstanceState { + async fn on_start(&mut self, context: wasi::otel::tracing::SpanContext) -> Result<()> { + let mut state = self.state.write().unwrap(); + + // Before we do anything make sure we track the original host span ID for reparenting + if state.original_host_span_id.is_none() { + state.original_host_span_id = Some( + tracing::Span::current() + .context() + .span() + .span_context() + .span_id(), + ); + } + + // Track the guest spans context in our ordered map + let span_context: opentelemetry::trace::SpanContext = context.into(); + state + .guest_span_contexts + .insert(span_context.span_id(), span_context); + + Ok(()) + } + + async fn on_end(&mut self, span_data: wasi::otel::tracing::SpanData) -> Result<()> { + let mut state = self.state.write().unwrap(); + + let span_context: opentelemetry::trace::SpanContext = span_data.span_context.clone().into(); + let span_id: opentelemetry::trace::SpanId = span_context.span_id(); + + if state.guest_span_contexts.shift_remove(&span_id).is_none() { + Err(anyhow!("Trying to end a span that was not started"))?; + } + + self.span_processor.on_end(span_data.into()); + + Ok(()) + } + + async fn outer_span_context(&mut self) -> Result { + Ok(tracing::Span::current() + .context() + .span() + .span_context() + .clone() + .into()) + } +} + +impl wasi::otel::metrics::Host for InstanceState { + async fn export( + &mut self, + metrics: wasi::otel::metrics::ResourceMetrics, + ) -> spin_core::wasmtime::Result> { + let mut rm: opentelemetry_sdk::metrics::data::ResourceMetrics = metrics.into(); + match self.metric_exporter.export(&mut rm).await { + Ok(_) => Ok(Ok(())), + Err(e) => match e { + OTelSdkError::AlreadyShutdown => { + let msg = "Shutdown has already been invoked"; + tracing::error!(msg); + Ok(Err(msg.to_string())) + } + OTelSdkError::InternalFailure(e) => { + let detailed_msg = format!("Internal failure: {}", e); + tracing::error!(detailed_msg); + Ok(Err("Internal failure.".to_string())) + } + OTelSdkError::Timeout(d) => { + let detailed_msg = format!("Operation timed out after {} seconds", d.as_secs()); + tracing::error!(detailed_msg); + Ok(Err("Operation timed out.".to_string())) + } + }, + } + } +} diff --git a/crates/factor-otel/src/lib.rs b/crates/factor-otel/src/lib.rs new file mode 100644 index 0000000000..c224ce3730 --- /dev/null +++ b/crates/factor-otel/src/lib.rs @@ -0,0 +1,213 @@ +mod host; + +use anyhow::bail; +use indexmap::IndexMap; +use opentelemetry::{ + trace::{SpanContext, SpanId, TraceContextExt}, + Context, +}; +use opentelemetry_otlp::MetricExporter; +use opentelemetry_sdk::{ + resource::{EnvResourceDetector, ResourceDetector, TelemetryResourceDetector}, + runtime::Tokio, + trace::{span_processor_with_async_runtime::BatchSpanProcessor, SpanProcessor}, + Resource, +}; +use spin_factors::{Factor, FactorData, PrepareContext, RuntimeFactors, SelfInstanceBuilder}; +use spin_telemetry::{detector::SpinResourceDetector, env::OtlpProtocol}; +use std::sync::{Arc, RwLock}; +use tracing_opentelemetry::OpenTelemetrySpanExt; + +pub struct OtelFactor { + span_processor: Arc>, + metric_exporter: Arc, +} + +impl Factor for OtelFactor { + type RuntimeConfig = (); + type AppState = (); + type InstanceBuilder = InstanceState; + + fn init(&mut self, ctx: &mut impl spin_factors::InitContext) -> anyhow::Result<()> { + ctx.link_bindings(spin_world::wasi::otel::tracing::add_to_linker::<_, FactorData>)?; + ctx.link_bindings(spin_world::wasi::otel::metrics::add_to_linker::<_, FactorData>)?; + Ok(()) + } + + fn configure_app( + &self, + _ctx: spin_factors::ConfigureAppContext, + ) -> anyhow::Result { + Ok(()) + } + + fn prepare( + &self, + _: spin_factors::PrepareContext, + ) -> anyhow::Result { + Ok(InstanceState { + state: Arc::new(RwLock::new(State { + guest_span_contexts: Default::default(), + original_host_span_id: None, + })), + span_processor: self.span_processor.clone(), + metric_exporter: self.metric_exporter.clone(), + }) + } +} + +impl OtelFactor { + pub fn new() -> anyhow::Result { + // This is a hack b/c we know the version of this crate will be the same as the version of Spin + let spin_version = env!("CARGO_PKG_VERSION").to_string(); + + let resource = Resource::builder() + .with_detectors(&[ + // Set service.name from env OTEL_SERVICE_NAME > env OTEL_RESOURCE_ATTRIBUTES > spin + // Set service.version from Spin metadata + Box::new(SpinResourceDetector::new(spin_version)) as Box, + // Sets fields from env OTEL_RESOURCE_ATTRIBUTES + Box::new(EnvResourceDetector::new()), + // Sets telemetry.sdk{name, language, version} + Box::new(TelemetryResourceDetector), + ]) + .build(); + + // This will configure the exporter based on the OTEL_EXPORTER_* environment variables. + let span_exporter = match OtlpProtocol::traces_protocol_from_env() { + OtlpProtocol::Grpc => opentelemetry_otlp::SpanExporter::builder() + .with_tonic() + .build()?, + OtlpProtocol::HttpProtobuf => opentelemetry_otlp::SpanExporter::builder() + .with_http() + .build()?, + OtlpProtocol::HttpJson => bail!("http/json OTLP protocol is not supported"), + }; + + let mut span_processor = BatchSpanProcessor::builder(span_exporter, Tokio).build(); + + span_processor.set_resource(&resource); + + let metric_exporter = match OtlpProtocol::metrics_protocol_from_env() { + OtlpProtocol::Grpc => opentelemetry_otlp::MetricExporter::builder() + .with_tonic() + .build()?, + OtlpProtocol::HttpProtobuf => opentelemetry_otlp::MetricExporter::builder() + .with_http() + .build()?, + OtlpProtocol::HttpJson => bail!("http/json OTLP protocol is not supported"), + }; + + Ok(Self { + span_processor: Arc::new(span_processor), + metric_exporter: Arc::new(metric_exporter), + }) + } +} + +pub struct InstanceState { + pub(crate) state: Arc>, + pub(crate) span_processor: Arc>, + pub(crate) metric_exporter: Arc, +} + +impl SelfInstanceBuilder for InstanceState {} + +/// Internal state of the OtelFactor instance state. +/// +/// This data lives here rather than directly on InstanceState so that we can have multiple things +/// take Arc references to it. +pub(crate) struct State { + /// An order-preserved mapping between immutable [SpanId]s of guest created spans and their + /// corresponding [SpanContext]. + /// + /// The topmost [SpanId] is the last active span. When a span is ended it is removed from this + /// map (regardless of whether it is the active span) and all other spans are shifted back to + /// retain relative order. + pub(crate) guest_span_contexts: IndexMap, + + /// Id of the last span emitted from within the host before entering the guest. + /// + /// We use this to avoid accidentally reparenting the original host span as a child of a guest + /// span. + pub(crate) original_host_span_id: Option, +} + +/// Manages access to the OtelFactor state for the purpose of maintaining proper span +/// parent/child relationships when WASI Otel spans are being created. +pub struct OtelContext { + pub(crate) state: Option>>, +} + +impl OtelContext { + /// Creates an [`OtelContext`] from a [`PrepareContext`]. + /// + /// If [`RuntimeFactors`] does not contain an [`OtelFactor`], then calling + /// [`OtelContext::reparent_tracing_span`] will be a no-op. + pub fn from_prepare_context( + prepare_context: &mut PrepareContext, + ) -> anyhow::Result { + let state = match prepare_context.instance_builder::() { + Ok(instance_state) => Some(instance_state.state.clone()), + Err(spin_factors::Error::NoSuchFactor(_)) => None, + Err(e) => return Err(e.into()), + }; + Ok(Self { state }) + } + + /// Reparents the current [tracing] span to be a child of the last active guest span. + /// + /// The otel factor enables guests to emit spans that should be part of the same trace as the + /// host is producing for a request. Below is an example trace. A request is made to an app, a + /// guest span is created and then the host is re-entered to fetch a key value. + /// + /// ```text + /// | GET /... _________________________________| + /// | execute_wasm_component foo ___________| + /// | my_guest_span ___________________| + /// | spin_key_value.get | + /// ``` + /// + /// Setting the guest spans parent as the host is enabled through current_span_context. + /// However, the more difficult task is having the host factor spans be children of the guest + /// span. [`OtelContext::reparent_tracing_span`] handles this by reparenting the current span to + /// be a child of the last active guest span (which is tracked internally in the otel factor). + /// + /// Note that if the otel factor is not in your [`RuntimeFactors`] than this is effectively a + /// no-op. + /// + /// This MUST only be called from a factor host implementation function that is instrumented. + /// + /// This MUST be called at the very start of the function before any awaits. + pub fn reparent_tracing_span(&self) { + // If state is None then we want to return early b/c the factor doesn't depend on the + // Otel factor and therefore there is nothing to do + let state = if let Some(state) = self.state.as_ref() { + state.read().unwrap() + } else { + return; + }; + + // If there are no active guest spans then there is nothing to do + let Some((_, active_span_context)) = state.guest_span_contexts.last() else { + return; + }; + + // Ensure that we are not reparenting the original host span + if let Some(original_host_span_id) = state.original_host_span_id { + if tracing::Span::current() + .context() + .span() + .span_context() + .span_id() + .eq(&original_host_span_id) + { + panic!("Incorrectly attempting to reparent the original host span. Likely `reparent_tracing_span` was called in an incorrect location.") + } + } + + // Now reparent the current span to the last active guest span + let parent_context = Context::new().with_remote_span_context(active_span_context.clone()); + tracing::Span::current().set_parent(parent_context); + } +} diff --git a/crates/factor-outbound-http/Cargo.toml b/crates/factor-outbound-http/Cargo.toml index 6e6d14cf01..008d1c6a16 100644 --- a/crates/factor-outbound-http/Cargo.toml +++ b/crates/factor-outbound-http/Cargo.toml @@ -16,6 +16,7 @@ pin-project-lite = { workspace = true } reqwest = { workspace = true, features = ["gzip"] } rustls = { workspace = true } serde = { workspace = true } +spin-factor-otel = { path = "../factor-otel" } spin-factor-outbound-networking = { path = "../factor-outbound-networking" } spin-factors = { path = "../factors" } spin-telemetry = { path = "../telemetry" } diff --git a/crates/factor-outbound-http/src/lib.rs b/crates/factor-outbound-http/src/lib.rs index 094b9a21ef..5a24570a5f 100644 --- a/crates/factor-outbound-http/src/lib.rs +++ b/crates/factor-outbound-http/src/lib.rs @@ -14,6 +14,7 @@ use http::{ }; use intercept::OutboundHttpInterceptor; use runtime_config::RuntimeConfig; +use spin_factor_otel::OtelContext; use spin_factor_outbound_networking::{ config::{allowed_hosts::OutboundAllowedHosts, blocked_networks::BlockedNetworks}, ComponentTlsClientConfigs, OutboundNetworkingFactor, @@ -74,6 +75,7 @@ impl Factor for OutboundHttpFactor { let allowed_hosts = outbound_networking.allowed_hosts(); let blocked_networks = outbound_networking.blocked_networks(); let component_tls_configs = outbound_networking.component_tls_configs(); + let otel_context = OtelContext::from_prepare_context(&mut ctx)?; Ok(InstanceState { wasi_http_ctx: WasiHttpCtx::new(), allowed_hosts, @@ -88,6 +90,7 @@ impl Factor for OutboundHttpFactor { .app_state() .concurrent_outbound_connections_semaphore .clone(), + otel_context, }) } } @@ -114,6 +117,8 @@ pub struct InstanceState { connection_pooling_enabled: bool, /// A semaphore to limit the number of concurrent outbound connections. concurrent_outbound_connections_semaphore: Option>, + /// Manages access to the OtelFactor state. + otel_context: OtelContext, } impl InstanceState { diff --git a/crates/factor-outbound-http/src/spin.rs b/crates/factor-outbound-http/src/spin.rs index 3eb9408320..b4fe9f6d0b 100644 --- a/crates/factor-outbound-http/src/spin.rs +++ b/crates/factor-outbound-http/src/spin.rs @@ -15,6 +15,8 @@ impl spin_http::Host for crate::InstanceState { fields(otel.kind = "client", url.full = Empty, http.request.method = Empty, http.response.status_code = Empty, otel.name = Empty, server.address = Empty, server.port = Empty))] async fn send_request(&mut self, req: Request) -> Result { + self.otel_context.reparent_tracing_span(); + let span = Span::current(); record_request_fields(&span, &req); diff --git a/crates/factor-outbound-mqtt/Cargo.toml b/crates/factor-outbound-mqtt/Cargo.toml index bd5222881c..962b5efb0a 100644 --- a/crates/factor-outbound-mqtt/Cargo.toml +++ b/crates/factor-outbound-mqtt/Cargo.toml @@ -8,6 +8,7 @@ edition = { workspace = true } anyhow = { workspace = true } rumqttc = { version = "0.24", features = ["url"] } spin-core = { path = "../core" } +spin-factor-otel = { path = "../factor-otel" } spin-factor-outbound-networking = { path = "../factor-outbound-networking" } spin-factors = { path = "../factors" } spin-resource-table = { path = "../table" } diff --git a/crates/factor-outbound-mqtt/src/host.rs b/crates/factor-outbound-mqtt/src/host.rs index 28ca42885d..53cb6a9830 100644 --- a/crates/factor-outbound-mqtt/src/host.rs +++ b/crates/factor-outbound-mqtt/src/host.rs @@ -4,6 +4,7 @@ use anyhow::Result; use spin_core::{async_trait, wasmtime::component::Resource}; use spin_factor_outbound_networking::config::allowed_hosts::OutboundAllowedHosts; use spin_world::v2::mqtt::{self as v2, Connection, Error, Qos}; +use spin_factor_otel::OtelContext; use tracing::{instrument, Level}; use crate::ClientCreator; @@ -12,14 +13,20 @@ pub struct InstanceState { allowed_hosts: OutboundAllowedHosts, connections: spin_resource_table::Table>, create_client: Arc, + otel_context: OtelContext, } impl InstanceState { - pub fn new(allowed_hosts: OutboundAllowedHosts, create_client: Arc) -> Self { + pub fn new( + allowed_hosts: OutboundAllowedHosts, + create_client: Arc, + otel_context: OtelContext, + ) -> Self { Self { allowed_hosts, create_client, connections: spin_resource_table::Table::new(1024), + otel_context, } } } @@ -72,6 +79,8 @@ impl v2::HostConnection for InstanceState { password: String, keep_alive_interval: u64, ) -> Result, Error> { + self.otel_context.reparent_tracing_span(); + if !self .is_address_allowed(&address) .await @@ -105,6 +114,8 @@ impl v2::HostConnection for InstanceState { payload: Vec, qos: Qos, ) -> Result<(), Error> { + self.otel_context.reparent_tracing_span(); + let conn = self.get_conn(connection).await.map_err(other_error)?; conn.publish_bytes(topic, qos, payload).await?; diff --git a/crates/factor-outbound-mqtt/src/lib.rs b/crates/factor-outbound-mqtt/src/lib.rs index a5de2696b9..250aa09d5c 100644 --- a/crates/factor-outbound-mqtt/src/lib.rs +++ b/crates/factor-outbound-mqtt/src/lib.rs @@ -7,6 +7,7 @@ use host::other_error; use host::InstanceState; use rumqttc::{AsyncClient, Event, Incoming, Outgoing, QoS}; use spin_core::async_trait; +use spin_factor_otel::OtelContext; use spin_factor_outbound_networking::OutboundNetworkingFactor; use spin_factors::{ ConfigureAppContext, Factor, FactorData, PrepareContext, RuntimeFactors, SelfInstanceBuilder, @@ -50,9 +51,12 @@ impl Factor for OutboundMqttFactor { let allowed_hosts = ctx .instance_builder::()? .allowed_hosts(); + let otel_context = OtelContext::from_prepare_context(&mut ctx)?; + Ok(InstanceState::new( allowed_hosts, self.create_client.clone(), + otel_context, )) } } diff --git a/crates/factor-outbound-mysql/Cargo.toml b/crates/factor-outbound-mysql/Cargo.toml index 4ae73f9fbc..ed6a0b01a0 100644 --- a/crates/factor-outbound-mysql/Cargo.toml +++ b/crates/factor-outbound-mysql/Cargo.toml @@ -14,6 +14,7 @@ mysql_async = { version = "0.35", default-features = false, features = [ "native-tls-tls", ] } spin-core = { path = "../core" } +spin-factor-otel = { path = "../factor-otel" } spin-factor-outbound-networking = { path = "../factor-outbound-networking" } spin-factors = { path = "../factors" } spin-resource-table = { path = "../table" } diff --git a/crates/factor-outbound-mysql/src/host.rs b/crates/factor-outbound-mysql/src/host.rs index e562d4d741..ca113206aa 100644 --- a/crates/factor-outbound-mysql/src/host.rs +++ b/crates/factor-outbound-mysql/src/host.rs @@ -38,6 +38,7 @@ impl v2::Host for InstanceState {} impl v2::HostConnection for InstanceState { #[instrument(name = "spin_outbound_mysql.open", skip(self, address), err(level = Level::INFO), fields(otel.kind = "client", db.system = "mysql", db.address = Empty, server.port = Empty, db.namespace = Empty))] async fn open(&mut self, address: String) -> Result, v2::Error> { + self.otel_context.reparent_tracing_span(); spin_factor_outbound_networking::record_address_fields(&address); if !self @@ -59,6 +60,7 @@ impl v2::HostConnection for InstanceState { statement: String, params: Vec, ) -> Result<(), v2::Error> { + self.otel_context.reparent_tracing_span(); self.get_client(connection) .await? .execute(statement, params) @@ -72,6 +74,7 @@ impl v2::HostConnection for InstanceState { statement: String, params: Vec, ) -> Result { + self.otel_context.reparent_tracing_span(); self.get_client(connection) .await? .query(statement, params) diff --git a/crates/factor-outbound-mysql/src/lib.rs b/crates/factor-outbound-mysql/src/lib.rs index fbe213bf9e..e1bf9aabdb 100644 --- a/crates/factor-outbound-mysql/src/lib.rs +++ b/crates/factor-outbound-mysql/src/lib.rs @@ -3,6 +3,7 @@ mod host; use client::Client; use mysql_async::Conn as MysqlClient; +use spin_factor_otel::OtelContext; use spin_factor_outbound_networking::{ config::allowed_hosts::OutboundAllowedHosts, OutboundNetworkingFactor, }; @@ -39,9 +40,12 @@ impl Factor for OutboundMysqlFactor { let allowed_hosts = ctx .instance_builder::()? .allowed_hosts(); + let otel_context = OtelContext::from_prepare_context(&mut ctx)?; + Ok(InstanceState { allowed_hosts, connections: Default::default(), + otel_context, }) } } @@ -63,6 +67,7 @@ impl OutboundMysqlFactor { pub struct InstanceState { allowed_hosts: OutboundAllowedHosts, connections: spin_resource_table::Table, + otel_context: OtelContext, } impl SelfInstanceBuilder for InstanceState {} diff --git a/crates/factor-outbound-pg/Cargo.toml b/crates/factor-outbound-pg/Cargo.toml index 6b8f32bb4c..6436d55268 100644 --- a/crates/factor-outbound-pg/Cargo.toml +++ b/crates/factor-outbound-pg/Cargo.toml @@ -16,6 +16,7 @@ postgres_range = "0.11" rust_decimal = { version = "1.37", features = ["db-tokio-postgres"] } serde_json = { workspace = true } spin-core = { path = "../core" } +spin-factor-otel = { path = "../factor-otel" } spin-factor-outbound-networking = { path = "../factor-outbound-networking" } spin-factors = { path = "../factors" } spin-resource-table = { path = "../table" } diff --git a/crates/factor-outbound-pg/src/host.rs b/crates/factor-outbound-pg/src/host.rs index 111df6f998..81dda9bbe6 100644 --- a/crates/factor-outbound-pg/src/host.rs +++ b/crates/factor-outbound-pg/src/host.rs @@ -219,6 +219,7 @@ impl v2::Host for InstanceState {} impl v2::HostConnection for InstanceState { #[instrument(name = "spin_outbound_pg.open", skip(self, address), err(level = Level::INFO), fields(otel.kind = "client", db.system = "postgresql", db.address = Empty, server.port = Empty, db.namespace = Empty))] async fn open(&mut self, address: String) -> Result, v2::Error> { + self.otel_context.reparent_tracing_span(); spin_factor_outbound_networking::record_address_fields(&address); if !self @@ -240,6 +241,8 @@ impl v2::HostConnection for InstanceState { statement: String, params: Vec, ) -> Result { + self.otel_context.reparent_tracing_span(); + Ok(self .get_client(connection) .await? @@ -254,6 +257,7 @@ impl v2::HostConnection for InstanceState { statement: String, params: Vec, ) -> Result { + self.otel_context.reparent_tracing_span(); Ok(self .get_client(connection) .await? diff --git a/crates/factor-outbound-pg/src/lib.rs b/crates/factor-outbound-pg/src/lib.rs index b3a433946e..a793271fef 100644 --- a/crates/factor-outbound-pg/src/lib.rs +++ b/crates/factor-outbound-pg/src/lib.rs @@ -4,7 +4,9 @@ mod types; use std::sync::Arc; +use client::Client; use client::ClientFactory; +use spin_factor_otel::OtelContext; use spin_factor_outbound_networking::{ config::allowed_hosts::OutboundAllowedHosts, OutboundNetworkingFactor, }; @@ -48,10 +50,13 @@ impl Factor for OutboundPgFactor { let allowed_hosts = ctx .instance_builder::()? .allowed_hosts(); + let otel_context = OtelContext::from_prepare_context(&mut ctx)?; + Ok(InstanceState { allowed_hosts, client_factory: ctx.app_state().clone(), connections: Default::default(), + otel_context, }) } } @@ -74,6 +79,7 @@ pub struct InstanceState { allowed_hosts: OutboundAllowedHosts, client_factory: Arc, connections: spin_resource_table::Table, + otel_context: OtelContext, } impl SelfInstanceBuilder for InstanceState {} diff --git a/crates/factor-outbound-redis/Cargo.toml b/crates/factor-outbound-redis/Cargo.toml index 73f5d86017..6518459d79 100644 --- a/crates/factor-outbound-redis/Cargo.toml +++ b/crates/factor-outbound-redis/Cargo.toml @@ -8,6 +8,7 @@ edition = { workspace = true } anyhow = { workspace = true } redis = { workspace = true , features = ["tokio-comp", "tokio-native-tls-comp", "aio"] } spin-core = { path = "../core" } +spin-factor-otel = { path = "../factor-otel" } spin-factor-outbound-networking = { path = "../factor-outbound-networking" } spin-factors = { path = "../factors" } spin-resource-table = { path = "../table" } diff --git a/crates/factor-outbound-redis/src/host.rs b/crates/factor-outbound-redis/src/host.rs index 5dcb0d3475..ac1c817ebb 100644 --- a/crates/factor-outbound-redis/src/host.rs +++ b/crates/factor-outbound-redis/src/host.rs @@ -5,6 +5,7 @@ use redis::io::AsyncDNSResolver; use redis::AsyncConnectionConfig; use redis::{aio::MultiplexedConnection, AsyncCommands, FromRedisValue, Value}; use spin_core::wasmtime::component::Resource; +use spin_factor_otel::OtelContext; use spin_factor_outbound_networking::config::allowed_hosts::OutboundAllowedHosts; use spin_factor_outbound_networking::config::blocked_networks::BlockedNetworks; use spin_world::v1::{redis as v1, redis_types}; @@ -18,6 +19,7 @@ pub struct InstanceState { pub allowed_hosts: OutboundAllowedHosts, pub blocked_networks: BlockedNetworks, pub connections: spin_resource_table::Table, + pub otel_context: OtelContext, } impl InstanceState { @@ -63,8 +65,7 @@ impl v2::Host for crate::InstanceState { impl v2::HostConnection for crate::InstanceState { #[instrument(name = "spin_outbound_redis.open_connection", skip(self, address), err(level = Level::INFO), fields(otel.kind = "client", db.system = "redis", db.address = Empty, server.port = Empty, db.namespace = Empty))] async fn open(&mut self, address: String) -> Result, Error> { - spin_factor_outbound_networking::record_address_fields(&address); - + self.otel_context.reparent_tracing_span(); if !self .is_address_allowed(&address) .await @@ -83,6 +84,8 @@ impl v2::HostConnection for crate::InstanceState { channel: String, payload: Vec, ) -> Result<(), Error> { + self.otel_context.reparent_tracing_span(); + let conn = self.get_conn(connection).await.map_err(other_error)?; // The `let () =` syntax is needed to suppress a warning when the result type is inferred. // You can read more about the issue here: @@ -99,6 +102,8 @@ impl v2::HostConnection for crate::InstanceState { connection: Resource, key: String, ) -> Result>, Error> { + self.otel_context.reparent_tracing_span(); + let conn = self.get_conn(connection).await.map_err(other_error)?; let value = conn.get(&key).await.map_err(other_error)?; Ok(value) @@ -111,6 +116,8 @@ impl v2::HostConnection for crate::InstanceState { key: String, value: Vec, ) -> Result<(), Error> { + self.otel_context.reparent_tracing_span(); + let conn = self.get_conn(connection).await.map_err(other_error)?; // The `let () =` syntax is needed to suppress a warning when the result type is inferred. // You can read more about the issue here: @@ -124,6 +131,8 @@ impl v2::HostConnection for crate::InstanceState { connection: Resource, key: String, ) -> Result { + self.otel_context.reparent_tracing_span(); + let conn = self.get_conn(connection).await.map_err(other_error)?; let value = conn.incr(&key, 1).await.map_err(other_error)?; Ok(value) @@ -135,6 +144,8 @@ impl v2::HostConnection for crate::InstanceState { connection: Resource, keys: Vec, ) -> Result { + self.otel_context.reparent_tracing_span(); + let conn = self.get_conn(connection).await.map_err(other_error)?; let value = conn.del(&keys).await.map_err(other_error)?; Ok(value) @@ -147,6 +158,8 @@ impl v2::HostConnection for crate::InstanceState { key: String, values: Vec, ) -> Result { + self.otel_context.reparent_tracing_span(); + let conn = self.get_conn(connection).await.map_err(other_error)?; let value = conn.sadd(&key, &values).await.map_err(|e| { if e.kind() == redis::ErrorKind::TypeError { @@ -164,6 +177,8 @@ impl v2::HostConnection for crate::InstanceState { connection: Resource, key: String, ) -> Result, Error> { + self.otel_context.reparent_tracing_span(); + let conn = self.get_conn(connection).await.map_err(other_error)?; let value = conn.smembers(&key).await.map_err(other_error)?; Ok(value) @@ -176,6 +191,8 @@ impl v2::HostConnection for crate::InstanceState { key: String, values: Vec, ) -> Result { + self.otel_context.reparent_tracing_span(); + let conn = self.get_conn(connection).await.map_err(other_error)?; let value = conn.srem(&key, &values).await.map_err(other_error)?; Ok(value) @@ -188,6 +205,8 @@ impl v2::HostConnection for crate::InstanceState { command: String, arguments: Vec, ) -> Result, Error> { + self.otel_context.reparent_tracing_span(); + let conn = self.get_conn(connection).await?; let mut cmd = redis::cmd(&command); arguments.iter().for_each(|value| match value { diff --git a/crates/factor-outbound-redis/src/lib.rs b/crates/factor-outbound-redis/src/lib.rs index 731321618a..09bf410931 100644 --- a/crates/factor-outbound-redis/src/lib.rs +++ b/crates/factor-outbound-redis/src/lib.rs @@ -1,6 +1,7 @@ mod host; use host::InstanceState; +use spin_factor_otel::OtelContext; use spin_factor_outbound_networking::OutboundNetworkingFactor; use spin_factors::{ anyhow, ConfigureAppContext, Factor, FactorData, PrepareContext, RuntimeFactors, @@ -41,11 +42,14 @@ impl Factor for OutboundRedisFactor { &self, mut ctx: PrepareContext, ) -> anyhow::Result { + let otel_context = OtelContext::from_prepare_context(&mut ctx)?; let outbound_networking = ctx.instance_builder::()?; + Ok(InstanceState { allowed_hosts: outbound_networking.allowed_hosts(), blocked_networks: outbound_networking.blocked_networks(), connections: spin_resource_table::Table::new(1024), + otel_context, }) } } diff --git a/crates/factor-sqlite/Cargo.toml b/crates/factor-sqlite/Cargo.toml index ee945ed4fa..98a6325ad7 100644 --- a/crates/factor-sqlite/Cargo.toml +++ b/crates/factor-sqlite/Cargo.toml @@ -10,6 +10,7 @@ rust-version.workspace = true [dependencies] async-trait = { workspace = true } +spin-factor-otel = { path = "../factor-otel" } spin-factors = { path = "../factors" } spin-locked-app = { path = "../locked-app" } spin-resource-table = { path = "../table" } diff --git a/crates/factor-sqlite/src/host.rs b/crates/factor-sqlite/src/host.rs index 953ee70cc4..e6ed819a54 100644 --- a/crates/factor-sqlite/src/host.rs +++ b/crates/factor-sqlite/src/host.rs @@ -1,6 +1,7 @@ use std::collections::{HashMap, HashSet}; use std::sync::Arc; +use spin_factor_otel::OtelContext; use spin_factors::wasmtime::component::Resource; use spin_factors::{anyhow, SelfInstanceBuilder}; use spin_world::spin::sqlite::sqlite as v3; @@ -17,6 +18,7 @@ pub struct InstanceState { connections: spin_resource_table::Table>, /// A map from database label to connection creators. connection_creators: HashMap>, + otel_context: OtelContext, } impl InstanceState { @@ -26,11 +28,13 @@ impl InstanceState { pub fn new( allowed_databases: Arc>, connection_creators: HashMap>, + otel_context: OtelContext, ) -> Self { Self { allowed_databases, connections: spin_resource_table::Table::new(256), connection_creators, + otel_context, } } @@ -154,6 +158,7 @@ impl v2::Host for InstanceState { impl v2::HostConnection for InstanceState { #[instrument(name = "spin_sqlite.open", skip(self), err(level = Level::INFO), fields(otel.kind = "client", db.system = "sqlite", sqlite.backend = Empty))] async fn open(&mut self, database: String) -> Result, v2::Error> { + self.otel_context.reparent_tracing_span(); self.open_impl(database).await.map_err(to_v2_error) } @@ -164,6 +169,7 @@ impl v2::HostConnection for InstanceState { query: String, parameters: Vec, ) -> Result { + self.otel_context.reparent_tracing_span(); self.execute_impl( connection, query, diff --git a/crates/factor-sqlite/src/lib.rs b/crates/factor-sqlite/src/lib.rs index 9fafdb796a..ae3b4686e0 100644 --- a/crates/factor-sqlite/src/lib.rs +++ b/crates/factor-sqlite/src/lib.rs @@ -8,6 +8,7 @@ use host::InstanceState; use async_trait::async_trait; use spin_factors::{anyhow, Factor, FactorData}; +use spin_factor_otel::OtelContext; use spin_locked_app::MetadataKey; use spin_world::spin::sqlite::sqlite as v3; use spin_world::v1::sqlite as v1; @@ -74,7 +75,7 @@ impl Factor for SqliteFactor { fn prepare( &self, - ctx: spin_factors::PrepareContext, + mut ctx: spin_factors::PrepareContext, ) -> spin_factors::anyhow::Result { let allowed_databases = ctx .app_state() @@ -82,9 +83,11 @@ impl Factor for SqliteFactor { .get(ctx.app_component().id()) .cloned() .unwrap_or_default(); + let otel_context = OtelContext::from_prepare_context(&mut ctx)?; Ok(InstanceState::new( allowed_databases, ctx.app_state().connection_creators.clone(), + otel_context, )) } } diff --git a/crates/factor-variables/Cargo.toml b/crates/factor-variables/Cargo.toml index 4a1a76f83e..c24c6ebb7c 100644 --- a/crates/factor-variables/Cargo.toml +++ b/crates/factor-variables/Cargo.toml @@ -6,6 +6,7 @@ edition = { workspace = true } [dependencies] spin-expressions = { path = "../expressions" } +spin-factor-otel = { path = "../factor-otel" } spin-factors = { path = "../factors" } spin-telemetry = { path = "../telemetry" } spin-world = { path = "../world" } diff --git a/crates/factor-variables/src/host.rs b/crates/factor-variables/src/host.rs index 31706af0ca..784cebd280 100644 --- a/crates/factor-variables/src/host.rs +++ b/crates/factor-variables/src/host.rs @@ -8,6 +8,7 @@ use crate::InstanceState; impl variables::Host for InstanceState { #[instrument(name = "spin_variables.get", skip(self), fields(otel.kind = "client"))] async fn get(&mut self, key: String) -> Result { + self.otel_context.reparent_tracing_span(); let key = spin_expressions::Key::new(&key).map_err(expressions_to_variables_err)?; self.expression_resolver .resolve(&self.component_id, key) diff --git a/crates/factor-variables/src/lib.rs b/crates/factor-variables/src/lib.rs index b75824b9ba..43d489ecae 100644 --- a/crates/factor-variables/src/lib.rs +++ b/crates/factor-variables/src/lib.rs @@ -5,6 +5,7 @@ use std::sync::Arc; use runtime_config::RuntimeConfig; use spin_expressions::{ProviderResolver as ExpressionResolver, Template}; +use spin_factor_otel::OtelContext; use spin_factors::{ anyhow, ConfigureAppContext, Factor, FactorData, InitContext, PrepareContext, RuntimeFactors, SelfInstanceBuilder, @@ -62,13 +63,15 @@ impl Factor for VariablesFactor { fn prepare( &self, - ctx: PrepareContext, + mut ctx: PrepareContext, ) -> anyhow::Result { let component_id = ctx.app_component().id().to_string(); let expression_resolver = ctx.app_state().expression_resolver.clone(); + let otel_context = OtelContext::from_prepare_context(&mut ctx)?; Ok(InstanceState { component_id, expression_resolver, + otel_context, }) } } @@ -94,6 +97,7 @@ impl AppState { pub struct InstanceState { component_id: String, expression_resolver: Arc, + otel_context: OtelContext, } impl InstanceState { diff --git a/crates/runtime-config/Cargo.toml b/crates/runtime-config/Cargo.toml index 5a8aa05ad0..1b08cda8f7 100644 --- a/crates/runtime-config/Cargo.toml +++ b/crates/runtime-config/Cargo.toml @@ -15,6 +15,7 @@ spin-common = { path = "../common" } spin-expressions = { path = "../expressions" } spin-factor-key-value = { path = "../factor-key-value" } spin-factor-llm = { path = "../factor-llm" } +spin-factor-otel = { path = "../factor-otel" } spin-factor-outbound-http = { path = "../factor-outbound-http" } spin-factor-outbound-mqtt = { path = "../factor-outbound-mqtt" } spin-factor-outbound-mysql = { path = "../factor-outbound-mysql" } diff --git a/crates/runtime-config/src/lib.rs b/crates/runtime-config/src/lib.rs index 4c0d6f4b1f..fedd1b1512 100644 --- a/crates/runtime-config/src/lib.rs +++ b/crates/runtime-config/src/lib.rs @@ -5,6 +5,7 @@ use spin_common::ui::quoted_path; use spin_factor_key_value::runtime_config::spin::{self as key_value}; use spin_factor_key_value::KeyValueFactor; use spin_factor_llm::{spin as llm, LlmFactor}; +use spin_factor_otel::OtelFactor; use spin_factor_outbound_http::OutboundHttpFactor; use spin_factor_outbound_mqtt::OutboundMqttFactor; use spin_factor_outbound_mysql::OutboundMysqlFactor; @@ -398,6 +399,12 @@ impl FactorRuntimeConfigSource for TomlRuntimeConfigSource<'_, '_> } } +impl FactorRuntimeConfigSource for TomlRuntimeConfigSource<'_, '_> { + fn get_runtime_config(&mut self) -> anyhow::Result> { + Ok(None) + } +} + impl RuntimeConfigSourceFinalizer for TomlRuntimeConfigSource<'_, '_> { fn finalize(&mut self) -> anyhow::Result<()> { Ok(self.toml.validate_all_keys_used()?) diff --git a/crates/runtime-factors/Cargo.toml b/crates/runtime-factors/Cargo.toml index 257c3f36fa..4e36fccca2 100644 --- a/crates/runtime-factors/Cargo.toml +++ b/crates/runtime-factors/Cargo.toml @@ -19,6 +19,7 @@ clap = { workspace = true, features = ["derive", "env"] } spin-common = { path = "../common" } spin-factor-key-value = { path = "../factor-key-value" } spin-factor-llm = { path = "../factor-llm" } +spin-factor-otel = { path = "../factor-otel" } spin-factor-outbound-http = { path = "../factor-outbound-http" } spin-factor-outbound-mqtt = { path = "../factor-outbound-mqtt" } spin-factor-outbound-mysql = { path = "../factor-outbound-mysql" } diff --git a/crates/runtime-factors/src/lib.rs b/crates/runtime-factors/src/lib.rs index 4e2ef09d02..b1865e444c 100644 --- a/crates/runtime-factors/src/lib.rs +++ b/crates/runtime-factors/src/lib.rs @@ -10,6 +10,7 @@ use anyhow::Context as _; use spin_common::arg_parser::parse_kv; use spin_factor_key_value::KeyValueFactor; use spin_factor_llm::LlmFactor; +use spin_factor_otel::OtelFactor; use spin_factor_outbound_http::OutboundHttpFactor; use spin_factor_outbound_mqtt::{NetworkedMqttClient, OutboundMqttFactor}; use spin_factor_outbound_mysql::OutboundMysqlFactor; @@ -25,6 +26,7 @@ use spin_variables_static::VariableSource; #[derive(RuntimeFactors)] pub struct TriggerFactors { + pub otel: OtelFactor, pub wasi: WasiFactor, pub variables: VariablesFactor, pub key_value: KeyValueFactor, @@ -45,6 +47,7 @@ impl TriggerFactors { allow_transient_writes: bool, ) -> anyhow::Result { Ok(Self { + otel: OtelFactor::new()?, wasi: wasi_factor(working_dir, allow_transient_writes), variables: VariablesFactor::default(), key_value: KeyValueFactor::new(), diff --git a/crates/telemetry/Cargo.toml b/crates/telemetry/Cargo.toml index bf5079ac37..0ef7d9150f 100644 --- a/crates/telemetry/Cargo.toml +++ b/crates/telemetry/Cargo.toml @@ -10,11 +10,11 @@ http0 = { version = "0.2.9", package = "http" } http1 = { version = "1.0.0", package = "http" } opentelemetry = { version = "0.28", features = ["metrics", "trace", "logs"] } opentelemetry-appender-tracing = "0.28" -opentelemetry-otlp = { version = "0.28", features = ["grpc-tonic"] } -opentelemetry_sdk = { version = "0.28", features = ["rt-tokio", "spec_unstable_logs_enabled", "metrics"] } +opentelemetry-otlp = { workspace = true, features = ["grpc-tonic"] } +opentelemetry_sdk = { workspace = true, features = ["rt-tokio", "spec_unstable_logs_enabled", "metrics"] } terminal = { path = "../terminal" } tracing = { workspace = true } -tracing-opentelemetry = { version = "0.29", default-features = false, features = ["metrics"] } +tracing-opentelemetry = { workspace = true, default-features = false, features = ["metrics"] } tracing-subscriber = { version = "0.3", default-features = false, features = ["smallvec", "fmt", "ansi", "std", "env-filter", "json", "registry"] } [features] diff --git a/crates/telemetry/src/env.rs b/crates/telemetry/src/env.rs index 5786e236df..487aad6227 100644 --- a/crates/telemetry/src/env.rs +++ b/crates/telemetry/src/env.rs @@ -19,7 +19,7 @@ const SPIN_DISABLE_LOG_TO_TRACING: &str = "SPIN_DISABLE_LOG_TO_TRACING"; /// - `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` /// /// Note that this is overridden if OTEL_SDK_DISABLED is set and not empty. -pub(crate) fn otel_tracing_enabled() -> bool { +pub fn otel_tracing_enabled() -> bool { any_vars_set(&[ OTEL_EXPORTER_OTLP_ENDPOINT, OTEL_EXPORTER_OTLP_TRACES_ENDPOINT, @@ -33,7 +33,7 @@ pub(crate) fn otel_tracing_enabled() -> bool { /// - `OTEL_EXPORTER_OTLP_METRICS_ENDPOINT` /// /// Note that this is overridden if OTEL_SDK_DISABLED is set and not empty. -pub(crate) fn otel_metrics_enabled() -> bool { +pub fn otel_metrics_enabled() -> bool { any_vars_set(&[ OTEL_EXPORTER_OTLP_ENDPOINT, OTEL_EXPORTER_OTLP_METRICS_ENDPOINT, @@ -47,7 +47,7 @@ pub(crate) fn otel_metrics_enabled() -> bool { /// - `OTEL_EXPORTER_OTLP_LOGS_ENDPOINT` /// /// Note that this is overridden if OTEL_SDK_DISABLED is set and not empty. -pub(crate) fn otel_logs_enabled() -> bool { +pub fn otel_logs_enabled() -> bool { any_vars_set(&[ OTEL_EXPORTER_OTLP_ENDPOINT, OTEL_EXPORTER_OTLP_LOGS_ENDPOINT, @@ -59,7 +59,7 @@ pub(crate) fn otel_logs_enabled() -> bool { /// /// It is considered disabled if the environment variable `SPIN_DISABLED_LOG_TO_TRACING` is set and not /// empty. By default the features is enabled. -pub(crate) fn spin_disable_log_to_tracing() -> bool { +pub fn spin_disable_log_to_tracing() -> bool { any_vars_set(&[SPIN_DISABLE_LOG_TO_TRACING]) } @@ -72,13 +72,13 @@ fn any_vars_set(enabling_vars: &[&str]) -> bool { /// Returns a boolean indicating if the OTEL SDK should be disabled for all signals. /// /// It is considered disabled if the environment variable `OTEL_SDK_DISABLED` is set and not empty. -pub(crate) fn otel_sdk_disabled() -> bool { +pub fn otel_sdk_disabled() -> bool { std::env::var_os(OTEL_SDK_DISABLED).is_some_and(|val| !val.is_empty()) } /// The protocol to use for OTLP exporter. #[derive(Debug)] -pub(crate) enum OtlpProtocol { +pub enum OtlpProtocol { Grpc, HttpProtobuf, HttpJson, @@ -86,7 +86,7 @@ pub(crate) enum OtlpProtocol { impl OtlpProtocol { /// Returns the protocol to be used for exporting traces as defined by the environment. - pub(crate) fn traces_protocol_from_env() -> Self { + pub fn traces_protocol_from_env() -> Self { Self::protocol_from_env( std::env::var(OTEL_EXPORTER_OTLP_TRACES_PROTOCOL), std::env::var(OTEL_EXPORTER_OTLP_PROTOCOL), @@ -94,7 +94,7 @@ impl OtlpProtocol { } /// Returns the protocol to be used for exporting metrics as defined by the environment. - pub(crate) fn metrics_protocol_from_env() -> Self { + pub fn metrics_protocol_from_env() -> Self { Self::protocol_from_env( std::env::var(OTEL_EXPORTER_OTLP_METRICS_PROTOCOL), std::env::var(OTEL_EXPORTER_OTLP_PROTOCOL), @@ -102,7 +102,7 @@ impl OtlpProtocol { } /// Returns the protocol to be used for exporting logs as defined by the environment. - pub(crate) fn logs_protocol_from_env() -> Self { + pub fn logs_protocol_from_env() -> Self { Self::protocol_from_env( std::env::var(OTEL_EXPORTER_OTLP_LOGS_PROTOCOL), std::env::var(OTEL_EXPORTER_OTLP_PROTOCOL), diff --git a/crates/telemetry/src/lib.rs b/crates/telemetry/src/lib.rs index 4c5c99074e..dd1343e13d 100644 --- a/crates/telemetry/src/lib.rs +++ b/crates/telemetry/src/lib.rs @@ -9,7 +9,7 @@ use tracing_subscriber::{fmt, prelude::*, registry, EnvFilter, Layer}; mod alert_in_dev; pub mod detector; -mod env; +pub mod env; pub mod logs; pub mod metrics; mod propagation; @@ -53,6 +53,15 @@ pub use propagation::inject_trace_context; /// spin_telemetry::metrics::monotonic_counter!(spin.metric_name = 1, metric_attribute = "value"); /// ``` pub fn init(spin_version: String) -> anyhow::Result<()> { + // This filter globally filters out spans produced by wasi_http so that they don't conflict with + // the behaviour of the wasi-otel factor. + let wasi_http_trace_filter = tracing_subscriber::filter::filter_fn(|metadata| { + if metadata.is_span() && metadata.name() == "wit-bindgen export" { + return false; + } + true + }); + // This layer will print all tracing library log messages to stderr. let fmt_layer = fmt::layer() .with_writer(std::io::stderr) @@ -91,6 +100,7 @@ pub fn init(spin_version: String) -> anyhow::Result<()> { // Build a registry subscriber with the layers we want to use. registry() + .with(wasi_http_trace_filter) .with(otel_tracing_layer) .with(otel_metrics_layer) .with(fmt_layer) diff --git a/crates/telemetry/src/logs.rs b/crates/telemetry/src/logs.rs index f87857bb70..deb0166389 100644 --- a/crates/telemetry/src/logs.rs +++ b/crates/telemetry/src/logs.rs @@ -3,8 +3,9 @@ use std::{ascii::escape_default, sync::OnceLock}; use anyhow::bail; use opentelemetry::logs::{LogRecord, Logger, LoggerProvider}; use opentelemetry_sdk::{ - logs::{BatchConfigBuilder, BatchLogProcessor, SdkLogger}, + logs::{log_processor_with_async_runtime::BatchLogProcessor, BatchConfigBuilder, SdkLogger}, resource::{EnvResourceDetector, ResourceDetector, TelemetryResourceDetector}, + runtime::Tokio, Resource, }; @@ -97,7 +98,7 @@ pub(crate) fn init_otel_logging_backend(spin_version: String) -> anyhow::Result< let provider = opentelemetry_sdk::logs::SdkLoggerProvider::builder() .with_resource(resource) .with_log_processor( - BatchLogProcessor::builder(exporter) + BatchLogProcessor::builder(exporter, Tokio) .with_batch_config(BatchConfigBuilder::default().build()) .build(), ) diff --git a/crates/telemetry/src/metrics.rs b/crates/telemetry/src/metrics.rs index 2dc2ed811c..9c76090d62 100644 --- a/crates/telemetry/src/metrics.rs +++ b/crates/telemetry/src/metrics.rs @@ -1,8 +1,9 @@ use anyhow::{bail, Result}; use opentelemetry::global; use opentelemetry_sdk::{ - metrics::{PeriodicReader, SdkMeterProvider}, + metrics::{periodic_reader_with_async_runtime::PeriodicReader, SdkMeterProvider}, resource::{EnvResourceDetector, ResourceDetector, TelemetryResourceDetector}, + runtime::Tokio, Resource, }; use tracing::Subscriber; @@ -45,7 +46,7 @@ pub(crate) fn otel_metrics_layer LookupSpan<'span>>( OtlpProtocol::HttpJson => bail!("http/json OTLP protocol is not supported"), }; - let reader = PeriodicReader::builder(exporter).build(); + let reader = PeriodicReader::builder(exporter, Tokio).build(); let meter_provider = SdkMeterProvider::builder() .with_reader(reader) .with_resource(resource) diff --git a/crates/telemetry/src/traces.rs b/crates/telemetry/src/traces.rs index fdccd4b44a..0b9f92f020 100644 --- a/crates/telemetry/src/traces.rs +++ b/crates/telemetry/src/traces.rs @@ -2,6 +2,7 @@ use anyhow::bail; use opentelemetry::{global, trace::TracerProvider}; use opentelemetry_sdk::{ resource::{EnvResourceDetector, ResourceDetector, TelemetryResourceDetector}, + runtime::Tokio, Resource, }; use tracing::Subscriber; @@ -42,7 +43,11 @@ pub(crate) fn otel_tracing_layer LookupSpan<'span>>( OtlpProtocol::HttpJson => bail!("http/json OTLP protocol is not supported"), }; - let span_processor = opentelemetry_sdk::trace::BatchSpanProcessor::builder(exporter).build(); + let span_processor = + opentelemetry_sdk::trace::span_processor_with_async_runtime::BatchSpanProcessor::builder( + exporter, Tokio, + ) + .build(); let tracer_provider = opentelemetry_sdk::trace::SdkTracerProvider::builder() .with_resource(resource) diff --git a/crates/trigger-http/Cargo.toml b/crates/trigger-http/Cargo.toml index 62637df8d3..0774fc3dbf 100644 --- a/crates/trigger-http/Cargo.toml +++ b/crates/trigger-http/Cargo.toml @@ -32,6 +32,7 @@ spin-http = { path = "../http" } spin-telemetry = { path = "../telemetry" } spin-trigger = { path = "../trigger" } spin-world = { path = "../world" } +spin-factor-otel = { path = "../factor-otel" } terminal = { path = "../terminal" } tokio = { workspace = true, features = ["full"] } tokio-rustls = { workspace = true } diff --git a/crates/trigger-http/src/wasi.rs b/crates/trigger-http/src/wasi.rs index f506f08591..1116face6a 100644 --- a/crates/trigger-http/src/wasi.rs +++ b/crates/trigger-http/src/wasi.rs @@ -107,6 +107,7 @@ impl HttpExecutor for WasiHttpExecutor<'_> { HandlerType::Wagi(_) => unreachable!("should have used WagiExecutor instead"), }; + let span = tracing::debug_span!("execute_wasi"); let handle = task::spawn( async move { let result = match handler { diff --git a/crates/world/Cargo.toml b/crates/world/Cargo.toml index fd4763100d..4508fb7e6a 100644 --- a/crates/world/Cargo.toml +++ b/crates/world/Cargo.toml @@ -5,5 +5,8 @@ authors = { workspace = true } edition = { workspace = true } [dependencies] +anyhow = { workspace = true } async-trait = { workspace = true } +opentelemetry = { workspace = true } +opentelemetry_sdk = { workspace = true } wasmtime = { workspace = true } diff --git a/crates/world/src/conversions.rs b/crates/world/src/conversions.rs index 8177b623b2..2362ab8954 100644 --- a/crates/world/src/conversions.rs +++ b/crates/world/src/conversions.rs @@ -553,3 +553,495 @@ mod llm { } } } + +mod otel { + use super::*; + use opentelemetry::StringValue; + use opentelemetry_sdk::trace::{SpanEvents, SpanLinks}; + use std::borrow::Cow; + use std::time::{Duration, SystemTime, UNIX_EPOCH}; + use wasi::clocks0_2_0::wall_clock; + + impl From + for opentelemetry_sdk::metrics::data::ResourceMetrics + { + fn from(value: wasi::otel::metrics::ResourceMetrics) -> Self { + Self { + resource: value.resource.into(), + scope_metrics: value.scope_metrics.into_iter().map(Into::into).collect(), + } + } + } + + impl From for opentelemetry_sdk::Resource { + fn from(value: wasi::otel::metrics::Resource) -> Self { + let attributes: Vec = + value.attributes.into_iter().map(Into::into).collect(); + let schema_url: Option = value.schema_url.into(); + + match schema_url { + Some(url) => opentelemetry_sdk::resource::Resource::builder() + .with_schema_url(attributes, url) + .build(), + None => opentelemetry_sdk::resource::Resource::builder() + .with_attributes(attributes) + .build(), + } + } + } + + impl From for opentelemetry_sdk::metrics::data::ScopeMetrics { + fn from(value: wasi::otel::metrics::ScopeMetrics) -> Self { + Self { + scope: value.scope.into(), + metrics: value.metrics.into_iter().map(Into::into).collect(), + } + } + } + + impl From for opentelemetry_sdk::metrics::data::Metric { + fn from(value: wasi::otel::metrics::Metric) -> Self { + Self { + name: Cow::Owned(value.name), + description: Cow::Owned(value.description), + unit: Cow::Owned(value.unit), + data: value.data.into(), + } + } + } + + /// Converts a Wasi exemplar to an OTel exemplar + macro_rules! exemplars_to_otel { + ( + $wasi_exemplar_list:expr, + $exemplar_type:ty + ) => { + $wasi_exemplar_list + .iter() + .map(|e| { + let span_id: [u8; 8] = e + .span_id + .as_bytes() + .try_into() + .expect("Span ID is longer than 8 bytes"); + let trace_id: [u8; 16] = e + .trace_id + .as_bytes() + .try_into() + .expect("Trace ID is longer than 16 bytes"); + opentelemetry_sdk::metrics::data::Exemplar::<$exemplar_type> { + filtered_attributes: e + .filtered_attributes + .to_owned() + .into_iter() + .map(Into::into) + .collect(), + time: e.time.into(), + value: e.value.into(), + span_id, + trace_id, + } + }) + .collect() + }; + } + + /// Converts a WASI Gauge to an OTel Gauge + macro_rules! wasi_gauge_to_otel { + ($gauge:expr, $number_type:ty) => { + Box::new(opentelemetry_sdk::metrics::data::Gauge { + data_points: $gauge + .data_points + .iter() + .map(|dp| opentelemetry_sdk::metrics::data::GaugeDataPoint { + attributes: dp.attributes.iter().map(Into::into).collect(), + value: dp.value.into(), + exemplars: exemplars_to_otel!(dp.exemplars, $number_type), + }) + .collect(), + start_time: match $gauge.start_time { + Some(t) => Some(t.into()), + None => None, + }, + time: $gauge.time.into(), + }) + }; + } + + /// Converts a WASI Sum to an OTel Sum + macro_rules! wasi_sum_to_otel { + ($sum:expr, $number_type:ty) => { + Box::new(opentelemetry_sdk::metrics::data::Sum { + data_points: $sum + .data_points + .iter() + .map(|dp| opentelemetry_sdk::metrics::data::SumDataPoint { + attributes: dp.attributes.iter().map(Into::into).collect(), + exemplars: exemplars_to_otel!(dp.exemplars, $number_type), + value: dp.value.into(), + }) + .collect(), + start_time: $sum.start_time.into(), + time: $sum.time.into(), + temporality: $sum.temporality.into(), + is_monotonic: $sum.is_monotonic, + }) + }; + } + + /// Converts a WASI Histogram to an OTel Histogram + macro_rules! wasi_histogram_to_otel { + ($histogram:expr, $number_type:ty) => { + Box::new(opentelemetry_sdk::metrics::data::Histogram { + data_points: $histogram + .data_points + .iter() + .map(|dp| opentelemetry_sdk::metrics::data::HistogramDataPoint { + attributes: dp.attributes.iter().map(Into::into).collect(), + bounds: dp.bounds.to_owned(), + bucket_counts: dp.bucket_counts.to_owned(), + exemplars: exemplars_to_otel!(dp.exemplars, $number_type), + count: dp.count, + max: match dp.max { + Some(m) => Some(m.into()), + None => None, + }, + min: match dp.min { + Some(m) => Some(m.into()), + None => None, + }, + sum: dp.sum.into(), + }) + .collect(), + start_time: $histogram.start_time.into(), + time: $histogram.time.into(), + temporality: $histogram.temporality.into(), + }) + }; + } + + /// Converts a WASI ExponentialHistogram to an OTel ExponentialHistogram + macro_rules! wasi_exponential_histogram_to_otel { + ($histogram:expr, $number_type:ty) => { + Box::new(opentelemetry_sdk::metrics::data::ExponentialHistogram { + data_points: $histogram + .data_points + .iter() + .map( + |dp| opentelemetry_sdk::metrics::data::ExponentialHistogramDataPoint { + attributes: dp.attributes.iter().map(Into::into).collect(), + exemplars: exemplars_to_otel!(dp.exemplars, $number_type), + count: dp.count as usize, + max: match dp.max { + Some(m) => Some(m.into()), + None => None, + }, + min: match dp.min { + Some(m) => Some(m.into()), + None => None, + }, + sum: dp.sum.into(), + scale: dp.scale, + zero_count: dp.zero_count, + positive_bucket: dp.positive_bucket.to_owned().into(), + negative_bucket: dp.negative_bucket.to_owned().into(), + zero_threshold: dp.zero_threshold, + }, + ) + .collect(), + start_time: $histogram.start_time.into(), + time: $histogram.time.into(), + temporality: $histogram.temporality.into(), + }) + }; + } + + impl From + for Box + { + fn from(value: wasi::otel::metrics::MetricData) -> Self { + match value { + wasi::otel::metrics::MetricData::F64Sum(s) => wasi_sum_to_otel!(s, f64), + wasi::otel::metrics::MetricData::S64Sum(s) => wasi_sum_to_otel!(s, i64), + wasi::otel::metrics::MetricData::U64Sum(s) => wasi_sum_to_otel!(s, u64), + wasi::otel::metrics::MetricData::F64Gauge(g) => wasi_gauge_to_otel!(g, f64), + wasi::otel::metrics::MetricData::S64Gauge(g) => wasi_gauge_to_otel!(g, i64), + wasi::otel::metrics::MetricData::U64Gauge(g) => wasi_gauge_to_otel!(g, u64), + wasi::otel::metrics::MetricData::F64Histogram(h) => wasi_histogram_to_otel!(h, f64), + wasi::otel::metrics::MetricData::S64Histogram(h) => wasi_histogram_to_otel!(h, i64), + wasi::otel::metrics::MetricData::U64Histogram(h) => wasi_histogram_to_otel!(h, u64), + wasi::otel::metrics::MetricData::F64ExponentialHistogram(h) => { + wasi_exponential_histogram_to_otel!(h, f64) + } + wasi::otel::metrics::MetricData::S64ExponentialHistogram(h) => { + wasi_exponential_histogram_to_otel!(h, i64) + } + wasi::otel::metrics::MetricData::U64ExponentialHistogram(h) => { + wasi_exponential_histogram_to_otel!(h, u64) + } + } + } + } + + impl From for f64 { + fn from(value: wasi::otel::metrics::MetricNumber) -> Self { + match value { + wasi::otel::metrics::MetricNumber::F64(n) => n, + _ => panic!("error converting WASI MetricNumber to f64"), + } + } + } + + impl From for u64 { + fn from(value: wasi::otel::metrics::MetricNumber) -> Self { + match value { + wasi::otel::metrics::MetricNumber::U64(n) => n, + _ => panic!("error converting WASI MetricNumber to u64"), + } + } + } + + impl From for i64 { + fn from(value: wasi::otel::metrics::MetricNumber) -> Self { + match value { + wasi::otel::metrics::MetricNumber::S64(n) => n, + _ => panic!("error converting WASI MetricNumber to i64"), + } + } + } + + impl From + for opentelemetry_sdk::metrics::data::ExponentialBucket + { + fn from(value: wasi::otel::metrics::ExponentialBucket) -> Self { + Self { + offset: value.offset, + counts: value.counts, + } + } + } + + impl From for opentelemetry_sdk::metrics::Temporality { + fn from(value: wasi::otel::metrics::Temporality) -> Self { + use opentelemetry_sdk::metrics::Temporality; + match value { + wasi::otel::metrics::Temporality::Cumulative => Temporality::Cumulative, + wasi::otel::metrics::Temporality::Delta => Temporality::Delta, + wasi::otel::metrics::Temporality::LowMemory => Temporality::LowMemory, + } + } + } + + impl From for opentelemetry_sdk::trace::SpanData { + fn from(value: wasi::otel::tracing::SpanData) -> Self { + let mut span_events = SpanEvents::default(); + span_events.events = value.events.into_iter().map(Into::into).collect(); + span_events.dropped_count = value.dropped_events; + let mut span_links = SpanLinks::default(); + span_links.links = value.links.into_iter().map(Into::into).collect(); + span_links.dropped_count = value.dropped_links; + Self { + span_context: value.span_context.into(), + parent_span_id: opentelemetry::trace::SpanId::from_hex(&value.parent_span_id) + .unwrap_or(opentelemetry::trace::SpanId::INVALID), + span_kind: value.span_kind.into(), + name: value.name.into(), + start_time: value.start_time.into(), + end_time: value.end_time.into(), + attributes: value.attributes.into_iter().map(Into::into).collect(), + dropped_attributes_count: value.dropped_attributes, + events: span_events, + links: span_links, + status: value.status.into(), + instrumentation_scope: value.instrumentation_scope.into(), + } + } + } + + impl From for opentelemetry::trace::SpanContext { + fn from(sc: wasi::otel::tracing::SpanContext) -> Self { + let trace_id = opentelemetry::trace::TraceId::from_hex(&sc.trace_id) + .unwrap_or(opentelemetry::trace::TraceId::INVALID); + let span_id = opentelemetry::trace::SpanId::from_hex(&sc.span_id) + .unwrap_or(opentelemetry::trace::SpanId::INVALID); + let trace_state = opentelemetry::trace::TraceState::from_key_value(sc.trace_state) + .unwrap_or_else(|_| opentelemetry::trace::TraceState::default()); + Self::new( + trace_id, + span_id, + sc.trace_flags.into(), + sc.is_remote, + trace_state, + ) + } + } + + impl From for wasi::otel::tracing::SpanContext { + fn from(sc: opentelemetry::trace::SpanContext) -> Self { + Self { + trace_id: format!("{:x}", sc.trace_id()), + span_id: format!("{:x}", sc.span_id()), + trace_flags: sc.trace_flags().into(), + is_remote: sc.is_remote(), + trace_state: sc + .trace_state() + .header() + .split(',') + .filter_map(|s| { + if let Some((key, value)) = s.split_once('=') { + Some((key.to_string(), value.to_string())) + } else { + None + } + }) + .collect(), + } + } + } + + impl From for opentelemetry::trace::TraceFlags { + fn from(flags: wasi::otel::tracing::TraceFlags) -> Self { + Self::new(flags.as_array()[0] as u8) + } + } + + impl From for wasi::otel::tracing::TraceFlags { + fn from(flags: opentelemetry::trace::TraceFlags) -> Self { + if flags.is_sampled() { + wasi::otel::tracing::TraceFlags::SAMPLED + } else { + wasi::otel::tracing::TraceFlags::empty() + } + } + } + + impl From for opentelemetry::trace::SpanKind { + fn from(kind: wasi::otel::tracing::SpanKind) -> Self { + match kind { + wasi::otel::tracing::SpanKind::Client => opentelemetry::trace::SpanKind::Client, + wasi::otel::tracing::SpanKind::Server => opentelemetry::trace::SpanKind::Server, + wasi::otel::tracing::SpanKind::Producer => opentelemetry::trace::SpanKind::Producer, + wasi::otel::tracing::SpanKind::Consumer => opentelemetry::trace::SpanKind::Consumer, + wasi::otel::tracing::SpanKind::Internal => opentelemetry::trace::SpanKind::Internal, + } + } + } + + impl From for opentelemetry::KeyValue { + fn from(kv: wasi::otel::tracing::KeyValue) -> Self { + opentelemetry::KeyValue::new(kv.key, kv.value) + } + } + + impl From<&wasi::otel::tracing::KeyValue> for opentelemetry::KeyValue { + fn from(kv: &wasi::otel::tracing::KeyValue) -> Self { + opentelemetry::KeyValue::new(kv.key.to_owned(), kv.value.to_owned()) + } + } + + impl From for opentelemetry::Value { + fn from(value: wasi::otel::types::Value) -> Self { + match value { + wasi::otel::types::Value::String(v) => v.into(), + wasi::otel::types::Value::Bool(v) => v.into(), + wasi::otel::types::Value::F64(v) => v.into(), + wasi::otel::types::Value::S64(v) => v.into(), + wasi::otel::types::Value::StringArray(v) => opentelemetry::Value::Array( + v.into_iter() + .map(StringValue::from) + .collect::>() + .into(), + ), + wasi::otel::types::Value::BoolArray(v) => opentelemetry::Value::Array(v.into()), + wasi::otel::types::Value::F64Array(v) => opentelemetry::Value::Array(v.into()), + wasi::otel::types::Value::S64Array(v) => opentelemetry::Value::Array(v.into()), + } + } + } + + impl From for opentelemetry::trace::Event { + fn from(event: wasi::otel::tracing::Event) -> Self { + Self::new( + event.name, + event.time.into(), + event.attributes.into_iter().map(Into::into).collect(), + 0, + ) + } + } + + impl From for opentelemetry::trace::Link { + fn from(link: wasi::otel::tracing::Link) -> Self { + Self::new( + link.span_context.into(), + link.attributes.into_iter().map(Into::into).collect(), + 0, + ) + } + } + + impl From for opentelemetry::trace::Status { + fn from(status: wasi::otel::tracing::Status) -> Self { + match status { + wasi::otel::tracing::Status::Unset => Self::Unset, + wasi::otel::tracing::Status::Ok => Self::Ok, + wasi::otel::tracing::Status::Error(s) => Self::Error { + description: s.into(), + }, + } + } + } + + impl From for opentelemetry::InstrumentationScope { + fn from(value: wasi::otel::tracing::InstrumentationScope) -> Self { + let builder = Self::builder(value.name) + .with_attributes(value.attributes.into_iter().map(Into::into)); + match (value.version, value.schema_url) { + (Some(version), Some(schema_url)) => builder + .with_version(version) + .with_schema_url(schema_url) + .build(), + (Some(version), None) => builder.with_version(version).build(), + (None, Some(schema_url)) => builder.with_schema_url(schema_url).build(), + (None, None) => builder.build(), + } + } + } + + impl From for SystemTime { + fn from(timestamp: wall_clock::Datetime) -> Self { + UNIX_EPOCH + + Duration::from_secs(timestamp.seconds) + + Duration::from_nanos(timestamp.nanoseconds as u64) + } + } + + mod test { + #[test] + fn trace_flags() { + let flags = opentelemetry::trace::TraceFlags::SAMPLED; + let flags2 = crate::wasi::otel::tracing::TraceFlags::from(flags); + let flags3 = opentelemetry::trace::TraceFlags::from(flags2); + assert_eq!(flags, flags3); + } + + #[test] + fn span_context() { + let sc = opentelemetry::trace::SpanContext::new( + opentelemetry::trace::TraceId::from_hex("4fb34cb4484029f7881399b149e41e98") + .unwrap(), + opentelemetry::trace::SpanId::from_hex("9ffd58d3cd4dd90b").unwrap(), + opentelemetry::trace::TraceFlags::SAMPLED, + false, + opentelemetry::trace::TraceState::from_key_value(vec![ + ("foo", "bar"), + ("baz", "qux"), + ]) + .unwrap(), + ); + let sc2 = crate::wasi::otel::tracing::SpanContext::from(sc.clone()); + let sc3 = opentelemetry::trace::SpanContext::from(sc2); + assert_eq!(sc, sc3); + } + } +} diff --git a/tests/integration.rs b/tests/integration.rs index 3d89810cc6..1f00a42f70 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -1,6 +1,7 @@ -mod testcases; +pub mod testcases; mod integration_tests { + use anyhow::Context; use sha2::Digest; use std::collections::HashMap; use test_environment::{ @@ -9,13 +10,12 @@ mod integration_tests { }; use testing_framework::runtimes::{spin_cli::SpinConfig, SpinAppType}; - use super::testcases::{ + pub use super::testcases::{ assert_spin_request, bootstap_env, http_smoke_test_template, run_test, spin_binary, }; - use anyhow::Context; - /// Helper macro to assert that a condition is true eventually #[cfg(feature = "extern-dependencies-tests")] + /// Helper macro to assert that a condition is true eventually macro_rules! assert_eventually { ($e:expr, $t:expr) => { let mut i = 0; @@ -1676,3 +1676,432 @@ route = "/..." Ok(()) } } + +mod otel_integration_tests { + use fake_opentelemetry_collector::FakeCollectorServer; + use std::time::Duration; + use test_environment::{ + http::{Method, Request, Response}, + services::ServicesConfig, + }; + use testing_framework::runtimes::{spin_cli::SpinConfig, SpinAppType}; + + use crate::testcases::run_test_inited; + + use super::testcases::{assert_spin_request, spin_binary}; + + #[test] + // Test that basic otel tracing and inbound/outbound context propagation works + fn otel_smoke_test() -> anyhow::Result<()> { + let rt = tokio::runtime::Runtime::new()?; + let mut collector = rt + .block_on(FakeCollectorServer::start()) + .expect("fake collector server should start"); + let collector_endpoint = collector.endpoint().clone(); + + run_test_inited( + "otel-smoke-test", + SpinConfig { + binary_path: spin_binary(), + spin_up_args: Vec::new(), + app_type: SpinAppType::Http, + }, + ServicesConfig::none(), + |env| { + env.set_env_var("OTEL_EXPORTER_OTLP_TRACES_ENDPOINT", collector_endpoint); + env.set_env_var("OTEL_EXPORTER_OTLP_TRACES_PROTOCOL", "grpc"); + env.set_env_var("OTEL_BSP_SCHEDULE_DELAY", "5"); + Ok(()) + }, + move |env| { + let spin = env.runtime_mut(); + assert_spin_request(spin, Request::new(Method::Get, "/one"), Response::new(200))?; + + let spans = rt.block_on(collector.exported_spans(5, Duration::from_secs(5))); + + assert_eq!(spans.len(), 5); + + // They're all part of the same trace which implies context propagation is working + assert!(spans + .iter() + .map(|s| s.trace_id.clone()) + .all(|t| t == spans[0].trace_id)); + + Ok(()) + }, + )?; + + Ok(()) + } + + #[test] + fn wasi_otel_nested_spans() -> anyhow::Result<()> { + let rt = tokio::runtime::Runtime::new()?; + let mut collector = rt + .block_on(FakeCollectorServer::start()) + .expect("fake collector server should start"); + let collector_endpoint = collector.endpoint().clone(); + + run_test_inited( + "wasi-otel-tracing", + SpinConfig { + binary_path: spin_binary(), + spin_up_args: Vec::new(), + app_type: SpinAppType::Http, + }, + ServicesConfig::none(), + |env| { + env.set_env_var("OTEL_EXPORTER_OTLP_TRACES_ENDPOINT", collector_endpoint); + env.set_env_var("OTEL_EXPORTER_OTLP_TRACES_PROTOCOL", "grpc"); + env.set_env_var("OTEL_BSP_SCHEDULE_DELAY", "5"); + Ok(()) + }, + move |env| { + let spin = env.runtime_mut(); + assert_spin_request( + spin, + Request::new(Method::Get, "/nested-spans"), + Response::new(200), + )?; + + let spans = rt.block_on(collector.exported_spans(4, Duration::from_secs(5))); + + assert_eq!(spans.len(), 4); + + let handle_request_span = spans + .iter() + .find(|s| s.name == "GET /...") + .expect("'GET /...' span should exist"); + let exec_component_span = spans + .iter() + .find(|s| s.name == "execute_wasm_component wasi-otel-tracing") + .expect("'execute_wasm_component wasi-otel-tracing' span should exist"); + let outer_span = spans + .iter() + .find(|s| s.name == "outer_func") + .expect("'outer_func' span should exist"); + let inner_span = spans + .iter() + .find(|s| s.name == "inner_func") + .expect("'inner_func' span should exist"); + + assert!( + handle_request_span.trace_id == exec_component_span.trace_id + && exec_component_span.trace_id == outer_span.trace_id + && outer_span.trace_id == inner_span.trace_id + ); + assert_eq!( + exec_component_span.parent_span_id, + handle_request_span.span_id + ); + assert_eq!(outer_span.parent_span_id, exec_component_span.span_id); + assert_eq!(inner_span.parent_span_id, outer_span.span_id); + + Ok(()) + }, + )?; + + Ok(()) + } + + #[test] + fn wasi_otel_setting_attributes() -> anyhow::Result<()> { + let rt = tokio::runtime::Runtime::new()?; + let mut collector = rt + .block_on(FakeCollectorServer::start()) + .expect("fake collector server should start"); + let collector_endpoint = collector.endpoint().clone(); + + run_test_inited( + "wasi-otel-tracing", + SpinConfig { + binary_path: spin_binary(), + spin_up_args: Vec::new(), + app_type: SpinAppType::Http, + }, + ServicesConfig::none(), + |env| { + env.set_env_var("OTEL_EXPORTER_OTLP_TRACES_ENDPOINT", collector_endpoint); + env.set_env_var("OTEL_EXPORTER_OTLP_TRACES_PROTOCOL", "grpc"); + env.set_env_var("OTEL_BSP_SCHEDULE_DELAY", "5"); + Ok(()) + }, + move |env| { + let spin = env.runtime_mut(); + assert_spin_request( + spin, + Request::new(Method::Get, "/setting-attributes"), + Response::new(200), + )?; + + let spans = rt.block_on(collector.exported_spans(3, Duration::from_secs(5))); + + assert_eq!(spans.len(), 3); + + let attr_span = spans + .iter() + .find(|s| s.name == "setting_attributes") + .expect("'setting_attributes' span should exist"); + + // There are some other attributes already set on the span + assert_eq!(attr_span.attributes.len(), 2); + + assert_eq!( + attr_span + .attributes + .get("foo") + .expect("'foo' attribute should exist"), + "Some(AnyValue { value: Some(StringValue(\"baz\")) })" + ); + assert_eq!( + attr_span.attributes.get("qux").expect("'qux' attribute should exist"), + "Some(AnyValue { value: Some(ArrayValue(ArrayValue { values: [AnyValue { value: Some(StringValue(\"qaz\")) }, AnyValue { value: Some(StringValue(\"thud\")) }] })) })" + ); + + Ok(()) + }, + )?; + + Ok(()) + } + + #[test] + fn wasi_otel_host_guest_host() -> anyhow::Result<()> { + let rt = tokio::runtime::Runtime::new()?; + let mut collector = rt + .block_on(FakeCollectorServer::start()) + .expect("fake collector server should start"); + let collector_endpoint = collector.endpoint().clone(); + + run_test_inited( + "wasi-otel-tracing", + SpinConfig { + binary_path: spin_binary(), + spin_up_args: Vec::new(), + app_type: SpinAppType::Http, + }, + ServicesConfig::none(), + |env| { + env.set_env_var("OTEL_EXPORTER_OTLP_TRACES_ENDPOINT", collector_endpoint); + env.set_env_var("OTEL_EXPORTER_OTLP_TRACES_PROTOCOL", "grpc"); + env.set_env_var("OTEL_BSP_SCHEDULE_DELAY", "5"); + Ok(()) + }, + move |env| { + let spin = env.runtime_mut(); + assert_spin_request( + spin, + Request::new(Method::Get, "/host-guest-host"), + Response::new(200), + )?; + + let spans = rt.block_on(collector.exported_spans(4, Duration::from_secs(5))); + + assert_eq!(spans.len(), 4); + + assert!(spans + .iter() + .map(|s| s.trace_id.clone()) + .all(|t| t == spans[0].trace_id)); + + let exec_component_span = spans + .iter() + .find(|s| s.name == "execute_wasm_component wasi-otel-tracing") + .expect("'execute_wasm_component wasi-otel-tracing' span should exist"); + let guest_span = spans + .iter() + .find(|s| s.name == "guest") + .expect("'guest' span should exist"); + let get_span = spans + .iter() + .find(|s| s.name == "GET") + .expect("'GET' span should exist"); + + assert_eq!(guest_span.parent_span_id, exec_component_span.span_id); + assert_eq!(get_span.parent_span_id, guest_span.span_id); + + Ok(()) + }, + )?; + + Ok(()) + } + + #[test] + fn wasi_otel_events() -> anyhow::Result<()> { + let rt = tokio::runtime::Runtime::new()?; + let mut collector = rt + .block_on(FakeCollectorServer::start()) + .expect("fake collector server should start"); + let collector_endpoint = collector.endpoint().clone(); + + run_test_inited( + "wasi-otel-tracing", + SpinConfig { + binary_path: spin_binary(), + spin_up_args: Vec::new(), + app_type: SpinAppType::Http, + }, + ServicesConfig::none(), + |env| { + env.set_env_var("OTEL_EXPORTER_OTLP_TRACES_ENDPOINT", collector_endpoint); + env.set_env_var("OTEL_EXPORTER_OTLP_TRACES_PROTOCOL", "grpc"); + env.set_env_var("OTEL_BSP_SCHEDULE_DELAY", "5"); + Ok(()) + }, + move |env| { + let spin = env.runtime_mut(); + assert_spin_request( + spin, + Request::new(Method::Get, "/events"), + Response::new(200), + )?; + + let spans = rt.block_on(collector.exported_spans(3, Duration::from_secs(5))); + + assert_eq!(spans.len(), 3); + + let event_span = spans + .iter() + .find(|s| s.name == "events") + .expect("'events' span should exist"); + + let events = event_span.events.clone(); + assert_eq!(events.len(), 3); + + let basic_event = events + .iter() + .find(|e| e.name == "basic-event") + .expect("'basic' event should exist"); + let event_with_attributes = events + .iter() + .find(|e| e.name == "event-with-attributes") + .expect("'event_with_attributes' event should exist"); + let event_with_timestamp = events + .iter() + .find(|e| e.name == "event-with-timestamp") + .expect("'event_with_timestamp' event should exist"); + + assert!(basic_event.time_unix_nano < event_with_attributes.time_unix_nano); + assert_eq!(event_with_attributes.attributes.len(), 1); + assert!(event_with_attributes.time_unix_nano < event_with_timestamp.time_unix_nano); + + Ok(()) + }, + )?; + + Ok(()) + } + + #[test] + fn wasi_otel_links() -> anyhow::Result<()> { + let rt = tokio::runtime::Runtime::new()?; + let mut collector = rt + .block_on(FakeCollectorServer::start()) + .expect("fake collector server should start"); + let collector_endpoint = collector.endpoint().clone(); + + run_test_inited( + "wasi-otel-tracing", + SpinConfig { + binary_path: spin_binary(), + spin_up_args: Vec::new(), + app_type: SpinAppType::Http, + }, + ServicesConfig::none(), + |env| { + env.set_env_var("OTEL_EXPORTER_OTLP_TRACES_ENDPOINT", collector_endpoint); + env.set_env_var("OTEL_EXPORTER_OTLP_TRACES_PROTOCOL", "grpc"); + env.set_env_var("OTEL_BSP_SCHEDULE_DELAY", "5"); + Ok(()) + }, + move |env| { + let spin = env.runtime_mut(); + assert_spin_request( + spin, + Request::new(Method::Get, "/links"), + Response::new(200), + )?; + + let spans = rt.block_on(collector.exported_spans(4, Duration::from_secs(5))); + + assert_eq!(spans.len(), 4); + + let first_span = spans + .iter() + .find(|s| s.name == "first") + .expect("'first' span should exist"); + let second_span = spans + .iter() + .find(|s| s.name == "second") + .expect("'second' span should exist"); + + assert_eq!(first_span.links.len(), 0); + assert_eq!(second_span.links.len(), 1); + assert_eq!( + second_span.links.first().unwrap().span_id, + first_span.span_id + ); + assert_eq!(second_span.links.first().unwrap().attributes.len(), 1); + + Ok(()) + }, + )?; + + Ok(()) + } + + #[test] + fn wasi_otel_root_span() -> anyhow::Result<()> { + let rt = tokio::runtime::Runtime::new()?; + let mut collector = rt + .block_on(FakeCollectorServer::start()) + .expect("fake collector server should start"); + let collector_endpoint = collector.endpoint().clone(); + + run_test_inited( + "wasi-otel-tracing", + SpinConfig { + binary_path: spin_binary(), + spin_up_args: Vec::new(), + app_type: SpinAppType::Http, + }, + ServicesConfig::none(), + |env| { + env.set_env_var("OTEL_EXPORTER_OTLP_TRACES_ENDPOINT", collector_endpoint); + env.set_env_var("OTEL_EXPORTER_OTLP_TRACES_PROTOCOL", "grpc"); + env.set_env_var("OTEL_BSP_SCHEDULE_DELAY", "5"); + Ok(()) + }, + move |env| { + let spin = env.runtime_mut(); + assert_spin_request( + spin, + Request::new(Method::Get, "/root-span"), + Response::new(200), + )?; + + let spans = rt.block_on(collector.exported_spans(7, Duration::from_secs(5))); + + assert_eq!(spans.len(), 4); + + let root_span = spans + .iter() + .find(|s| s.name == "root") + .expect("'root' span should exist"); + let request_span = spans + .iter() + .find(|s| s.name == "GET") + .expect("'GET' span should exist"); + + assert_eq!(root_span.trace_id, request_span.trace_id); + assert_eq!(root_span.span_id, request_span.parent_span_id); + assert_eq!(root_span.parent_span_id, "".to_string()); + + Ok(()) + }, + )?; + + Ok(()) + } +} diff --git a/tests/test-components/components/Cargo.lock b/tests/test-components/components/Cargo.lock index 6f6bbff2ba..44ed4f0b48 100644 --- a/tests/test-components/components/Cargo.lock +++ b/tests/test-components/components/Cargo.lock @@ -2,6 +2,18 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "ahash" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + [[package]] name = "ai" version = "0.1.0" @@ -21,9 +33,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.99" +version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" [[package]] name = "arrayvec" @@ -33,20 +45,20 @@ checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "async-trait" -version = "0.1.77" +version = "0.1.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.108", ] [[package]] name = "autocfg" -version = "1.1.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "base64" @@ -56,9 +68,9 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "bitflags" -version = "2.4.1" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" [[package]] name = "block-buffer" @@ -83,15 +95,15 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.5.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" [[package]] name = "cc" -version = "1.2.40" +version = "1.2.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1d05d92f4b1fd76aad469d46cdd858ca761576082cd37df81416691e50199fb" +checksum = "37521ac7aabe3d13122dc382493e20c9416f299d2ccd5b3a5340a2570cdeb0f3" dependencies = [ "find-msvc-tools", "shlex", @@ -99,9 +111,9 @@ dependencies = [ [[package]] name = "cfg-if" -version = "1.0.0" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "chrono" @@ -124,9 +136,9 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.12" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" dependencies = [ "libc", ] @@ -160,14 +172,14 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.108", ] [[package]] name = "equivalent" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "fallible-iterator" @@ -177,9 +189,9 @@ checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" [[package]] name = "find-msvc-tools" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0399f9d26e5191ce32c498bebd31e7a3ceabc2745f0ac54af3f335126c3f24b3" +checksum = "52051878f80a721bb68ebfbc930e07b65ba72f2da88968ea5c06fd6ca3d3a127" [[package]] name = "fnv" @@ -258,7 +270,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.108", ] [[package]] @@ -293,9 +305,9 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.14.7" +version = "0.14.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2" dependencies = [ "typenum", "version_check", @@ -303,14 +315,23 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", "libc", "r-efi", - "wasi 0.14.7+wasi-0.2.4", + "wasip2", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", ] [[package]] @@ -322,6 +343,12 @@ dependencies = [ "foldhash", ] +[[package]] +name = "hashbrown" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" + [[package]] name = "head-rust-sdk-redis" version = "0.1.0" @@ -336,7 +363,7 @@ name = "headers-dynamic-env" version = "0.1.0" dependencies = [ "anyhow", - "http 0.2.11", + "http 0.2.12", "spin-sdk 2.2.0", ] @@ -360,7 +387,7 @@ name = "hello-world" version = "0.1.0" dependencies = [ "anyhow", - "http 0.2.11", + "http 0.2.12", "spin-sdk 2.2.0", ] @@ -388,9 +415,9 @@ dependencies = [ [[package]] name = "http" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" dependencies = [ "bytes", "fnv", @@ -399,9 +426,9 @@ dependencies = [ [[package]] name = "http" -version = "1.1.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" dependencies = [ "bytes", "fnv", @@ -443,9 +470,9 @@ dependencies = [ [[package]] name = "icu_collections" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" +checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" dependencies = [ "displaydoc", "potential_utf", @@ -456,9 +483,9 @@ dependencies = [ [[package]] name = "icu_locale_core" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" +checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" dependencies = [ "displaydoc", "litemap", @@ -469,11 +496,10 @@ dependencies = [ [[package]] name = "icu_normalizer" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" +checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" dependencies = [ - "displaydoc", "icu_collections", "icu_normalizer_data", "icu_properties", @@ -484,42 +510,38 @@ dependencies = [ [[package]] name = "icu_normalizer_data" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" +checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" [[package]] name = "icu_properties" -version = "2.0.1" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" +checksum = "e93fcd3157766c0c8da2f8cff6ce651a31f0810eaa1c51ec363ef790bbb5fb99" dependencies = [ - "displaydoc", "icu_collections", "icu_locale_core", "icu_properties_data", "icu_provider", - "potential_utf", "zerotrie", "zerovec", ] [[package]] name = "icu_properties_data" -version = "2.0.1" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" +checksum = "02845b3647bb045f1100ecd6480ff52f34c35f82d9880e029d329c21d1054899" [[package]] name = "icu_provider" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" +checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" dependencies = [ "displaydoc", "icu_locale_core", - "stable_deref_trait", - "tinystr", "writeable", "yoke", "zerofrom", @@ -556,12 +578,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.11.3" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92119844f513ffa41556430369ab02c295a3578af21cf945caa3e9e0c2481ac3" +checksum = "6717a8d2a5a929a1a2eb43a12812498ed141a0bcfb7e8f7844fbdbe4303bba9f" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.16.0", "serde", "serde_core", ] @@ -571,7 +593,7 @@ name = "integration-simple" version = "0.1.0" dependencies = [ "anyhow", - "http 0.2.11", + "http 0.2.12", "spin-sdk 2.2.0", ] @@ -619,7 +641,7 @@ version = "0.1.0" dependencies = [ "anyhow", "helper", - "http 0.2.11", + "http 0.2.12", "spin-sdk 2.2.0", ] @@ -629,7 +651,7 @@ version = "0.1.0" dependencies = [ "anyhow", "helper", - "http 0.2.11", + "http 0.2.12", "spin-sdk 2.2.0", ] @@ -639,7 +661,7 @@ version = "0.1.0" dependencies = [ "anyhow", "helper", - "http 0.2.11", + "http 0.2.12", "spin-sdk 2.2.0", ] @@ -658,20 +680,20 @@ dependencies = [ "anyhow", "futures", "helper", - "spin-sdk 3.0.0", + "spin-sdk 3.1.1", ] [[package]] name = "itoa" -version = "1.0.10" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "js-sys" -version = "0.3.81" +version = "0.3.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec48937a97411dcb524a265206ccd4c90bb711fca92b2792c407f268825b9305" +checksum = "b011eec8cc36da2aab2d5cff675ec18454fad408585853910a202391cf9f8e65" dependencies = [ "once_cell", "wasm-bindgen", @@ -694,6 +716,12 @@ dependencies = [ "spin-sdk 2.2.0", ] +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "leb128" version = "0.2.5" @@ -708,21 +736,21 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" [[package]] name = "libc" -version = "0.2.176" +version = "0.2.177" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58f929b4d672ea937a23a1ab494143d968337a5f47e56d0815df1e0890ddf174" +checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" [[package]] name = "litemap" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" +checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" [[package]] name = "log" -version = "0.4.20" +version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" [[package]] name = "md-5" @@ -736,32 +764,41 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.1" +version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" [[package]] name = "mini-internal" -version = "0.1.36" +version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51c55587ac25c2d63a75e4171221b2803a9b9e83aeb7bdfde5833c4cd578b50d" +checksum = "560f32b6891d8d9bade8942c45a27694f16d789d3b4b8e6b7135a5240de0a8af" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.108", ] [[package]] name = "miniserde" -version = "0.1.36" +version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8621df4a46e5de4c1541242407da38281ea0e320b94e238477688a36a1a059f7" +checksum = "ac79f4123c070de643a7a93b9339abf18c30005c622bf4b1c29c2c0960f52d39" dependencies = [ "itoa", "mini-internal", "ryu", ] +[[package]] +name = "nu-ansi-term" +version = "0.50.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" +dependencies = [ + "windows-sys", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -773,16 +810,70 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.19.0" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "opentelemetry" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aaf416e4cb72756655126f7dd7bb0af49c674f4c1b9903e80c009e0c37e552e6" +dependencies = [ + "futures-core", + "futures-sink", + "js-sys", + "pin-project-lite", + "thiserror 2.0.17", + "tracing", +] + +[[package]] +name = "opentelemetry-wasi" +version = "0.27.0" +source = "git+https://github.com/calebschoepp/opentelemetry-wasi?rev=60df119fbc03ed83d0e2cc1300f6a8eb055d23f7#60df119fbc03ed83d0e2cc1300f6a8eb055d23f7" +dependencies = [ + "anyhow", + "opentelemetry", + "opentelemetry_sdk", + "spin-sdk 3.1.1", + "tracing", + "tracing-opentelemetry", + "tracing-subscriber", + "wit-bindgen 0.30.0", +] + +[[package]] +name = "opentelemetry_sdk" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "11f644aa9e5e31d11896e024305d7e3c98a88884d9f8919dbf37a9991bc47a4b" +dependencies = [ + "futures-channel", + "futures-executor", + "futures-util", + "opentelemetry", + "percent-encoding", + "rand", + "serde_json", + "thiserror 2.0.17", +] + +[[package]] +name = "otel-smoke-test" +version = "0.1.0" +dependencies = [ + "anyhow", + "http 0.2.12", + "spin-sdk 2.2.0", +] [[package]] name = "outbound-http-component" version = "0.1.0" dependencies = [ "anyhow", - "http 0.2.11", + "http 0.2.12", "spin-sdk 2.2.0", ] @@ -826,9 +917,9 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] name = "pin-utils" @@ -856,9 +947,9 @@ dependencies = [ [[package]] name = "postgres-types" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a120daaabfcb0e324d5bf6e411e9222994cb3795c79943a0ef28ed27ea76e4" +checksum = "ef4605b7c057056dd35baeb6ac0c0338e4975b1f2bef0f65da953285eb007095" dependencies = [ "bytes", "fallible-iterator", @@ -877,9 +968,9 @@ dependencies = [ [[package]] name = "potential_utf" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84df19adbe5b5a0782edcab45899906947ab039ccf4573713735ee7de1e6b08a" +checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" dependencies = [ "zerovec", ] @@ -895,28 +986,28 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.29" +version = "0.2.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6924ced06e1f7dfe3fa48d57b9f74f55d8915f5036121bef647ef4b204895fac" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", - "syn 2.0.98", + "syn 2.0.108", ] [[package]] name = "proc-macro2" -version = "1.0.93" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" +checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.35" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1" dependencies = [ "proc-macro2", ] @@ -958,9 +1049,9 @@ dependencies = [ [[package]] name = "routefinder" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94f8f99b10dedd317514253dda1fa7c14e344aac96e1f78149a64879ce282aca" +checksum = "0971d3c8943a6267d6bd0d782fdc4afa7593e7381a92a3df950ff58897e066b5" dependencies = [ "smartcow", "smartstring", @@ -968,9 +1059,9 @@ dependencies = [ [[package]] name = "rust_decimal" -version = "1.38.0" +version = "1.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8975fc98059f365204d635119cf9c5a60ae67b841ed49b5422a9a7e56cdfac0" +checksum = "35affe401787a9bd846712274d97654355d21b2a2c092a3139aabe31e9022282" dependencies = [ "arrayvec", "num-traits", @@ -984,21 +1075,21 @@ checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "ryu" -version = "1.0.16" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] name = "semver" -version = "1.0.20" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" [[package]] name = "serde" -version = "1.0.225" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6c24dee235d0da097043389623fb913daddf92c76e9f5a1db88607a0bcbd1d" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" dependencies = [ "serde_core", "serde_derive", @@ -1006,33 +1097,35 @@ dependencies = [ [[package]] name = "serde_core" -version = "1.0.225" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "659356f9a0cb1e529b24c01e43ad2bdf520ec4ceaf83047b83ddcc2251f96383" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.225" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ea936adf78b1f766949a4977b91d2f5595825bd6ec079aa9543ad2685fc4516" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.108", ] [[package]] name = "serde_json" -version = "1.0.108" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" dependencies = [ "itoa", + "memchr", "ryu", "serde", + "serde_core", ] [[package]] @@ -1043,7 +1136,7 @@ checksum = "0431a35568651e363364210c91983c1da5eb29404d9f0928b67d4ebcfa7d330c" dependencies = [ "percent-encoding", "serde", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -1057,6 +1150,15 @@ dependencies = [ "digest", ] +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + [[package]] name = "shlex" version = "1.3.0" @@ -1065,12 +1167,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "slab" -version = "0.4.9" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] +checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" [[package]] name = "smallvec" @@ -1100,22 +1199,33 @@ dependencies = [ [[package]] name = "spdx" -version = "0.10.2" +version = "0.10.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b19b32ed6d899ab23174302ff105c1577e45a06b08d4fe0a9dd13ce804bbbf71" +checksum = "c3e17e880bafaeb362a7b751ec46bdc5b61445a188f80e0606e68167cd540fa3" dependencies = [ "smallvec", ] [[package]] name = "spin-executor" -version = "5.0.0" +version = "3.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d11baf86ca52100e8742ea43d2c342cf4d75b94f8a85454cf44fd108cdd71d5" +dependencies = [ + "futures", + "once_cell", + "wit-bindgen 0.16.0", +] + +[[package]] +name = "spin-executor" +version = "5.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cde323c004c7d9d68fbccd1dd6caee6330aaefbcb40562587fc0356bd0ea8e5f" +checksum = "9fa74c56ad71afb64fff0566d7cb313567d0469ba2a75b0af58c323f59b74280" dependencies = [ "futures", "once_cell", - "wasi 0.13.1+wasi-0.2.0", + "wasi", ] [[package]] @@ -1126,7 +1236,7 @@ checksum = "13524474ab9f876586e29f954377a66ed14fcb646fc9893e6f0e762213ddbd86" dependencies = [ "anyhow", "bytes", - "http 0.2.11", + "http 0.2.12", "proc-macro2", "quote", "syn 1.0.109", @@ -1134,9 +1244,9 @@ dependencies = [ [[package]] name = "spin-macro" -version = "3.0.0" +version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a161ae2fefde8582ef555ead81d87cf897cd31a23a1d1e0c22a9c43fd9af421a" +checksum = "988ffe27470862bf28fe9b4f0268361040d4732cd86bcaebe45aa3d3b3e3d896" dependencies = [ "anyhow", "bytes", @@ -1147,9 +1257,9 @@ dependencies = [ [[package]] name = "spin-macro" -version = "5.0.0" +version = "5.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1592d94530c032aa8676c8adee71022fba49504ae6d4d8961a454029d3bac6f" +checksum = "74edf3aab0f4e24b30e765d10fcdbff69aa2d1906907f3318c5f8a8106daef34" dependencies = [ "anyhow", "bytes", @@ -1177,42 +1287,44 @@ dependencies = [ "bytes", "form_urlencoded", "futures", - "http 0.2.11", + "http 0.2.12", "once_cell", "routefinder", "serde", "serde_json", "spin-macro 2.2.0", - "thiserror", + "thiserror 1.0.69", "wit-bindgen 0.13.1", ] [[package]] name = "spin-sdk" -version = "3.0.0" +version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2c02cf00c243c03fb330cb5be7bf4eb3c8db7c5476425068c7385ddff1567aa" +checksum = "f845e889d8431740806e04704ac5aa619466dfaef626f3c15952ecf823913e01" dependencies = [ "anyhow", "async-trait", "bytes", + "chrono", "form_urlencoded", "futures", - "http 1.1.0", + "http 1.3.1", "once_cell", "routefinder", "serde", "serde_json", - "spin-macro 3.0.0", - "thiserror", + "spin-executor 3.1.1", + "spin-macro 3.1.1", + "thiserror 1.0.69", "wit-bindgen 0.16.0", ] [[package]] name = "spin-sdk" -version = "5.0.0" +version = "5.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72e9705e63f1e7f955b3c9bef754a6f957624d734c6091990a2dc6f1e135625d" +checksum = "5374bed998dc151d3c3a45ffdba3269d9f94ea6cf19f002ff7fc744edb09a5f8" dependencies = [ "anyhow", "async-trait", @@ -1220,18 +1332,18 @@ dependencies = [ "chrono", "form_urlencoded", "futures", - "http 1.1.0", + "http 1.3.1", "once_cell", "postgres_range", "routefinder", "rust_decimal", "serde", "serde_json", - "spin-executor", - "spin-macro 5.0.0", - "thiserror", + "spin-executor 5.1.0", + "spin-macro 5.1.0", + "thiserror 2.0.17", "uuid", - "wasi 0.13.1+wasi-0.2.0", + "wasi", "wit-bindgen 0.43.0", ] @@ -1245,9 +1357,9 @@ dependencies = [ [[package]] name = "stable_deref_trait" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] name = "static_assertions" @@ -1285,9 +1397,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.98" +version = "2.0.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1" +checksum = "da58917d35242480a05c2897064da0a80589a2a0476c9a3f2fdc83b53502e917" dependencies = [ "proc-macro2", "quote", @@ -1302,7 +1414,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.108", ] [[package]] @@ -1315,29 +1427,58 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.56" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" +checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" dependencies = [ - "thiserror-impl", + "thiserror-impl 2.0.17", ] [[package]] name = "thiserror-impl" -version = "1.0.56" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.108", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "thread_local" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" +dependencies = [ + "cfg-if", ] [[package]] name = "tinystr" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" +checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" dependencies = [ "displaydoc", "zerovec", @@ -1358,11 +1499,86 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" +[[package]] +name = "tracing" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + +[[package]] +name = "tracing-core" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-opentelemetry" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddcf5959f39507d0d04d6413119c04f33b623f4f951ebcbdddddfad2d0623a9c" +dependencies = [ + "js-sys", + "once_cell", + "opentelemetry", + "opentelemetry_sdk", + "smallvec", + "tracing", + "tracing-core", + "tracing-log", + "tracing-subscriber", + "web-time", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5" +dependencies = [ + "nu-ansi-term", + "sharded-slab", + "smallvec", + "thread_local", + "tracing-core", + "tracing-log", +] + [[package]] name = "typenum" -version = "1.17.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" [[package]] name = "unicode-bidi" @@ -1372,43 +1588,43 @@ checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" [[package]] name = "unicode-normalization" -version = "0.1.24" +version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" +checksum = "5fd4f6878c9cb28d874b009da9e8d183b5abc80117c40bbd187a1fde336be6e8" dependencies = [ "tinyvec", ] [[package]] name = "unicode-properties" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0" +checksum = "7df058c713841ad818f1dc5d3fd88063241cc61f49f5fbea4b951e8cf5a8d71d" [[package]] name = "unicode-segmentation" -version = "1.10.1" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] name = "unicode-xid" -version = "0.2.4" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "unsupported-import" version = "0.1.0" dependencies = [ "anyhow", - "spin-sdk 5.0.0", + "spin-sdk 5.1.0", "wit-bindgen 0.43.0", ] @@ -1440,6 +1656,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + [[package]] name = "variables" version = "0.1.0" @@ -1453,15 +1675,15 @@ name = "vault-variables-test" version = "0.1.0" dependencies = [ "anyhow", - "http 0.2.11", + "http 0.2.12", "spin-sdk 2.2.0", ] [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "wasi" @@ -1472,15 +1694,6 @@ dependencies = [ "wit-bindgen-rt 0.24.0", ] -[[package]] -name = "wasi" -version = "0.14.7+wasi-0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "883478de20367e224c0090af9cf5f9fa85bed63a95c1abf3afc5c083ebc06e8c" -dependencies = [ - "wasip2", -] - [[package]] name = "wasi-config" version = "0.1.0" @@ -1522,6 +1735,19 @@ dependencies = [ "wit-bindgen 0.46.0", ] +[[package]] +name = "wasi-otel-tracing" +version = "0.1.0" +dependencies = [ + "anyhow", + "http 0.2.12", + "opentelemetry", + "opentelemetry-wasi", + "opentelemetry_sdk", + "spin-sdk 3.1.1", + "wit-bindgen 0.30.0", +] + [[package]] name = "wasip2" version = "1.0.1+wasi-0.2.4" @@ -1533,9 +1759,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.104" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1da10c01ae9f1ae40cbfac0bac3b1e724b320abfcf52229f80b547c0d250e2d" +checksum = "da95793dfc411fbbd93f5be7715b0578ec61fe87cb1a42b12eb625caa5c5ea60" dependencies = [ "cfg-if", "once_cell", @@ -1544,25 +1770,11 @@ dependencies = [ "wasm-bindgen-shared", ] -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.104" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "671c9a5a66f49d8a47345ab942e2cb93c7d1d0339065d4f8139c486121b43b19" -dependencies = [ - "bumpalo", - "log", - "proc-macro2", - "quote", - "syn 2.0.98", - "wasm-bindgen-shared", -] - [[package]] name = "wasm-bindgen-macro" -version = "0.2.104" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ca60477e4c59f5f2986c50191cd972e3a50d8a95603bc9434501cf156a9a119" +checksum = "04264334509e04a7bf8690f2384ef5265f05143a4bff3889ab7a3269adab59c2" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1570,22 +1782,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.104" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f07d2f20d4da7b26400c9f4a0511e6e0345b040694e8a75bd41d578fa4421d7" +checksum = "420bc339d9f322e562942d52e115d57e950d12d88983a14c79b86859ee6c7ebc" dependencies = [ + "bumpalo", "proc-macro2", "quote", - "syn 2.0.98", - "wasm-bindgen-backend", + "syn 2.0.108", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.104" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bad67dc8b2a1a6e5448428adec4c3e84c43e561d8c9ee8a9e5aabeb193ec41d1" +checksum = "76f218a38c84bcb33c25ec7059b07847d465ce0e0a76b995e134a45adcb6af76" dependencies = [ "unicode-ident", ] @@ -1617,6 +1829,16 @@ dependencies = [ "leb128", ] +[[package]] +name = "wasm-encoder" +version = "0.215.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb56df3e06b8e6b77e37d2969a50ba51281029a9aeb3855e76b7f49b6418847" +dependencies = [ + "leb128", + "wasmparser 0.215.0", +] + [[package]] name = "wasm-encoder" version = "0.235.0" @@ -1653,6 +1875,22 @@ dependencies = [ "wasmparser 0.121.2", ] +[[package]] +name = "wasm-metadata" +version = "0.215.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c6bb07c5576b608f7a2a9baa2294c1a3584a249965d695a9814a496cb6d232f" +dependencies = [ + "anyhow", + "indexmap", + "serde", + "serde_derive", + "serde_json", + "spdx", + "wasm-encoder 0.215.0", + "wasmparser 0.215.0", +] + [[package]] name = "wasm-metadata" version = "0.235.0" @@ -1689,9 +1927,9 @@ dependencies = [ [[package]] name = "wasmparser" -version = "0.118.1" +version = "0.118.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95ee9723b928e735d53000dec9eae7b07a60e490c85ab54abb66659fc61bfcd9" +checksum = "77f1154f1ab868e2a01d9834a805faca7bf8b50d041b4ca714d005d0dab1c50c" dependencies = [ "indexmap", "semver", @@ -1708,6 +1946,19 @@ dependencies = [ "semver", ] +[[package]] +name = "wasmparser" +version = "0.215.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53fbde0881f24199b81cf49b6ff8f9c145ac8eb1b7fc439adb5c099734f7d90e" +dependencies = [ + "ahash", + "bitflags", + "hashbrown 0.14.5", + "indexmap", + "semver", +] + [[package]] name = "wasmparser" version = "0.235.0" @@ -1715,7 +1966,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "161296c618fa2d63f6ed5fffd1112937e803cb9ec71b32b01a76321555660917" dependencies = [ "bitflags", - "hashbrown", + "hashbrown 0.15.5", "indexmap", "semver", ] @@ -1727,16 +1978,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c9d90bb93e764f6beabf1d02028c70a2156a6583e63ac4218dd07ef733368b0" dependencies = [ "bitflags", - "hashbrown", + "hashbrown 0.15.5", "indexmap", "semver", ] +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "windows-core" -version = "0.62.1" +version = "0.62.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6844ee5416b285084d3d3fffd743b925a6c9385455f64f6d4fa3031c4c2749a9" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" dependencies = [ "windows-implement", "windows-interface", @@ -1747,46 +2008,55 @@ dependencies = [ [[package]] name = "windows-implement" -version = "0.60.1" +version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edb307e42a74fb6de9bf3a02d9712678b22399c87e6fa869d6dfcd8c1b7754e0" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.108", ] [[package]] name = "windows-interface" -version = "0.59.2" +version = "0.59.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0abd1ddbc6964ac14db11c7213d6532ef34bd9aa042c2e5935f59d7908b46a5" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.108", ] [[package]] name = "windows-link" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] name = "windows-result" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7084dcc306f89883455a206237404d3eaf961e5bd7e0f312f7c91f57eb44167f" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" dependencies = [ "windows-link", ] [[package]] name = "windows-strings" -version = "0.5.0" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7218c655a553b0bed4426cf54b20d7ba363ef543b52d515b3e48d7fd55318dda" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ "windows-link", ] @@ -1811,6 +2081,16 @@ dependencies = [ "wit-bindgen-rust-macro 0.16.0", ] +[[package]] +name = "wit-bindgen" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b4bac478334a647374ff24a74b66737a4cb586dc8288bc3080a93252cd1105c" +dependencies = [ + "wit-bindgen-rt 0.30.0", + "wit-bindgen-rust-macro 0.30.0", +] + [[package]] name = "wit-bindgen" version = "0.43.0" @@ -1852,7 +2132,18 @@ checksum = "75d55e1a488af2981fb0edac80d8d20a51ac36897a1bdef4abde33c29c1b6d0d" dependencies = [ "anyhow", "wit-component 0.18.2", - "wit-parser 0.13.0", + "wit-parser 0.13.2", +] + +[[package]] +name = "wit-bindgen-core" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb7e3df01cd43cfa1cb52602e4fc05cb2b62217655f6705639b6953eb0a3fed2" +dependencies = [ + "anyhow", + "heck 0.5.0", + "wit-parser 0.215.0", ] [[package]] @@ -1886,6 +2177,15 @@ dependencies = [ "bitflags", ] +[[package]] +name = "wit-bindgen-rt" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2de7a3b06b9725d129b5cbd1beca968feed919c433305a23da46843185ecdd6" +dependencies = [ + "bitflags", +] + [[package]] name = "wit-bindgen-rt" version = "0.43.0" @@ -1923,6 +2223,22 @@ dependencies = [ "wit-component 0.18.2", ] +[[package]] +name = "wit-bindgen-rust" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61a767d1a8eb4e908bfc53febc48b87ada545703b16fe0148ee7736a29a01417" +dependencies = [ + "anyhow", + "heck 0.5.0", + "indexmap", + "prettyplease", + "syn 2.0.108", + "wasm-metadata 0.215.0", + "wit-bindgen-core 0.30.0", + "wit-component 0.215.0", +] + [[package]] name = "wit-bindgen-rust" version = "0.43.0" @@ -1933,7 +2249,7 @@ dependencies = [ "heck 0.5.0", "indexmap", "prettyplease", - "syn 2.0.98", + "syn 2.0.108", "wasm-metadata 0.235.0", "wit-bindgen-core 0.43.0", "wit-component 0.235.0", @@ -1949,7 +2265,7 @@ dependencies = [ "heck 0.5.0", "indexmap", "prettyplease", - "syn 2.0.98", + "syn 2.0.108", "wasm-metadata 0.239.0", "wit-bindgen-core 0.46.0", "wit-component 0.239.0", @@ -1964,7 +2280,7 @@ dependencies = [ "anyhow", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.108", "wit-bindgen-core 0.13.1", "wit-bindgen-rust 0.13.2", "wit-component 0.17.0", @@ -1979,12 +2295,27 @@ dependencies = [ "anyhow", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.108", "wit-bindgen-core 0.16.0", "wit-bindgen-rust 0.16.0", "wit-component 0.18.2", ] +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b185c342d0d27bd83d4080f5a66cf3b4f247fa49d679bceb66e11cc7eb58b99" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn 2.0.108", + "wit-bindgen-core 0.30.0", + "wit-bindgen-rust 0.30.0", +] + [[package]] name = "wit-bindgen-rust-macro" version = "0.43.0" @@ -1995,7 +2326,7 @@ dependencies = [ "prettyplease", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.108", "wit-bindgen-core 0.43.0", "wit-bindgen-rust 0.43.0", ] @@ -2010,7 +2341,7 @@ dependencies = [ "prettyplease", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.108", "wit-bindgen-core 0.46.0", "wit-bindgen-rust 0.46.0", ] @@ -2049,8 +2380,27 @@ dependencies = [ "serde_json", "wasm-encoder 0.38.1", "wasm-metadata 0.10.20", - "wasmparser 0.118.1", - "wit-parser 0.13.0", + "wasmparser 0.118.2", + "wit-parser 0.13.2", +] + +[[package]] +name = "wit-component" +version = "0.215.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f725e3885fc5890648be5c5cbc1353b755dc932aa5f1aa7de968b912a3280743" +dependencies = [ + "anyhow", + "bitflags", + "indexmap", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder 0.215.0", + "wasm-metadata 0.215.0", + "wasmparser 0.215.0", + "wit-parser 0.215.0", ] [[package]] @@ -2110,9 +2460,9 @@ dependencies = [ [[package]] name = "wit-parser" -version = "0.13.0" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15df6b7b28ce94b8be39d8df5cb21a08a4f3b9f33b631aedb4aa5776f785ead3" +checksum = "316b36a9f0005f5aa4b03c39bc3728d045df136f8c13a73b7db4510dec725e08" dependencies = [ "anyhow", "id-arena", @@ -2125,6 +2475,24 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "wit-parser" +version = "0.215.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "935a97eaffd57c3b413aa510f8f0b550a4a9fe7d59e79cd8b89a83dcb860321f" +dependencies = [ + "anyhow", + "id-arena", + "indexmap", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser 0.215.0", +] + [[package]] name = "wit-parser" version = "0.235.0" @@ -2163,17 +2531,16 @@ dependencies = [ [[package]] name = "writeable" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" +checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" [[package]] name = "yoke" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" +checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" dependencies = [ - "serde", "stable_deref_trait", "yoke-derive", "zerofrom", @@ -2181,13 +2548,13 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" +checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.108", "synstructure", ] @@ -2208,7 +2575,7 @@ checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.108", ] [[package]] @@ -2228,15 +2595,15 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.108", "synstructure", ] [[package]] name = "zerotrie" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" dependencies = [ "displaydoc", "yoke", @@ -2245,9 +2612,9 @@ dependencies = [ [[package]] name = "zerovec" -version = "0.11.4" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b" +checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" dependencies = [ "yoke", "zerofrom", @@ -2256,11 +2623,11 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" +checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.108", ] diff --git a/tests/test-components/components/otel-smoke-test/Cargo.toml b/tests/test-components/components/otel-smoke-test/Cargo.toml new file mode 100644 index 0000000000..521468b790 --- /dev/null +++ b/tests/test-components/components/otel-smoke-test/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "otel-smoke-test" +version = "0.1.0" +edition = "2021" + +[lib] +crate-type = ["cdylib"] + +[dependencies] +anyhow = "1" +http = "0.2" +spin-sdk = "2.2.0" diff --git a/tests/test-components/components/otel-smoke-test/src/lib.rs b/tests/test-components/components/otel-smoke-test/src/lib.rs new file mode 100644 index 0000000000..85c4326102 --- /dev/null +++ b/tests/test-components/components/otel-smoke-test/src/lib.rs @@ -0,0 +1,22 @@ +use spin_sdk::{ + http::{Method, Params, Request, Response, Router}, + http_component, +}; + +#[http_component] +fn handle(req: http::Request<()>) -> Response { + let mut router = Router::new(); + router.get_async("/one", one); + router.get_async("/two", two); + router.handle(req) +} + +async fn one(_req: Request, _params: Params) -> Response { + let req = Request::builder().method(Method::Get).uri("/two").build(); + let _res: Response = spin_sdk::http::send(req).await.unwrap(); + Response::new(200, "") +} + +async fn two(_req: Request, _params: Params) -> Response { + Response::new(201, "") +} diff --git a/tests/test-components/components/wasi-otel-tracing/Cargo.toml b/tests/test-components/components/wasi-otel-tracing/Cargo.toml new file mode 100644 index 0000000000..4a434653e1 --- /dev/null +++ b/tests/test-components/components/wasi-otel-tracing/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "wasi-otel-tracing" +version = "0.1.0" +edition = "2021" + +[lib] +crate-type = ["cdylib"] + +[dependencies] +anyhow = "1" +http = "0.2" +opentelemetry = "0.30.0" +opentelemetry_sdk = "0.30.0" +opentelemetry-wasi = { git = "https://github.com/calebschoepp/opentelemetry-wasi", rev = "60df119fbc03ed83d0e2cc1300f6a8eb055d23f7" } +spin-sdk = "3.1.0" +wit-bindgen = "0.30.0" diff --git a/tests/test-components/components/wasi-otel-tracing/src/lib.rs b/tests/test-components/components/wasi-otel-tracing/src/lib.rs new file mode 100644 index 0000000000..c7d427b8bc --- /dev/null +++ b/tests/test-components/components/wasi-otel-tracing/src/lib.rs @@ -0,0 +1,130 @@ +use std::time; + +use opentelemetry::{ + global::{self, BoxedTracer, ObjectSafeSpan}, + trace::{TraceContextExt, Tracer}, + Array, Context, ContextGuard, KeyValue, Value, +}; +use opentelemetry_sdk::trace::SdkTracerProvider; +use opentelemetry_wasi::WasiPropagator; +use spin_sdk::{ + http::{IntoResponse, Method, Params, Request, Response, Router}, + http_component, +}; + +#[http_component] +fn handle(req: Request) -> anyhow::Result { + let mut router = Router::new(); + router.get("/nested-spans", nested_spans); + router.get("/setting-attributes", setting_attributes); + router.get_async("/host-guest-host", host_guest_host); + router.get("/events", events); + router.get("/links", links); + router.get_async("/root-span", root_span); + Ok(router.handle(req)) +} + +fn setup_tracer(propagate_context: bool) -> (BoxedTracer, Option) { + // Set up a tracer using the WASI processor + let wasi_processor = opentelemetry_wasi::WasiProcessor::new(); + let tracer_provider = SdkTracerProvider::builder() + .with_span_processor(wasi_processor) + .build(); + global::set_tracer_provider(tracer_provider); + let tracer = global::tracer("wasi-otel-tracing"); + + if propagate_context { + let wasi_propagator = opentelemetry_wasi::TraceContextPropagator::new(); + ( + tracer, + Some(wasi_propagator.extract(&Context::current()).attach()), + ) + } else { + (tracer, None) + } +} + +fn nested_spans(_req: Request, _params: Params) -> Response { + let (tracer, _ctx) = setup_tracer(true); + tracer.in_span("outer_func", |_| { + tracer.in_span("inner_func", |_| {}); + }); + Response::new(200, "") +} + +fn setting_attributes(_req: Request, _params: Params) -> Response { + let (tracer, _ctx) = setup_tracer(true); + tracer.in_span("setting_attributes", |cx| { + let span = cx.span(); + span.set_attribute(KeyValue::new("foo", "bar")); + span.set_attribute(KeyValue::new("foo", "baz")); + span.set_attribute(KeyValue::new( + "qux", + Value::Array(Array::String(vec!["qaz".into(), "thud".into()])), + )); + }); + + Response::new(200, "") +} + +async fn host_guest_host(_req: Request, _params: Params) -> Response { + let (tracer, _ctx) = setup_tracer(true); + let mut span = tracer.start("guest"); + make_request().await; + span.end(); + + Response::new(200, "") +} + +fn events(_req: Request, _params: Params) -> Response { + let (tracer, _ctx) = setup_tracer(true); + tracer.in_span("events", |cx| { + let span = cx.span(); + span.add_event("basic-event".to_string(), vec![]); + span.add_event( + "event-with-attributes".to_string(), + vec![KeyValue::new("foo", true)], + ); + let time = time::SystemTime::now() + .duration_since(time::UNIX_EPOCH) + .unwrap(); + let time = time.as_secs_f64(); + let time = time::Duration::from_secs_f64(time + 1.0); + let time = time::SystemTime::UNIX_EPOCH + time; + span.add_event_with_timestamp("event-with-timestamp", time, vec![]); + }); + Response::new(200, "") +} + +fn links(_req: Request, _params: Params) -> Response { + let (tracer, _ctx) = setup_tracer(true); + let mut first = tracer.start("first"); + first.end(); + let mut second = tracer.start("second"); + second.add_link( + first.span_context().clone(), + vec![KeyValue::new("foo", "bar")], + ); + second.end(); + Response::new(200, "") +} + +async fn root_span(_req: Request, _params: Params) -> Response { + let (tracer, _ctx) = setup_tracer(false); + let mut span = tracer.start("root"); + make_request().await; + span.end(); + Response::new(200, "") +} + +async fn make_request() { + let req = Request::builder() + .method(Method::Get) + .uri("https://asdf.com") + .build(); + let _res: Response = spin_sdk::http::send(req).await.unwrap(); +} + +// TODO: Test what happens if start is called but not end +// TODO: Test what happens if end is called but not start +// TODO: What happens if child span outlives parent diff --git a/tests/testcases/otel-smoke-test/spin.toml b/tests/testcases/otel-smoke-test/spin.toml index bc143dd323..909149421f 100644 --- a/tests/testcases/otel-smoke-test/spin.toml +++ b/tests/testcases/otel-smoke-test/spin.toml @@ -1,12 +1,13 @@ spin_version = "1" -authors = ["Spin Framework Contributors"] -description = "A simple application that returns hello and goodbye." -name = "head-rust-sdk-http" +authors = ["Fermyon Engineering "] +description = "A simple application that tests otel." +name = "otel-smoke-test" trigger = { type = "http" } version = "1.0.0" [[component]] -id = "hello" -source = "%{source=hello-world}" +id = "otel" +source = "%{source=otel-smoke-test}" +allowed_outbound_hosts = ["http://self"] [component.trigger] -route = "/hello/..." +route = "/..." diff --git a/tests/testcases/wasi-otel-tracing/spin.toml b/tests/testcases/wasi-otel-tracing/spin.toml new file mode 100644 index 0000000000..a54f57210b --- /dev/null +++ b/tests/testcases/wasi-otel-tracing/spin.toml @@ -0,0 +1,19 @@ +spin_manifest_version = 2 + +[application] +authors = ["Fermyon Engineering "] +description = "An application to exercise wasi-otel tracing functionality." +name = "wasi-otel-tracing" +version = "1.0.0" + +[[trigger.http]] +route = "/..." +component = "wasi-otel-tracing" + +[component.wasi-otel-tracing] +source = "%{source=wasi-otel-tracing}" +key_value_stores = ["default"] +allowed_outbound_hosts = ["http://self", "https://asdf.com"] +[component.wasi-otel-tracing.build] +command = "cargo build --target wasm32-wasi --release" +watch = ["src/**/*.rs", "Cargo.toml"] diff --git a/wit/deps/otel/metrics.wit b/wit/deps/otel/metrics.wit new file mode 100644 index 0000000000..8255684a4e --- /dev/null +++ b/wit/deps/otel/metrics.wit @@ -0,0 +1,264 @@ +interface metrics { + use wasi:clocks/wall-clock@0.2.0.{datetime}; + use wasi:clocks/monotonic-clock@0.2.0.{duration}; + use types.{key-value, instrumentation-scope}; + use tracing.{span-id, trace-id}; + + /// Exports a resource's metric data. + %export: func(metrics: resource-metrics) -> result<_, error>; + + /// An error resulting from `export` being called. + type error = string; + + /// A collection of `scope-metrics` and the associated `resource` that created them. + record resource-metrics { + /// The entity that collected the metrics. + %resource: %resource, + /// The collection of metrics with unique `instrumentation-scope`s. + scope-metrics: list, + } + + /// An immutable representation of the entity producing telemetry as attributes. + record %resource { + /// Attributes that identify the resource. + attributes: list, + /// The schema URL to be recorded in the emitted resource. + schema-url: option, + } + + /// A collection of `metric`s produced by a meter. + record scope-metrics { + /// The instrumentation scope that the meter was created with. + scope: instrumentation-scope, + /// The list of aggregations created by the meter. + metrics: list, + } + + /// A collection of one or more aggregated time series from a metric. + record metric { + /// The name of the metric that created this data. + name: string, + /// The description of the metric, which can be used in documentation. + description: string, + /// The unit in which the metric reports. + unit: string, + /// The aggregated data from a metric. + data: metric-data + } + + /// Metric data for all types. + variant metric-data { + /// Metric data for an f64 gauge. + f64-gauge(gauge), + /// Metric data for an f64 sum. + f64-sum(sum), + /// Metric data for an f64 histogram. + f64-histogram(histogram), + /// Metric data for an f64 exponential-histogram. + f64-exponential-histogram(exponential-histogram), + /// Metric data for an u64 gauge. + u64-gauge(gauge), + /// Metric data for an u64 sum. + u64-sum(sum), + /// Metric data for an u64 histogram. + u64-histogram(histogram), + /// Metric data for an u64 exponential-histogram. + u64-exponential-histogram(exponential-histogram), + /// Metric data for an s64 gauge. + s64-gauge(gauge), + /// Metric data for an s64 sum. + s64-sum(sum), + /// Metric data for an s64 histogram. + s64-histogram(histogram), + /// Metric data for an s64 exponential-histogram. + s64-exponential-histogram(exponential-histogram), + } + + /// A measurement of the current value of an instrument. + record gauge { + /// Represents individual aggregated measurements with unique attributes. + data-points: list, + /// The time when the time series was started. + start-time: option, + /// The time when the time series was recorded. + time: datetime, + } + + /// A single data point in a time series to be associated with a `gauge`. + record gauge-data-point { + /// `attributes` is the set of key value pairs that uniquely identify the + /// time series. + attributes: list, + /// The value of this data point. + value: metric-number, + /// The sampled `exemplar`s collected during the time series. + exemplars: list, + } + + /// Represents the sum of all measurements of values from an instrument. + record sum { + /// Represents individual aggregated measurements with unique attributes. + data-points: list, + /// The time when the time series was started. + start-time: datetime, + /// The time when the time series was recorded. + time: datetime, + /// Describes if the aggregation is reported as the change from the last report + /// time, or the cumulative changes since a fixed start time. + temporality: temporality, + /// Whether this aggregation only increases or decreases. + is-monotonic: bool, + } + + /// A single data point in a time series to be associated with a `sum`. + record sum-data-point { + /// `attributes` is the set of key value pairs that uniquely identify the + /// time series. + attributes: list, + /// The value of this data point. + value: metric-number, + /// The sampled `exemplar`s collected during the time series. + exemplars: list, + } + + /// Represents the histogram of all measurements of values from an instrument. + record histogram { + /// Individual aggregated measurements with unique attributes. + data-points: list, + /// The time when the time series was started. + start-time: datetime, + /// The time when the time series was recorded. + time: datetime, + /// Describes if the aggregation is reported as the change from the last report + /// time, or the cumulative changes since a fixed start time. + temporality: temporality, + } + + /// A single data point in a time series to be associated with a `histogram`. + record histogram-data-point { + /// The set of key value pairs that uniquely identify the time series. + attributes: list, + /// The number of updates this histogram has been calculated with. + count: u64, + /// The upper bounds of the buckets of the histogram. + bounds: list, + /// The count of each of the buckets. + bucket-counts: list, + /// The minimum value recorded. + min: option, + /// The maximum value recorded. + max: option, + /// The sum of the values recorded + sum: metric-number, + /// The sampled `exemplar`s collected during the time series. + exemplars: list, + } + + /// The histogram of all measurements of values from an instrument. + record exponential-histogram { + /// The individual aggregated measurements with unique attributes. + data-points: list, + /// When the time series was started. + start-time: datetime, + /// The time when the time series was recorded. + time: datetime, + /// Describes if the aggregation is reported as the change from the last report + /// time, or the cumulative changes since a fixed start time. + temporality: temporality, + } + + /// A single data point in a time series to be associated with an `exponential-histogram `. + record exponential-histogram-data-point { + /// The set of key value pairs that uniquely identify the time series. + attributes: list, + /// The number of updates this histogram has been calculated with. + count: u64, + /// The minimum value recorded. + min: option, + /// The maximum value recorded. + max: option, + /// The maximum value recorded. + sum: metric-number, + /// Describes the resolution of the histogram. + /// + /// Boundaries are located at powers of the base, where: + /// + /// base = 2 ^ (2 ^ -scale) + scale: s8, + /// The number of values whose absolute value is less than or equal to + /// `zero_threshold`. + /// + /// When `zero_threshold` is `0`, this is the number of values that cannot be + /// expressed using the standard exponential formula as well as values that have + /// been rounded to zero. + zero-count: u64, + /// The range of positive value bucket counts. + positive-bucket: exponential-bucket, + /// The range of negative value bucket counts. + negative-bucket: exponential-bucket, + /// The width of the zero region. + /// + /// Where the zero region is defined as the closed interval + /// [-zero_threshold, zero_threshold]. + zero-threshold: f64, + /// The sampled exemplars collected during the time series. + exemplars: list, + } + + /// A set of bucket counts, encoded in a contiguous array of counts. + record exponential-bucket { + /// The bucket index of the first entry in the `counts` list. + offset: s32, + /// A list where `counts[i]` carries the count of the bucket at index `offset + i`. + /// + /// `counts[i]` is the count of values greater than base^(offset+i) and less than + /// or equal to base^(offset+i+1). + counts: list, + } + + /// A measurement sampled from a time series providing a typical example. + record exemplar { + /// The attributes recorded with the measurement but filtered out of the + /// time series' aggregated data. + filtered-attributes: list, + /// The time when the measurement was recorded. + time: datetime, + /// The measured value. + value: metric-number, + /// The ID of the span that was active during the measurement. + /// + /// If no span was active or the span was not sampled this will be empty. + span-id: span-id, + /// The ID of the trace the active span belonged to during the measurement. + /// + /// If no span was active or the span was not sampled this will be empty. + trace-id: trace-id, + } + + /// Defines the window that an aggregation was calculated over. + enum temporality { + /// A measurement interval that continues to expand forward in time from a + /// starting point. + /// + /// New measurements are added to all previous measurements since a start time. + /// + /// This is the default temporality. + cumulative, + /// A measurement interval that resets each cycle. + /// + /// Measurements from one cycle are recorded independently, measurements from + /// other cycles do not affect them. + delta, + /// Configures Synchronous Counter and Histogram instruments to use + /// Delta aggregation temporality, which allows them to shed memory + /// following a cardinality explosion, thus use less memory. + low-memory, + } + + /// The number types available for any given instrument. + variant metric-number { + %f64(f64), + %s64(s64), + %u64(u64), + } +} diff --git a/wit/deps/otel/tracing.wit b/wit/deps/otel/tracing.wit new file mode 100644 index 0000000000..1143e9bcd4 --- /dev/null +++ b/wit/deps/otel/tracing.wit @@ -0,0 +1,122 @@ +interface tracing { + use wasi:clocks/wall-clock@0.2.0.{datetime}; + use types.{key-value, instrumentation-scope}; + + /// Called when a span is started. + on-start: func(context: span-context); + + /// Called when a span is ended. + on-end: func(span: span-data); + + /// Returns the span context of the host. + outer-span-context: func() -> span-context; + + /// The data associated with a span. + record span-data { + /// Span context. + span-context: span-context, + /// Span parent id. + parent-span-id: string, + /// Span kind. + span-kind: span-kind, + // Span name. + name: string, + /// Span start time. + start-time: datetime, + /// Span end time. + end-time: datetime, + /// Span attributes. + attributes: list, + /// Span events. + events: list, + /// Span Links. + links: list, + /// Span status. + status: status, + /// Instrumentation scope that produced this span. + instrumentation-scope: instrumentation-scope, + /// Number of attributes dropped by the span due to limits being reached. + dropped-attributes: u32, + /// Number of events dropped by the span due to limits being reached. + dropped-events: u32, + /// Number of links dropped by the span due to limits being reached. + dropped-links: u32, + } + + /// Identifying trace information about a span that can be serialized and propagated. + record span-context { + /// The `trace-id` for this `span-context`. + trace-id: trace-id, + /// The `span-id` for this `span-context`. + span-id: span-id, + /// The `trace-flags` for this `span-context`. + trace-flags: trace-flags, + /// Whether this `span-context` was propagated from a remote parent. + is-remote: bool, + /// The `trace-state` for this `span-context`. + trace-state: trace-state, + } + + /// The trace that this `span-context` belongs to. + /// + /// 16 bytes encoded as a hexadecimal string. + type trace-id = string; + + /// The id of this `span-context`. + /// + /// 8 bytes encoded as a hexadecimal string. + type span-id = string; + + /// Flags that can be set on a `span-context`. + flags trace-flags { + /// Whether the `span` should be sampled or not. + sampled, + } + + /// Carries system-specific configuration data, represented as a list of key-value pairs. `trace-state` allows multiple tracing systems to participate in the same trace. + /// + /// If any invalid keys or values are provided then the `trace-state` will be treated as an empty list. + type trace-state = list>; + + /// Describes the relationship between the Span, its parents, and its children in a trace. + enum span-kind { + /// Indicates that the span describes a request to some remote service. This span is usually the parent of a remote server span and does not end until the response is received. + client, + /// Indicates that the span covers server-side handling of a synchronous RPC or other remote request. This span is often the child of a remote client span that was expected to wait for a response. + server, + /// Indicates that the span describes the initiators of an asynchronous request. This parent span will often end before the corresponding child consumer span, possibly even before the child span starts. In messaging scenarios with batching, tracing individual messages requires a new producer span per message to be created. + producer, + /// Indicates that the span describes a child of an asynchronous consumer request. + consumer, + /// Default value. Indicates that the span represents an internal operation within an application, as opposed to an operations with remote parents or children. + internal + } + + /// An event describing a specific moment in time on a span and associated attributes. + record event { + /// Event name. + name: string, + /// Event time. + time: datetime, + /// Event attributes. + attributes: list, + } + + /// Describes a relationship to another `span`. + record link { + /// Denotes which `span` to link to. + span-context: span-context, + /// Attributes describing the link. + attributes: list, + } + + /// The `status` of a `span`. + variant status { + /// The default status. + unset, + /// The operation has been validated by an Application developer or Operator to have completed successfully. + ok, + /// The operation contains an error with a description. + error(string), + } +} diff --git a/wit/deps/otel/types.wit b/wit/deps/otel/types.wit new file mode 100644 index 0000000000..f9c30c9869 --- /dev/null +++ b/wit/deps/otel/types.wit @@ -0,0 +1,48 @@ +interface types { + /// A key-value pair describing an attribute. + record key-value { + /// The attribute name. + key: key, + /// The attribute value. + value: value, + } + + /// The key part of attribute `key-value` pairs. + type key = string; + + /// The value part of attribute `key-value` pairs. + variant value { + /// A string value. + %string(string), + /// A boolean value. + %bool(bool), + /// A double precision floating point value. + %f64(f64), + /// A signed 64 bit integer value. + %s64(s64), + /// A homogeneous array of string values. + string-array(list), + /// A homogeneous array of boolean values. + bool-array(list), + /// A homogeneous array of double precision floating point values. + f64-array(list), + /// A homogeneous array of 64 bit integer values. + s64-array(list), + } + + /// Describes the instrumentation scope that produced telemetry. + record instrumentation-scope { + /// Name of the instrumentation scope. + name: string, + + /// The library version. + version: option, + + /// Schema URL used by this library. + /// https://github.com/open-telemetry/opentelemetry-specification/blob/v1.9.0/specification/schemas/overview.md#schema-url + schema-url: option, + + /// Specifies the instrumentation scope attributes to associate with emitted telemetry. + attributes: list, + } +} diff --git a/wit/deps/otel/world.wit b/wit/deps/otel/world.wit new file mode 100644 index 0000000000..5824151cba --- /dev/null +++ b/wit/deps/otel/world.wit @@ -0,0 +1,7 @@ +package wasi:otel@0.2.0-draft; + +world imports { + import types; + import tracing; + import metrics; +} diff --git a/wit/world.wit b/wit/world.wit index efae2758ef..2fd63b700b 100644 --- a/wit/world.wit +++ b/wit/world.wit @@ -10,6 +10,7 @@ world http-trigger { world platform { include wasi:cli/imports@0.3.0-rc-2025-09-16; import wasi:http/handler@0.3.0-rc-2025-09-16; + include wasi:otel/imports@0.2.0-draft; include fermyon:spin/platform@2.0.0; include wasi:keyvalue/imports@0.2.0-draft2; import spin:postgres/postgres@3.0.0; From 44282321ec26b7a4814a94756cf4a55d4d8b812c Mon Sep 17 00:00:00 2001 From: Andrew Steurer <94206073+asteurer@users.noreply.github.com> Date: Fri, 21 Nov 2025 00:01:17 +0000 Subject: [PATCH 02/13] fix(wasi-otel): misc refactoring Signed-off-by: Andrew Steurer <94206073+asteurer@users.noreply.github.com> --- Cargo.lock | 13 +- crates/factor-key-value/src/host.rs | 6 +- crates/factor-key-value/src/lib.rs | 6 +- crates/factor-llm/src/lib.rs | 6 +- crates/factor-otel/Cargo.toml | 2 +- crates/factor-otel/src/host.rs | 3 +- crates/factor-otel/src/lib.rs | 15 +- crates/factor-outbound-http/src/lib.rs | 6 +- crates/factor-outbound-mqtt/src/host.rs | 6 +- crates/factor-outbound-mqtt/src/lib.rs | 4 +- crates/factor-outbound-mysql/src/lib.rs | 6 +- crates/factor-outbound-pg/src/lib.rs | 10 +- crates/factor-outbound-redis/src/host.rs | 4 +- crates/factor-outbound-redis/src/lib.rs | 4 +- crates/factor-sqlite/src/host.rs | 6 +- crates/factor-sqlite/src/lib.rs | 4 +- crates/factor-variables/src/lib.rs | 6 +- crates/trigger-http/src/wasi.rs | 1 - crates/wasi-otel/Cargo.toml | 12 + crates/wasi-otel/src/conversions.rs | 484 ++++++++++++++++++++++ crates/wasi-otel/src/lib.rs | 49 +++ crates/world/src/conversions.rs | 492 ----------------------- 22 files changed, 604 insertions(+), 541 deletions(-) create mode 100644 crates/wasi-otel/Cargo.toml create mode 100644 crates/wasi-otel/src/conversions.rs create mode 100644 crates/wasi-otel/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index b5af3917d7..1d4e504fbf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8792,10 +8792,10 @@ dependencies = [ "spin-factors", "spin-resource-table", "spin-telemetry", - "spin-world", "toml 0.5.11", "tracing", "tracing-opentelemetry", + "wasi-otel", ] [[package]] @@ -11074,6 +11074,17 @@ version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" +[[package]] +name = "wasi-otel" +version = "3.6.0-pre0" +dependencies = [ + "anyhow", + "async-trait", + "opentelemetry", + "opentelemetry_sdk", + "wasmtime", +] + [[package]] name = "wasip2" version = "1.0.1+wasi-0.2.4" diff --git a/crates/factor-key-value/src/host.rs b/crates/factor-key-value/src/host.rs index a7aef7005c..eda69ace6d 100644 --- a/crates/factor-key-value/src/host.rs +++ b/crates/factor-key-value/src/host.rs @@ -1,7 +1,7 @@ use super::{Cas, SwapError}; use anyhow::{Context, Result}; use spin_core::{async_trait, wasmtime::component::Resource}; -use spin_factor_otel::OtelContext; +use spin_factor_otel::OtelFactorState; use spin_resource_table::Table; use spin_telemetry::traces::{self, Blame}; use spin_world::v2::key_value; @@ -50,7 +50,7 @@ pub struct KeyValueDispatch { manager: Arc, stores: Table>, compare_and_swaps: Table>, - otel_context: Option, + otel_context: Option, } impl KeyValueDispatch { @@ -62,7 +62,7 @@ impl KeyValueDispatch { allowed_stores: HashSet, manager: Arc, capacity: u32, - otel_context: Option, + otel_context: Option, ) -> Self { Self { allowed_stores, diff --git a/crates/factor-key-value/src/lib.rs b/crates/factor-key-value/src/lib.rs index 62929a75ff..a9650baa40 100644 --- a/crates/factor-key-value/src/lib.rs +++ b/crates/factor-key-value/src/lib.rs @@ -8,7 +8,7 @@ use std::{ }; use anyhow::ensure; -use spin_factor_otel::OtelContext; +use spin_factor_otel::OtelFactorState; use spin_factors::{ ConfigureAppContext, Factor, FactorData, FactorInstanceBuilder, InitContext, PrepareContext, RuntimeFactors, @@ -96,7 +96,7 @@ impl Factor for KeyValueFactor { .get(ctx.app_component().id()) .expect("component should be in component_stores") .clone(); - let otel_context = OtelContext::from_prepare_context(&mut ctx)?; + let otel_context = OtelFactorState::from_prepare_context(&mut ctx)?; Ok(InstanceBuilder { store_manager: app_state.store_manager.clone(), allowed_stores, @@ -180,7 +180,7 @@ pub struct InstanceBuilder { store_manager: Arc, /// The allowed stores for this component instance. allowed_stores: HashSet, - otel_context: OtelContext, + otel_context: OtelFactorState, } impl FactorInstanceBuilder for InstanceBuilder { diff --git a/crates/factor-llm/src/lib.rs b/crates/factor-llm/src/lib.rs index b3e5c6a700..106594beeb 100644 --- a/crates/factor-llm/src/lib.rs +++ b/crates/factor-llm/src/lib.rs @@ -5,7 +5,7 @@ use std::collections::{HashMap, HashSet}; use std::sync::Arc; use async_trait::async_trait; -use spin_factor_otel::OtelContext; +use spin_factor_otel::OtelFactorState; use spin_factors::{ ConfigureAppContext, Factor, FactorData, PrepareContext, RuntimeFactors, SelfInstanceBuilder, }; @@ -83,7 +83,7 @@ impl Factor for LlmFactor { .cloned() .unwrap_or_default(); let engine = ctx.app_state().engine.clone(); - let otel_context = OtelContext::from_prepare_context(&mut ctx)?; + let otel_context = OtelFactorState::from_prepare_context(&mut ctx)?; Ok(InstanceState { engine, @@ -103,7 +103,7 @@ pub struct AppState { pub struct InstanceState { engine: Arc>, pub allowed_models: Arc>, - otel_context: OtelContext, + otel_context: OtelFactorState, } /// The runtime configuration for the LLM factor. diff --git a/crates/factor-otel/Cargo.toml b/crates/factor-otel/Cargo.toml index 1dcdb98c82..eb51afc54c 100644 --- a/crates/factor-otel/Cargo.toml +++ b/crates/factor-otel/Cargo.toml @@ -14,7 +14,7 @@ spin-core = { path = "../core" } spin-factors = { path = "../factors" } spin-resource-table = { path = "../table" } spin-telemetry = { path = "../telemetry" } -spin-world = { path = "../world" } +wasi-otel = { path = "../wasi-otel" } tracing = { workspace = true } tracing-opentelemetry = { workspace = true } diff --git a/crates/factor-otel/src/host.rs b/crates/factor-otel/src/host.rs index 8ece27d5b1..b9b7baf5c3 100644 --- a/crates/factor-otel/src/host.rs +++ b/crates/factor-otel/src/host.rs @@ -5,8 +5,9 @@ use opentelemetry::trace::TraceContextExt; use opentelemetry_sdk::error::OTelSdkError; use opentelemetry_sdk::metrics::exporter::PushMetricExporter; use opentelemetry_sdk::trace::SpanProcessor; -use spin_world::wasi; use tracing_opentelemetry::OpenTelemetrySpanExt; +// TODO: This feels weird. I'm wondering if it can be fixed by wrangling the bindgen macro in `crates/wasi_otel/lib.rs`. +use wasi_otel::wasi; impl wasi::otel::tracing::Host for InstanceState { async fn on_start(&mut self, context: wasi::otel::tracing::SpanContext) -> Result<()> { diff --git a/crates/factor-otel/src/lib.rs b/crates/factor-otel/src/lib.rs index c224ce3730..8563bd17ff 100644 --- a/crates/factor-otel/src/lib.rs +++ b/crates/factor-otel/src/lib.rs @@ -29,8 +29,9 @@ impl Factor for OtelFactor { type InstanceBuilder = InstanceState; fn init(&mut self, ctx: &mut impl spin_factors::InitContext) -> anyhow::Result<()> { - ctx.link_bindings(spin_world::wasi::otel::tracing::add_to_linker::<_, FactorData>)?; - ctx.link_bindings(spin_world::wasi::otel::metrics::add_to_linker::<_, FactorData>)?; + // TODO: This feels weird. I'm wondering if it can be fixed by wrangling the bindgen macro in `crates/wasi_otel/lib.rs`. + ctx.link_bindings(wasi_otel::wasi::otel::tracing::add_to_linker::<_, FactorData>)?; + ctx.link_bindings(wasi_otel::wasi::otel::metrics::add_to_linker::<_, FactorData>)?; Ok(()) } @@ -135,15 +136,15 @@ pub(crate) struct State { /// Manages access to the OtelFactor state for the purpose of maintaining proper span /// parent/child relationships when WASI Otel spans are being created. -pub struct OtelContext { +pub struct OtelFactorState { pub(crate) state: Option>>, } -impl OtelContext { - /// Creates an [`OtelContext`] from a [`PrepareContext`]. +impl OtelFactorState { + /// Creates an [`OtelFactorState`] from a [`PrepareContext`]. /// /// If [`RuntimeFactors`] does not contain an [`OtelFactor`], then calling - /// [`OtelContext::reparent_tracing_span`] will be a no-op. + /// [`OtelFactorState::reparent_tracing_span`] will be a no-op. pub fn from_prepare_context( prepare_context: &mut PrepareContext, ) -> anyhow::Result { @@ -170,7 +171,7 @@ impl OtelContext { /// /// Setting the guest spans parent as the host is enabled through current_span_context. /// However, the more difficult task is having the host factor spans be children of the guest - /// span. [`OtelContext::reparent_tracing_span`] handles this by reparenting the current span to + /// span. [`OtelFactorState::reparent_tracing_span`] handles this by reparenting the current span to /// be a child of the last active guest span (which is tracked internally in the otel factor). /// /// Note that if the otel factor is not in your [`RuntimeFactors`] than this is effectively a diff --git a/crates/factor-outbound-http/src/lib.rs b/crates/factor-outbound-http/src/lib.rs index 5a24570a5f..bb712b9d94 100644 --- a/crates/factor-outbound-http/src/lib.rs +++ b/crates/factor-outbound-http/src/lib.rs @@ -14,7 +14,7 @@ use http::{ }; use intercept::OutboundHttpInterceptor; use runtime_config::RuntimeConfig; -use spin_factor_otel::OtelContext; +use spin_factor_otel::OtelFactorState; use spin_factor_outbound_networking::{ config::{allowed_hosts::OutboundAllowedHosts, blocked_networks::BlockedNetworks}, ComponentTlsClientConfigs, OutboundNetworkingFactor, @@ -75,7 +75,7 @@ impl Factor for OutboundHttpFactor { let allowed_hosts = outbound_networking.allowed_hosts(); let blocked_networks = outbound_networking.blocked_networks(); let component_tls_configs = outbound_networking.component_tls_configs(); - let otel_context = OtelContext::from_prepare_context(&mut ctx)?; + let otel_context = OtelFactorState::from_prepare_context(&mut ctx)?; Ok(InstanceState { wasi_http_ctx: WasiHttpCtx::new(), allowed_hosts, @@ -118,7 +118,7 @@ pub struct InstanceState { /// A semaphore to limit the number of concurrent outbound connections. concurrent_outbound_connections_semaphore: Option>, /// Manages access to the OtelFactor state. - otel_context: OtelContext, + otel_context: OtelFactorState, } impl InstanceState { diff --git a/crates/factor-outbound-mqtt/src/host.rs b/crates/factor-outbound-mqtt/src/host.rs index 53cb6a9830..a39d1a4b60 100644 --- a/crates/factor-outbound-mqtt/src/host.rs +++ b/crates/factor-outbound-mqtt/src/host.rs @@ -2,9 +2,9 @@ use std::{sync::Arc, time::Duration}; use anyhow::Result; use spin_core::{async_trait, wasmtime::component::Resource}; +use spin_factor_otel::OtelFactorState; use spin_factor_outbound_networking::config::allowed_hosts::OutboundAllowedHosts; use spin_world::v2::mqtt::{self as v2, Connection, Error, Qos}; -use spin_factor_otel::OtelContext; use tracing::{instrument, Level}; use crate::ClientCreator; @@ -13,14 +13,14 @@ pub struct InstanceState { allowed_hosts: OutboundAllowedHosts, connections: spin_resource_table::Table>, create_client: Arc, - otel_context: OtelContext, + otel_context: OtelFactorState, } impl InstanceState { pub fn new( allowed_hosts: OutboundAllowedHosts, create_client: Arc, - otel_context: OtelContext, + otel_context: OtelFactorState, ) -> Self { Self { allowed_hosts, diff --git a/crates/factor-outbound-mqtt/src/lib.rs b/crates/factor-outbound-mqtt/src/lib.rs index 250aa09d5c..7297624696 100644 --- a/crates/factor-outbound-mqtt/src/lib.rs +++ b/crates/factor-outbound-mqtt/src/lib.rs @@ -7,7 +7,7 @@ use host::other_error; use host::InstanceState; use rumqttc::{AsyncClient, Event, Incoming, Outgoing, QoS}; use spin_core::async_trait; -use spin_factor_otel::OtelContext; +use spin_factor_otel::OtelFactorState; use spin_factor_outbound_networking::OutboundNetworkingFactor; use spin_factors::{ ConfigureAppContext, Factor, FactorData, PrepareContext, RuntimeFactors, SelfInstanceBuilder, @@ -51,7 +51,7 @@ impl Factor for OutboundMqttFactor { let allowed_hosts = ctx .instance_builder::()? .allowed_hosts(); - let otel_context = OtelContext::from_prepare_context(&mut ctx)?; + let otel_context = OtelFactorState::from_prepare_context(&mut ctx)?; Ok(InstanceState::new( allowed_hosts, diff --git a/crates/factor-outbound-mysql/src/lib.rs b/crates/factor-outbound-mysql/src/lib.rs index e1bf9aabdb..2e6faddc84 100644 --- a/crates/factor-outbound-mysql/src/lib.rs +++ b/crates/factor-outbound-mysql/src/lib.rs @@ -3,7 +3,7 @@ mod host; use client::Client; use mysql_async::Conn as MysqlClient; -use spin_factor_otel::OtelContext; +use spin_factor_otel::OtelFactorState; use spin_factor_outbound_networking::{ config::allowed_hosts::OutboundAllowedHosts, OutboundNetworkingFactor, }; @@ -40,7 +40,7 @@ impl Factor for OutboundMysqlFactor { let allowed_hosts = ctx .instance_builder::()? .allowed_hosts(); - let otel_context = OtelContext::from_prepare_context(&mut ctx)?; + let otel_context = OtelFactorState::from_prepare_context(&mut ctx)?; Ok(InstanceState { allowed_hosts, @@ -67,7 +67,7 @@ impl OutboundMysqlFactor { pub struct InstanceState { allowed_hosts: OutboundAllowedHosts, connections: spin_resource_table::Table, - otel_context: OtelContext, + otel_context: OtelFactorState, } impl SelfInstanceBuilder for InstanceState {} diff --git a/crates/factor-outbound-pg/src/lib.rs b/crates/factor-outbound-pg/src/lib.rs index a793271fef..37c7f13573 100644 --- a/crates/factor-outbound-pg/src/lib.rs +++ b/crates/factor-outbound-pg/src/lib.rs @@ -2,11 +2,8 @@ pub mod client; mod host; mod types; -use std::sync::Arc; - -use client::Client; use client::ClientFactory; -use spin_factor_otel::OtelContext; +use spin_factor_otel::OtelFactorState; use spin_factor_outbound_networking::{ config::allowed_hosts::OutboundAllowedHosts, OutboundNetworkingFactor, }; @@ -14,6 +11,7 @@ use spin_factors::{ anyhow, ConfigureAppContext, Factor, FactorData, PrepareContext, RuntimeFactors, SelfInstanceBuilder, }; +use std::sync::Arc; pub struct OutboundPgFactor { _phantom: std::marker::PhantomData, @@ -50,7 +48,7 @@ impl Factor for OutboundPgFactor { let allowed_hosts = ctx .instance_builder::()? .allowed_hosts(); - let otel_context = OtelContext::from_prepare_context(&mut ctx)?; + let otel_context = OtelFactorState::from_prepare_context(&mut ctx)?; Ok(InstanceState { allowed_hosts, @@ -79,7 +77,7 @@ pub struct InstanceState { allowed_hosts: OutboundAllowedHosts, client_factory: Arc, connections: spin_resource_table::Table, - otel_context: OtelContext, + otel_context: OtelFactorState, } impl SelfInstanceBuilder for InstanceState {} diff --git a/crates/factor-outbound-redis/src/host.rs b/crates/factor-outbound-redis/src/host.rs index ac1c817ebb..2f265b90dc 100644 --- a/crates/factor-outbound-redis/src/host.rs +++ b/crates/factor-outbound-redis/src/host.rs @@ -5,7 +5,7 @@ use redis::io::AsyncDNSResolver; use redis::AsyncConnectionConfig; use redis::{aio::MultiplexedConnection, AsyncCommands, FromRedisValue, Value}; use spin_core::wasmtime::component::Resource; -use spin_factor_otel::OtelContext; +use spin_factor_otel::OtelFactorState; use spin_factor_outbound_networking::config::allowed_hosts::OutboundAllowedHosts; use spin_factor_outbound_networking::config::blocked_networks::BlockedNetworks; use spin_world::v1::{redis as v1, redis_types}; @@ -19,7 +19,7 @@ pub struct InstanceState { pub allowed_hosts: OutboundAllowedHosts, pub blocked_networks: BlockedNetworks, pub connections: spin_resource_table::Table, - pub otel_context: OtelContext, + pub otel_context: OtelFactorState, } impl InstanceState { diff --git a/crates/factor-outbound-redis/src/lib.rs b/crates/factor-outbound-redis/src/lib.rs index 09bf410931..d432bf5c51 100644 --- a/crates/factor-outbound-redis/src/lib.rs +++ b/crates/factor-outbound-redis/src/lib.rs @@ -1,7 +1,7 @@ mod host; use host::InstanceState; -use spin_factor_otel::OtelContext; +use spin_factor_otel::OtelFactorState; use spin_factor_outbound_networking::OutboundNetworkingFactor; use spin_factors::{ anyhow, ConfigureAppContext, Factor, FactorData, PrepareContext, RuntimeFactors, @@ -42,7 +42,7 @@ impl Factor for OutboundRedisFactor { &self, mut ctx: PrepareContext, ) -> anyhow::Result { - let otel_context = OtelContext::from_prepare_context(&mut ctx)?; + let otel_context = OtelFactorState::from_prepare_context(&mut ctx)?; let outbound_networking = ctx.instance_builder::()?; Ok(InstanceState { diff --git a/crates/factor-sqlite/src/host.rs b/crates/factor-sqlite/src/host.rs index e6ed819a54..ddc6d0f5a8 100644 --- a/crates/factor-sqlite/src/host.rs +++ b/crates/factor-sqlite/src/host.rs @@ -1,7 +1,7 @@ use std::collections::{HashMap, HashSet}; use std::sync::Arc; -use spin_factor_otel::OtelContext; +use spin_factor_otel::OtelFactorState; use spin_factors::wasmtime::component::Resource; use spin_factors::{anyhow, SelfInstanceBuilder}; use spin_world::spin::sqlite::sqlite as v3; @@ -18,7 +18,7 @@ pub struct InstanceState { connections: spin_resource_table::Table>, /// A map from database label to connection creators. connection_creators: HashMap>, - otel_context: OtelContext, + otel_context: OtelFactorState, } impl InstanceState { @@ -28,7 +28,7 @@ impl InstanceState { pub fn new( allowed_databases: Arc>, connection_creators: HashMap>, - otel_context: OtelContext, + otel_context: OtelFactorState, ) -> Self { Self { allowed_databases, diff --git a/crates/factor-sqlite/src/lib.rs b/crates/factor-sqlite/src/lib.rs index ae3b4686e0..cf7d955680 100644 --- a/crates/factor-sqlite/src/lib.rs +++ b/crates/factor-sqlite/src/lib.rs @@ -7,8 +7,8 @@ use std::sync::Arc; use host::InstanceState; use async_trait::async_trait; +use spin_factor_otel::OtelFactorState; use spin_factors::{anyhow, Factor, FactorData}; -use spin_factor_otel::OtelContext; use spin_locked_app::MetadataKey; use spin_world::spin::sqlite::sqlite as v3; use spin_world::v1::sqlite as v1; @@ -83,7 +83,7 @@ impl Factor for SqliteFactor { .get(ctx.app_component().id()) .cloned() .unwrap_or_default(); - let otel_context = OtelContext::from_prepare_context(&mut ctx)?; + let otel_context = OtelFactorState::from_prepare_context(&mut ctx)?; Ok(InstanceState::new( allowed_databases, ctx.app_state().connection_creators.clone(), diff --git a/crates/factor-variables/src/lib.rs b/crates/factor-variables/src/lib.rs index 43d489ecae..7801b9f18e 100644 --- a/crates/factor-variables/src/lib.rs +++ b/crates/factor-variables/src/lib.rs @@ -5,7 +5,7 @@ use std::sync::Arc; use runtime_config::RuntimeConfig; use spin_expressions::{ProviderResolver as ExpressionResolver, Template}; -use spin_factor_otel::OtelContext; +use spin_factor_otel::OtelFactorState; use spin_factors::{ anyhow, ConfigureAppContext, Factor, FactorData, InitContext, PrepareContext, RuntimeFactors, SelfInstanceBuilder, @@ -67,7 +67,7 @@ impl Factor for VariablesFactor { ) -> anyhow::Result { let component_id = ctx.app_component().id().to_string(); let expression_resolver = ctx.app_state().expression_resolver.clone(); - let otel_context = OtelContext::from_prepare_context(&mut ctx)?; + let otel_context = OtelFactorState::from_prepare_context(&mut ctx)?; Ok(InstanceState { component_id, expression_resolver, @@ -97,7 +97,7 @@ impl AppState { pub struct InstanceState { component_id: String, expression_resolver: Arc, - otel_context: OtelContext, + otel_context: OtelFactorState, } impl InstanceState { diff --git a/crates/trigger-http/src/wasi.rs b/crates/trigger-http/src/wasi.rs index 1116face6a..f506f08591 100644 --- a/crates/trigger-http/src/wasi.rs +++ b/crates/trigger-http/src/wasi.rs @@ -107,7 +107,6 @@ impl HttpExecutor for WasiHttpExecutor<'_> { HandlerType::Wagi(_) => unreachable!("should have used WagiExecutor instead"), }; - let span = tracing::debug_span!("execute_wasi"); let handle = task::spawn( async move { let result = match handler { diff --git a/crates/wasi-otel/Cargo.toml b/crates/wasi-otel/Cargo.toml new file mode 100644 index 0000000000..b923f7b938 --- /dev/null +++ b/crates/wasi-otel/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "wasi-otel" +version = { workspace = true } +authors = { workspace = true } +edition = { workspace = true } + +[dependencies] +anyhow = { workspace = true } +async-trait = { workspace = true } +opentelemetry = { workspace = true } +opentelemetry_sdk = { workspace = true } +wasmtime = { workspace = true } diff --git a/crates/wasi-otel/src/conversions.rs b/crates/wasi-otel/src/conversions.rs new file mode 100644 index 0000000000..d8b21719ce --- /dev/null +++ b/crates/wasi-otel/src/conversions.rs @@ -0,0 +1,484 @@ +use super::*; +use opentelemetry::StringValue; +use opentelemetry_sdk::trace::{SpanEvents, SpanLinks}; +use std::borrow::Cow; +use std::time::{Duration, SystemTime, UNIX_EPOCH}; +use wasi::clocks0_2_0::wall_clock; + +impl From + for opentelemetry_sdk::metrics::data::ResourceMetrics +{ + fn from(value: wasi::otel::metrics::ResourceMetrics) -> Self { + Self { + resource: value.resource.into(), + scope_metrics: value.scope_metrics.into_iter().map(Into::into).collect(), + } + } +} + +impl From for opentelemetry_sdk::Resource { + fn from(value: wasi::otel::metrics::Resource) -> Self { + let attributes: Vec = + value.attributes.into_iter().map(Into::into).collect(); + let schema_url: Option = value.schema_url; + match schema_url { + Some(url) => opentelemetry_sdk::resource::Resource::builder() + .with_schema_url(attributes, url) + .build(), + None => opentelemetry_sdk::resource::Resource::builder() + .with_attributes(attributes) + .build(), + } + } +} + +impl From for opentelemetry_sdk::metrics::data::ScopeMetrics { + fn from(value: wasi::otel::metrics::ScopeMetrics) -> Self { + Self { + scope: value.scope.into(), + metrics: value.metrics.into_iter().map(Into::into).collect(), + } + } +} + +impl From for opentelemetry_sdk::metrics::data::Metric { + fn from(value: wasi::otel::metrics::Metric) -> Self { + Self { + name: Cow::Owned(value.name), + description: Cow::Owned(value.description), + unit: Cow::Owned(value.unit), + data: value.data.into(), + } + } +} + +/// Converts a Wasi exemplar to an OTel exemplar +macro_rules! exemplars_to_otel { + ( + $wasi_exemplar_list:expr, + $exemplar_type:ty + ) => { + $wasi_exemplar_list + .iter() + .map(|e| { + let span_id: [u8; 8] = e + .span_id + .as_bytes() + .try_into() + .expect("failed to parse span ID"); + let trace_id: [u8; 16] = e + .trace_id + .as_bytes() + .try_into() + .expect("failed to parse trace ID"); + opentelemetry_sdk::metrics::data::Exemplar::<$exemplar_type> { + filtered_attributes: e + .filtered_attributes + .to_owned() + .into_iter() + .map(Into::into) + .collect(), + time: e.time.into(), + value: e.value.into(), + span_id, + trace_id, + } + }) + .collect() + }; +} + +/// Converts a WASI Gauge to an OTel Gauge +macro_rules! wasi_gauge_to_otel { + ($gauge:expr, $number_type:ty) => { + Box::new(opentelemetry_sdk::metrics::data::Gauge { + data_points: $gauge + .data_points + .iter() + .map(|dp| opentelemetry_sdk::metrics::data::GaugeDataPoint { + attributes: dp.attributes.iter().map(Into::into).collect(), + value: dp.value.into(), + exemplars: exemplars_to_otel!(dp.exemplars, $number_type), + }) + .collect(), + start_time: match $gauge.start_time { + Some(t) => Some(t.into()), + None => None, + }, + time: $gauge.time.into(), + }) + }; +} + +/// Converts a WASI Sum to an OTel Sum +macro_rules! wasi_sum_to_otel { + ($sum:expr, $number_type:ty) => { + Box::new(opentelemetry_sdk::metrics::data::Sum { + data_points: $sum + .data_points + .iter() + .map(|dp| opentelemetry_sdk::metrics::data::SumDataPoint { + attributes: dp.attributes.iter().map(Into::into).collect(), + exemplars: exemplars_to_otel!(dp.exemplars, $number_type), + value: dp.value.into(), + }) + .collect(), + start_time: $sum.start_time.into(), + time: $sum.time.into(), + temporality: $sum.temporality.into(), + is_monotonic: $sum.is_monotonic, + }) + }; +} + +/// Converts a WASI Histogram to an OTel Histogram +macro_rules! wasi_histogram_to_otel { + ($histogram:expr, $number_type:ty) => { + Box::new(opentelemetry_sdk::metrics::data::Histogram { + data_points: $histogram + .data_points + .iter() + .map(|dp| opentelemetry_sdk::metrics::data::HistogramDataPoint { + attributes: dp.attributes.iter().map(Into::into).collect(), + bounds: dp.bounds.to_owned(), + bucket_counts: dp.bucket_counts.to_owned(), + exemplars: exemplars_to_otel!(dp.exemplars, $number_type), + count: dp.count, + max: match dp.max { + Some(m) => Some(m.into()), + None => None, + }, + min: match dp.min { + Some(m) => Some(m.into()), + None => None, + }, + sum: dp.sum.into(), + }) + .collect(), + start_time: $histogram.start_time.into(), + time: $histogram.time.into(), + temporality: $histogram.temporality.into(), + }) + }; +} + +/// Converts a WASI ExponentialHistogram to an OTel ExponentialHistogram +macro_rules! wasi_exponential_histogram_to_otel { + ($histogram:expr, $number_type:ty) => { + Box::new(opentelemetry_sdk::metrics::data::ExponentialHistogram { + data_points: $histogram + .data_points + .iter() + .map( + |dp| opentelemetry_sdk::metrics::data::ExponentialHistogramDataPoint { + attributes: dp.attributes.iter().map(Into::into).collect(), + exemplars: exemplars_to_otel!(dp.exemplars, $number_type), + count: dp.count as usize, + max: match dp.max { + Some(m) => Some(m.into()), + None => None, + }, + min: match dp.min { + Some(m) => Some(m.into()), + None => None, + }, + sum: dp.sum.into(), + scale: dp.scale, + zero_count: dp.zero_count, + positive_bucket: dp.positive_bucket.to_owned().into(), + negative_bucket: dp.negative_bucket.to_owned().into(), + zero_threshold: dp.zero_threshold, + }, + ) + .collect(), + start_time: $histogram.start_time.into(), + time: $histogram.time.into(), + temporality: $histogram.temporality.into(), + }) + }; +} + +impl From + for Box +{ + fn from(value: wasi::otel::metrics::MetricData) -> Self { + match value { + wasi::otel::metrics::MetricData::F64Sum(s) => wasi_sum_to_otel!(s, f64), + wasi::otel::metrics::MetricData::S64Sum(s) => wasi_sum_to_otel!(s, i64), + wasi::otel::metrics::MetricData::U64Sum(s) => wasi_sum_to_otel!(s, u64), + wasi::otel::metrics::MetricData::F64Gauge(g) => wasi_gauge_to_otel!(g, f64), + wasi::otel::metrics::MetricData::S64Gauge(g) => wasi_gauge_to_otel!(g, i64), + wasi::otel::metrics::MetricData::U64Gauge(g) => wasi_gauge_to_otel!(g, u64), + wasi::otel::metrics::MetricData::F64Histogram(h) => wasi_histogram_to_otel!(h, f64), + wasi::otel::metrics::MetricData::S64Histogram(h) => wasi_histogram_to_otel!(h, i64), + wasi::otel::metrics::MetricData::U64Histogram(h) => wasi_histogram_to_otel!(h, u64), + wasi::otel::metrics::MetricData::F64ExponentialHistogram(h) => { + wasi_exponential_histogram_to_otel!(h, f64) + } + wasi::otel::metrics::MetricData::S64ExponentialHistogram(h) => { + wasi_exponential_histogram_to_otel!(h, i64) + } + wasi::otel::metrics::MetricData::U64ExponentialHistogram(h) => { + wasi_exponential_histogram_to_otel!(h, u64) + } + } + } +} + +impl From for f64 { + fn from(value: wasi::otel::metrics::MetricNumber) -> Self { + match value { + wasi::otel::metrics::MetricNumber::F64(n) => n, + _ => panic!("error converting WASI MetricNumber to f64"), + } + } +} + +impl From for u64 { + fn from(value: wasi::otel::metrics::MetricNumber) -> Self { + match value { + wasi::otel::metrics::MetricNumber::U64(n) => n, + _ => panic!("error converting WASI MetricNumber to u64"), + } + } +} + +impl From for i64 { + fn from(value: wasi::otel::metrics::MetricNumber) -> Self { + match value { + wasi::otel::metrics::MetricNumber::S64(n) => n, + _ => panic!("error converting WASI MetricNumber to i64"), + } + } +} + +impl From + for opentelemetry_sdk::metrics::data::ExponentialBucket +{ + fn from(value: wasi::otel::metrics::ExponentialBucket) -> Self { + Self { + offset: value.offset, + counts: value.counts, + } + } +} + +impl From for opentelemetry_sdk::metrics::Temporality { + fn from(value: wasi::otel::metrics::Temporality) -> Self { + use opentelemetry_sdk::metrics::Temporality; + match value { + wasi::otel::metrics::Temporality::Cumulative => Temporality::Cumulative, + wasi::otel::metrics::Temporality::Delta => Temporality::Delta, + wasi::otel::metrics::Temporality::LowMemory => Temporality::LowMemory, + } + } +} + +impl From for opentelemetry_sdk::trace::SpanData { + fn from(value: wasi::otel::tracing::SpanData) -> Self { + let mut span_events = SpanEvents::default(); + span_events.events = value.events.into_iter().map(Into::into).collect(); + span_events.dropped_count = value.dropped_events; + let mut span_links = SpanLinks::default(); + span_links.links = value.links.into_iter().map(Into::into).collect(); + span_links.dropped_count = value.dropped_links; + Self { + span_context: value.span_context.into(), + parent_span_id: opentelemetry::trace::SpanId::from_hex(&value.parent_span_id) + .unwrap_or(opentelemetry::trace::SpanId::INVALID), + span_kind: value.span_kind.into(), + name: value.name.into(), + start_time: value.start_time.into(), + end_time: value.end_time.into(), + attributes: value.attributes.into_iter().map(Into::into).collect(), + dropped_attributes_count: value.dropped_attributes, + events: span_events, + links: span_links, + status: value.status.into(), + instrumentation_scope: value.instrumentation_scope.into(), + } + } +} + +impl From for opentelemetry::trace::SpanContext { + fn from(sc: wasi::otel::tracing::SpanContext) -> Self { + let trace_id = opentelemetry::trace::TraceId::from_hex(&sc.trace_id) + .unwrap_or(opentelemetry::trace::TraceId::INVALID); + let span_id = opentelemetry::trace::SpanId::from_hex(&sc.span_id) + .unwrap_or(opentelemetry::trace::SpanId::INVALID); + let trace_state = opentelemetry::trace::TraceState::from_key_value(sc.trace_state) + .unwrap_or_else(|_| opentelemetry::trace::TraceState::default()); + Self::new( + trace_id, + span_id, + sc.trace_flags.into(), + sc.is_remote, + trace_state, + ) + } +} + +impl From for wasi::otel::tracing::SpanContext { + fn from(sc: opentelemetry::trace::SpanContext) -> Self { + Self { + trace_id: format!("{:x}", sc.trace_id()), + span_id: format!("{:x}", sc.span_id()), + trace_flags: sc.trace_flags().into(), + is_remote: sc.is_remote(), + trace_state: sc + .trace_state() + .header() + .split(',') + .filter_map(|s| { + if let Some((key, value)) = s.split_once('=') { + Some((key.to_string(), value.to_string())) + } else { + None + } + }) + .collect(), + } + } +} + +impl From for opentelemetry::trace::TraceFlags { + fn from(flags: wasi::otel::tracing::TraceFlags) -> Self { + Self::new(flags.as_array()[0] as u8) + } +} + +impl From for wasi::otel::tracing::TraceFlags { + fn from(flags: opentelemetry::trace::TraceFlags) -> Self { + if flags.is_sampled() { + wasi::otel::tracing::TraceFlags::SAMPLED + } else { + wasi::otel::tracing::TraceFlags::empty() + } + } +} + +impl From for opentelemetry::trace::SpanKind { + fn from(kind: wasi::otel::tracing::SpanKind) -> Self { + match kind { + wasi::otel::tracing::SpanKind::Client => opentelemetry::trace::SpanKind::Client, + wasi::otel::tracing::SpanKind::Server => opentelemetry::trace::SpanKind::Server, + wasi::otel::tracing::SpanKind::Producer => opentelemetry::trace::SpanKind::Producer, + wasi::otel::tracing::SpanKind::Consumer => opentelemetry::trace::SpanKind::Consumer, + wasi::otel::tracing::SpanKind::Internal => opentelemetry::trace::SpanKind::Internal, + } + } +} + +impl From for opentelemetry::KeyValue { + fn from(kv: wasi::otel::tracing::KeyValue) -> Self { + opentelemetry::KeyValue::new(kv.key, kv.value) + } +} + +impl From<&wasi::otel::tracing::KeyValue> for opentelemetry::KeyValue { + fn from(kv: &wasi::otel::tracing::KeyValue) -> Self { + opentelemetry::KeyValue::new(kv.key.to_owned(), kv.value.to_owned()) + } +} + +impl From for opentelemetry::Value { + fn from(value: wasi::otel::types::Value) -> Self { + match value { + wasi::otel::types::Value::String(v) => v.into(), + wasi::otel::types::Value::Bool(v) => v.into(), + wasi::otel::types::Value::F64(v) => v.into(), + wasi::otel::types::Value::S64(v) => v.into(), + wasi::otel::types::Value::StringArray(v) => opentelemetry::Value::Array( + v.into_iter() + .map(StringValue::from) + .collect::>() + .into(), + ), + wasi::otel::types::Value::BoolArray(v) => opentelemetry::Value::Array(v.into()), + wasi::otel::types::Value::F64Array(v) => opentelemetry::Value::Array(v.into()), + wasi::otel::types::Value::S64Array(v) => opentelemetry::Value::Array(v.into()), + } + } +} + +impl From for opentelemetry::trace::Event { + fn from(event: wasi::otel::tracing::Event) -> Self { + Self::new( + event.name, + event.time.into(), + event.attributes.into_iter().map(Into::into).collect(), + 0, + ) + } +} + +impl From for opentelemetry::trace::Link { + fn from(link: wasi::otel::tracing::Link) -> Self { + Self::new( + link.span_context.into(), + link.attributes.into_iter().map(Into::into).collect(), + 0, + ) + } +} + +impl From for opentelemetry::trace::Status { + fn from(status: wasi::otel::tracing::Status) -> Self { + match status { + wasi::otel::tracing::Status::Unset => Self::Unset, + wasi::otel::tracing::Status::Ok => Self::Ok, + wasi::otel::tracing::Status::Error(s) => Self::Error { + description: s.into(), + }, + } + } +} + +impl From for opentelemetry::InstrumentationScope { + fn from(value: wasi::otel::tracing::InstrumentationScope) -> Self { + let builder = + Self::builder(value.name).with_attributes(value.attributes.into_iter().map(Into::into)); + match (value.version, value.schema_url) { + (Some(version), Some(schema_url)) => builder + .with_version(version) + .with_schema_url(schema_url) + .build(), + (Some(version), None) => builder.with_version(version).build(), + (None, Some(schema_url)) => builder.with_schema_url(schema_url).build(), + (None, None) => builder.build(), + } + } +} + +impl From for SystemTime { + fn from(timestamp: wall_clock::Datetime) -> Self { + UNIX_EPOCH + + Duration::from_secs(timestamp.seconds) + + Duration::from_nanos(timestamp.nanoseconds as u64) + } +} + +mod test { + #[test] + fn trace_flags() { + let flags = opentelemetry::trace::TraceFlags::SAMPLED; + let flags2 = crate::wasi::otel::tracing::TraceFlags::from(flags); + let flags3 = opentelemetry::trace::TraceFlags::from(flags2); + assert_eq!(flags, flags3); + } + + #[test] + fn span_context() { + let sc = opentelemetry::trace::SpanContext::new( + opentelemetry::trace::TraceId::from_hex("4fb34cb4484029f7881399b149e41e98").unwrap(), + opentelemetry::trace::SpanId::from_hex("9ffd58d3cd4dd90b").unwrap(), + opentelemetry::trace::TraceFlags::SAMPLED, + false, + opentelemetry::trace::TraceState::from_key_value(vec![("foo", "bar"), ("baz", "qux")]) + .unwrap(), + ); + let sc2 = crate::wasi::otel::tracing::SpanContext::from(sc.clone()); + let sc3 = opentelemetry::trace::SpanContext::from(sc2); + assert_eq!(sc, sc3); + } +} diff --git a/crates/wasi-otel/src/lib.rs b/crates/wasi-otel/src/lib.rs new file mode 100644 index 0000000000..52c8a5e63f --- /dev/null +++ b/crates/wasi-otel/src/lib.rs @@ -0,0 +1,49 @@ +#![allow(missing_docs)] +#![allow(non_camel_case_types)] // bindgen emits Host_Pre and Host_Indices + +pub use async_trait::async_trait; + +wasmtime::component::bindgen!({ + inline: r#" + package fermyon:runtime; + world host { + include fermyon:spin/host; + include fermyon:spin/platform@2.0.0; + include fermyon:spin/platform@3.0.0; + include spin:up/platform@3.2.0; + include spin:up/platform@3.4.0; + include spin:up/platform@3.5.0; + include wasi:keyvalue/imports@0.2.0-draft2; + } + "#, + path: "../../wit", + imports: { default: async | trappable }, + exports: { default: async }, + // The following is a roundabout way of saying "the host implementations for these interfaces don't trap" + trappable_error_type: { + "fermyon:spin/config/error" => v1::config::Error, + "fermyon:spin/http-types/http-error" => v1::http_types::HttpError, + "fermyon:spin/llm@2.0.0/error" => v2::llm::Error, + "fermyon:spin/llm/error" => v1::llm::Error, + "fermyon:spin/mqtt@2.0.0/error" => v2::mqtt::Error, + "fermyon:spin/mysql/mysql-error" => v1::mysql::MysqlError, + "fermyon:spin/postgres/pg-error" => v1::postgres::PgError, + "fermyon:spin/rdbms-types@2.0.0/error" => v2::rdbms_types::Error, + "fermyon:spin/redis-types/error" => v1::redis_types::Error, + "fermyon:spin/redis@2.0.0/error" => v2::redis::Error, + "fermyon:spin/sqlite@2.0.0/error" => v2::sqlite::Error, + "fermyon:spin/sqlite/error" => v1::sqlite::Error, + "fermyon:spin/variables@2.0.0/error" => v2::variables::Error, + "spin:postgres/postgres@3.0.0/error" => spin::postgres3_0_0::postgres::Error, + "spin:postgres/postgres@4.0.0/error" => spin::postgres4_0_0::postgres::Error, + "spin:sqlite/sqlite/error" => spin::sqlite::sqlite::Error, + "wasi:config/store@0.2.0-draft-2024-09-27/error" => wasi::config::store::Error, + "wasi:keyvalue/store/error" => wasi::keyvalue::store::Error, + "wasi:keyvalue/atomics/cas-error" => wasi::keyvalue::atomics::CasError, + }, +}); + +pub use fermyon::spin as v1; +pub use fermyon::spin2_0_0 as v2; + +mod conversions; diff --git a/crates/world/src/conversions.rs b/crates/world/src/conversions.rs index 2362ab8954..8177b623b2 100644 --- a/crates/world/src/conversions.rs +++ b/crates/world/src/conversions.rs @@ -553,495 +553,3 @@ mod llm { } } } - -mod otel { - use super::*; - use opentelemetry::StringValue; - use opentelemetry_sdk::trace::{SpanEvents, SpanLinks}; - use std::borrow::Cow; - use std::time::{Duration, SystemTime, UNIX_EPOCH}; - use wasi::clocks0_2_0::wall_clock; - - impl From - for opentelemetry_sdk::metrics::data::ResourceMetrics - { - fn from(value: wasi::otel::metrics::ResourceMetrics) -> Self { - Self { - resource: value.resource.into(), - scope_metrics: value.scope_metrics.into_iter().map(Into::into).collect(), - } - } - } - - impl From for opentelemetry_sdk::Resource { - fn from(value: wasi::otel::metrics::Resource) -> Self { - let attributes: Vec = - value.attributes.into_iter().map(Into::into).collect(); - let schema_url: Option = value.schema_url.into(); - - match schema_url { - Some(url) => opentelemetry_sdk::resource::Resource::builder() - .with_schema_url(attributes, url) - .build(), - None => opentelemetry_sdk::resource::Resource::builder() - .with_attributes(attributes) - .build(), - } - } - } - - impl From for opentelemetry_sdk::metrics::data::ScopeMetrics { - fn from(value: wasi::otel::metrics::ScopeMetrics) -> Self { - Self { - scope: value.scope.into(), - metrics: value.metrics.into_iter().map(Into::into).collect(), - } - } - } - - impl From for opentelemetry_sdk::metrics::data::Metric { - fn from(value: wasi::otel::metrics::Metric) -> Self { - Self { - name: Cow::Owned(value.name), - description: Cow::Owned(value.description), - unit: Cow::Owned(value.unit), - data: value.data.into(), - } - } - } - - /// Converts a Wasi exemplar to an OTel exemplar - macro_rules! exemplars_to_otel { - ( - $wasi_exemplar_list:expr, - $exemplar_type:ty - ) => { - $wasi_exemplar_list - .iter() - .map(|e| { - let span_id: [u8; 8] = e - .span_id - .as_bytes() - .try_into() - .expect("Span ID is longer than 8 bytes"); - let trace_id: [u8; 16] = e - .trace_id - .as_bytes() - .try_into() - .expect("Trace ID is longer than 16 bytes"); - opentelemetry_sdk::metrics::data::Exemplar::<$exemplar_type> { - filtered_attributes: e - .filtered_attributes - .to_owned() - .into_iter() - .map(Into::into) - .collect(), - time: e.time.into(), - value: e.value.into(), - span_id, - trace_id, - } - }) - .collect() - }; - } - - /// Converts a WASI Gauge to an OTel Gauge - macro_rules! wasi_gauge_to_otel { - ($gauge:expr, $number_type:ty) => { - Box::new(opentelemetry_sdk::metrics::data::Gauge { - data_points: $gauge - .data_points - .iter() - .map(|dp| opentelemetry_sdk::metrics::data::GaugeDataPoint { - attributes: dp.attributes.iter().map(Into::into).collect(), - value: dp.value.into(), - exemplars: exemplars_to_otel!(dp.exemplars, $number_type), - }) - .collect(), - start_time: match $gauge.start_time { - Some(t) => Some(t.into()), - None => None, - }, - time: $gauge.time.into(), - }) - }; - } - - /// Converts a WASI Sum to an OTel Sum - macro_rules! wasi_sum_to_otel { - ($sum:expr, $number_type:ty) => { - Box::new(opentelemetry_sdk::metrics::data::Sum { - data_points: $sum - .data_points - .iter() - .map(|dp| opentelemetry_sdk::metrics::data::SumDataPoint { - attributes: dp.attributes.iter().map(Into::into).collect(), - exemplars: exemplars_to_otel!(dp.exemplars, $number_type), - value: dp.value.into(), - }) - .collect(), - start_time: $sum.start_time.into(), - time: $sum.time.into(), - temporality: $sum.temporality.into(), - is_monotonic: $sum.is_monotonic, - }) - }; - } - - /// Converts a WASI Histogram to an OTel Histogram - macro_rules! wasi_histogram_to_otel { - ($histogram:expr, $number_type:ty) => { - Box::new(opentelemetry_sdk::metrics::data::Histogram { - data_points: $histogram - .data_points - .iter() - .map(|dp| opentelemetry_sdk::metrics::data::HistogramDataPoint { - attributes: dp.attributes.iter().map(Into::into).collect(), - bounds: dp.bounds.to_owned(), - bucket_counts: dp.bucket_counts.to_owned(), - exemplars: exemplars_to_otel!(dp.exemplars, $number_type), - count: dp.count, - max: match dp.max { - Some(m) => Some(m.into()), - None => None, - }, - min: match dp.min { - Some(m) => Some(m.into()), - None => None, - }, - sum: dp.sum.into(), - }) - .collect(), - start_time: $histogram.start_time.into(), - time: $histogram.time.into(), - temporality: $histogram.temporality.into(), - }) - }; - } - - /// Converts a WASI ExponentialHistogram to an OTel ExponentialHistogram - macro_rules! wasi_exponential_histogram_to_otel { - ($histogram:expr, $number_type:ty) => { - Box::new(opentelemetry_sdk::metrics::data::ExponentialHistogram { - data_points: $histogram - .data_points - .iter() - .map( - |dp| opentelemetry_sdk::metrics::data::ExponentialHistogramDataPoint { - attributes: dp.attributes.iter().map(Into::into).collect(), - exemplars: exemplars_to_otel!(dp.exemplars, $number_type), - count: dp.count as usize, - max: match dp.max { - Some(m) => Some(m.into()), - None => None, - }, - min: match dp.min { - Some(m) => Some(m.into()), - None => None, - }, - sum: dp.sum.into(), - scale: dp.scale, - zero_count: dp.zero_count, - positive_bucket: dp.positive_bucket.to_owned().into(), - negative_bucket: dp.negative_bucket.to_owned().into(), - zero_threshold: dp.zero_threshold, - }, - ) - .collect(), - start_time: $histogram.start_time.into(), - time: $histogram.time.into(), - temporality: $histogram.temporality.into(), - }) - }; - } - - impl From - for Box - { - fn from(value: wasi::otel::metrics::MetricData) -> Self { - match value { - wasi::otel::metrics::MetricData::F64Sum(s) => wasi_sum_to_otel!(s, f64), - wasi::otel::metrics::MetricData::S64Sum(s) => wasi_sum_to_otel!(s, i64), - wasi::otel::metrics::MetricData::U64Sum(s) => wasi_sum_to_otel!(s, u64), - wasi::otel::metrics::MetricData::F64Gauge(g) => wasi_gauge_to_otel!(g, f64), - wasi::otel::metrics::MetricData::S64Gauge(g) => wasi_gauge_to_otel!(g, i64), - wasi::otel::metrics::MetricData::U64Gauge(g) => wasi_gauge_to_otel!(g, u64), - wasi::otel::metrics::MetricData::F64Histogram(h) => wasi_histogram_to_otel!(h, f64), - wasi::otel::metrics::MetricData::S64Histogram(h) => wasi_histogram_to_otel!(h, i64), - wasi::otel::metrics::MetricData::U64Histogram(h) => wasi_histogram_to_otel!(h, u64), - wasi::otel::metrics::MetricData::F64ExponentialHistogram(h) => { - wasi_exponential_histogram_to_otel!(h, f64) - } - wasi::otel::metrics::MetricData::S64ExponentialHistogram(h) => { - wasi_exponential_histogram_to_otel!(h, i64) - } - wasi::otel::metrics::MetricData::U64ExponentialHistogram(h) => { - wasi_exponential_histogram_to_otel!(h, u64) - } - } - } - } - - impl From for f64 { - fn from(value: wasi::otel::metrics::MetricNumber) -> Self { - match value { - wasi::otel::metrics::MetricNumber::F64(n) => n, - _ => panic!("error converting WASI MetricNumber to f64"), - } - } - } - - impl From for u64 { - fn from(value: wasi::otel::metrics::MetricNumber) -> Self { - match value { - wasi::otel::metrics::MetricNumber::U64(n) => n, - _ => panic!("error converting WASI MetricNumber to u64"), - } - } - } - - impl From for i64 { - fn from(value: wasi::otel::metrics::MetricNumber) -> Self { - match value { - wasi::otel::metrics::MetricNumber::S64(n) => n, - _ => panic!("error converting WASI MetricNumber to i64"), - } - } - } - - impl From - for opentelemetry_sdk::metrics::data::ExponentialBucket - { - fn from(value: wasi::otel::metrics::ExponentialBucket) -> Self { - Self { - offset: value.offset, - counts: value.counts, - } - } - } - - impl From for opentelemetry_sdk::metrics::Temporality { - fn from(value: wasi::otel::metrics::Temporality) -> Self { - use opentelemetry_sdk::metrics::Temporality; - match value { - wasi::otel::metrics::Temporality::Cumulative => Temporality::Cumulative, - wasi::otel::metrics::Temporality::Delta => Temporality::Delta, - wasi::otel::metrics::Temporality::LowMemory => Temporality::LowMemory, - } - } - } - - impl From for opentelemetry_sdk::trace::SpanData { - fn from(value: wasi::otel::tracing::SpanData) -> Self { - let mut span_events = SpanEvents::default(); - span_events.events = value.events.into_iter().map(Into::into).collect(); - span_events.dropped_count = value.dropped_events; - let mut span_links = SpanLinks::default(); - span_links.links = value.links.into_iter().map(Into::into).collect(); - span_links.dropped_count = value.dropped_links; - Self { - span_context: value.span_context.into(), - parent_span_id: opentelemetry::trace::SpanId::from_hex(&value.parent_span_id) - .unwrap_or(opentelemetry::trace::SpanId::INVALID), - span_kind: value.span_kind.into(), - name: value.name.into(), - start_time: value.start_time.into(), - end_time: value.end_time.into(), - attributes: value.attributes.into_iter().map(Into::into).collect(), - dropped_attributes_count: value.dropped_attributes, - events: span_events, - links: span_links, - status: value.status.into(), - instrumentation_scope: value.instrumentation_scope.into(), - } - } - } - - impl From for opentelemetry::trace::SpanContext { - fn from(sc: wasi::otel::tracing::SpanContext) -> Self { - let trace_id = opentelemetry::trace::TraceId::from_hex(&sc.trace_id) - .unwrap_or(opentelemetry::trace::TraceId::INVALID); - let span_id = opentelemetry::trace::SpanId::from_hex(&sc.span_id) - .unwrap_or(opentelemetry::trace::SpanId::INVALID); - let trace_state = opentelemetry::trace::TraceState::from_key_value(sc.trace_state) - .unwrap_or_else(|_| opentelemetry::trace::TraceState::default()); - Self::new( - trace_id, - span_id, - sc.trace_flags.into(), - sc.is_remote, - trace_state, - ) - } - } - - impl From for wasi::otel::tracing::SpanContext { - fn from(sc: opentelemetry::trace::SpanContext) -> Self { - Self { - trace_id: format!("{:x}", sc.trace_id()), - span_id: format!("{:x}", sc.span_id()), - trace_flags: sc.trace_flags().into(), - is_remote: sc.is_remote(), - trace_state: sc - .trace_state() - .header() - .split(',') - .filter_map(|s| { - if let Some((key, value)) = s.split_once('=') { - Some((key.to_string(), value.to_string())) - } else { - None - } - }) - .collect(), - } - } - } - - impl From for opentelemetry::trace::TraceFlags { - fn from(flags: wasi::otel::tracing::TraceFlags) -> Self { - Self::new(flags.as_array()[0] as u8) - } - } - - impl From for wasi::otel::tracing::TraceFlags { - fn from(flags: opentelemetry::trace::TraceFlags) -> Self { - if flags.is_sampled() { - wasi::otel::tracing::TraceFlags::SAMPLED - } else { - wasi::otel::tracing::TraceFlags::empty() - } - } - } - - impl From for opentelemetry::trace::SpanKind { - fn from(kind: wasi::otel::tracing::SpanKind) -> Self { - match kind { - wasi::otel::tracing::SpanKind::Client => opentelemetry::trace::SpanKind::Client, - wasi::otel::tracing::SpanKind::Server => opentelemetry::trace::SpanKind::Server, - wasi::otel::tracing::SpanKind::Producer => opentelemetry::trace::SpanKind::Producer, - wasi::otel::tracing::SpanKind::Consumer => opentelemetry::trace::SpanKind::Consumer, - wasi::otel::tracing::SpanKind::Internal => opentelemetry::trace::SpanKind::Internal, - } - } - } - - impl From for opentelemetry::KeyValue { - fn from(kv: wasi::otel::tracing::KeyValue) -> Self { - opentelemetry::KeyValue::new(kv.key, kv.value) - } - } - - impl From<&wasi::otel::tracing::KeyValue> for opentelemetry::KeyValue { - fn from(kv: &wasi::otel::tracing::KeyValue) -> Self { - opentelemetry::KeyValue::new(kv.key.to_owned(), kv.value.to_owned()) - } - } - - impl From for opentelemetry::Value { - fn from(value: wasi::otel::types::Value) -> Self { - match value { - wasi::otel::types::Value::String(v) => v.into(), - wasi::otel::types::Value::Bool(v) => v.into(), - wasi::otel::types::Value::F64(v) => v.into(), - wasi::otel::types::Value::S64(v) => v.into(), - wasi::otel::types::Value::StringArray(v) => opentelemetry::Value::Array( - v.into_iter() - .map(StringValue::from) - .collect::>() - .into(), - ), - wasi::otel::types::Value::BoolArray(v) => opentelemetry::Value::Array(v.into()), - wasi::otel::types::Value::F64Array(v) => opentelemetry::Value::Array(v.into()), - wasi::otel::types::Value::S64Array(v) => opentelemetry::Value::Array(v.into()), - } - } - } - - impl From for opentelemetry::trace::Event { - fn from(event: wasi::otel::tracing::Event) -> Self { - Self::new( - event.name, - event.time.into(), - event.attributes.into_iter().map(Into::into).collect(), - 0, - ) - } - } - - impl From for opentelemetry::trace::Link { - fn from(link: wasi::otel::tracing::Link) -> Self { - Self::new( - link.span_context.into(), - link.attributes.into_iter().map(Into::into).collect(), - 0, - ) - } - } - - impl From for opentelemetry::trace::Status { - fn from(status: wasi::otel::tracing::Status) -> Self { - match status { - wasi::otel::tracing::Status::Unset => Self::Unset, - wasi::otel::tracing::Status::Ok => Self::Ok, - wasi::otel::tracing::Status::Error(s) => Self::Error { - description: s.into(), - }, - } - } - } - - impl From for opentelemetry::InstrumentationScope { - fn from(value: wasi::otel::tracing::InstrumentationScope) -> Self { - let builder = Self::builder(value.name) - .with_attributes(value.attributes.into_iter().map(Into::into)); - match (value.version, value.schema_url) { - (Some(version), Some(schema_url)) => builder - .with_version(version) - .with_schema_url(schema_url) - .build(), - (Some(version), None) => builder.with_version(version).build(), - (None, Some(schema_url)) => builder.with_schema_url(schema_url).build(), - (None, None) => builder.build(), - } - } - } - - impl From for SystemTime { - fn from(timestamp: wall_clock::Datetime) -> Self { - UNIX_EPOCH - + Duration::from_secs(timestamp.seconds) - + Duration::from_nanos(timestamp.nanoseconds as u64) - } - } - - mod test { - #[test] - fn trace_flags() { - let flags = opentelemetry::trace::TraceFlags::SAMPLED; - let flags2 = crate::wasi::otel::tracing::TraceFlags::from(flags); - let flags3 = opentelemetry::trace::TraceFlags::from(flags2); - assert_eq!(flags, flags3); - } - - #[test] - fn span_context() { - let sc = opentelemetry::trace::SpanContext::new( - opentelemetry::trace::TraceId::from_hex("4fb34cb4484029f7881399b149e41e98") - .unwrap(), - opentelemetry::trace::SpanId::from_hex("9ffd58d3cd4dd90b").unwrap(), - opentelemetry::trace::TraceFlags::SAMPLED, - false, - opentelemetry::trace::TraceState::from_key_value(vec![ - ("foo", "bar"), - ("baz", "qux"), - ]) - .unwrap(), - ); - let sc2 = crate::wasi::otel::tracing::SpanContext::from(sc.clone()); - let sc3 = opentelemetry::trace::SpanContext::from(sc2); - assert_eq!(sc, sc3); - } - } -} From 84f1bd478e6f36204b8e99e0b729c04d527821fb Mon Sep 17 00:00:00 2001 From: Andrew Steurer <94206073+asteurer@users.noreply.github.com> Date: Mon, 24 Nov 2025 09:35:43 -0600 Subject: [PATCH 03/13] Update crates/factor-otel/src/lib.rs Co-authored-by: Ryan Levick --- crates/factor-otel/src/lib.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/crates/factor-otel/src/lib.rs b/crates/factor-otel/src/lib.rs index 8563bd17ff..3b3cb67c9d 100644 --- a/crates/factor-otel/src/lib.rs +++ b/crates/factor-otel/src/lib.rs @@ -183,11 +183,7 @@ impl OtelFactorState { pub fn reparent_tracing_span(&self) { // If state is None then we want to return early b/c the factor doesn't depend on the // Otel factor and therefore there is nothing to do - let state = if let Some(state) = self.state.as_ref() { - state.read().unwrap() - } else { - return; - }; + let Some(state) = self.state.as_ref() { state.read().unwrap() } else { return }; // If there are no active guest spans then there is nothing to do let Some((_, active_span_context)) = state.guest_span_contexts.last() else { From 9d88adda6927c50fcaeae5066707a0112ea6e690 Mon Sep 17 00:00:00 2001 From: Andrew Steurer <94206073+asteurer@users.noreply.github.com> Date: Mon, 24 Nov 2025 09:35:53 -0600 Subject: [PATCH 04/13] Update crates/factor-otel/src/lib.rs Co-authored-by: Ryan Levick --- crates/factor-otel/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/factor-otel/src/lib.rs b/crates/factor-otel/src/lib.rs index 3b3cb67c9d..27183d2cae 100644 --- a/crates/factor-otel/src/lib.rs +++ b/crates/factor-otel/src/lib.rs @@ -169,7 +169,7 @@ impl OtelFactorState { /// | spin_key_value.get | /// ``` /// - /// Setting the guest spans parent as the host is enabled through current_span_context. + /// Setting the guest spans parent as the host is enabled through current_span_context. /// However, the more difficult task is having the host factor spans be children of the guest /// span. [`OtelFactorState::reparent_tracing_span`] handles this by reparenting the current span to /// be a child of the last active guest span (which is tracked internally in the otel factor). From 00d6ac957afc820f9719b6e5a8744fa7c85a326e Mon Sep 17 00:00:00 2001 From: Andrew Steurer <94206073+asteurer@users.noreply.github.com> Date: Mon, 24 Nov 2025 16:02:56 +0000 Subject: [PATCH 05/13] fix: misc refactors Signed-off-by: Andrew Steurer <94206073+asteurer@users.noreply.github.com> --- crates/factor-key-value/src/host.rs | 12 +++---- crates/factor-llm/src/host.rs | 8 +++-- crates/factor-otel/src/lib.rs | 23 ++++++++------ crates/factor-outbound-http/src/spin.rs | 5 ++- crates/factor-outbound-mqtt/src/host.rs | 8 +++-- crates/factor-outbound-mysql/src/host.rs | 12 +++++-- crates/factor-outbound-pg/src/host.rs | 13 +++++--- crates/factor-outbound-redis/src/host.rs | 40 ++++++++++++++++++------ crates/factor-sqlite/src/host.rs | 8 +++-- crates/factor-variables/src/host.rs | 4 ++- crates/runtime-factors/src/build.rs | 4 +++ crates/runtime-factors/src/lib.rs | 3 +- 12 files changed, 98 insertions(+), 42 deletions(-) diff --git a/crates/factor-key-value/src/host.rs b/crates/factor-key-value/src/host.rs index eda69ace6d..f77d105579 100644 --- a/crates/factor-key-value/src/host.rs +++ b/crates/factor-key-value/src/host.rs @@ -118,7 +118,7 @@ impl key_value::HostStore for KeyValueDispatch { #[instrument(name = "spin_key_value.open", skip(self), err, fields(otel.kind = "client", kv.backend=self.manager.summary(&name).unwrap_or("unknown".to_string())))] async fn open(&mut self, name: String) -> Result, Error>> { if let Some(otel_context) = self.otel_context.as_ref() { - otel_context.reparent_tracing_span() + otel_context.reparent_tracing_span()?; } Ok(async { if self.allowed_stores.contains(&name) { @@ -143,7 +143,7 @@ impl key_value::HostStore for KeyValueDispatch { key: String, ) -> Result>, Error>> { if let Some(otel_context) = self.otel_context.as_ref() { - otel_context.reparent_tracing_span() + otel_context.reparent_tracing_span()?; } let store = self.get_store(store)?; Ok(store.get(&key).await.map_err(track_error_on_span)) @@ -157,7 +157,7 @@ impl key_value::HostStore for KeyValueDispatch { value: Vec, ) -> Result> { if let Some(otel_context) = self.otel_context.as_ref() { - otel_context.reparent_tracing_span() + otel_context.reparent_tracing_span()?; } let store = self.get_store(store)?; Ok(store.set(&key, &value).await.map_err(track_error_on_span)) @@ -170,7 +170,7 @@ impl key_value::HostStore for KeyValueDispatch { key: String, ) -> Result> { if let Some(otel_context) = self.otel_context.as_ref() { - otel_context.reparent_tracing_span() + otel_context.reparent_tracing_span()?; } let store = self.get_store(store)?; Ok(store.delete(&key).await.map_err(track_error_on_span)) @@ -183,7 +183,7 @@ impl key_value::HostStore for KeyValueDispatch { key: String, ) -> Result> { if let Some(otel_context) = self.otel_context.as_ref() { - otel_context.reparent_tracing_span() + otel_context.reparent_tracing_span()?; } let store = self.get_store(store)?; Ok(store.exists(&key).await.map_err(track_error_on_span)) @@ -195,7 +195,7 @@ impl key_value::HostStore for KeyValueDispatch { store: Resource, ) -> Result, Error>> { if let Some(otel_context) = self.otel_context.as_ref() { - otel_context.reparent_tracing_span() + otel_context.reparent_tracing_span()?; } let store = self.get_store(store)?; Ok(store.get_keys().await.map_err(track_error_on_span)) diff --git a/crates/factor-llm/src/host.rs b/crates/factor-llm/src/host.rs index 61c49b5313..42aa457e59 100644 --- a/crates/factor-llm/src/host.rs +++ b/crates/factor-llm/src/host.rs @@ -13,7 +13,9 @@ impl v2::Host for InstanceState { prompt: String, params: Option, ) -> Result { - self.otel_context.reparent_tracing_span(); + if let Err(e) = self.otel_context.reparent_tracing_span() { + return Err(v2::Error::RuntimeError(e.to_string())); + }; if !self.allowed_models.contains(&model) { return Err(access_denied_error(&model)); @@ -42,7 +44,9 @@ impl v2::Host for InstanceState { model: v1::EmbeddingModel, data: Vec, ) -> Result { - self.otel_context.reparent_tracing_span(); + if let Err(e) = self.otel_context.reparent_tracing_span() { + return Err(v2::Error::RuntimeError(e.to_string())); + }; if !self.allowed_models.contains(&model) { return Err(access_denied_error(&model)); diff --git a/crates/factor-otel/src/lib.rs b/crates/factor-otel/src/lib.rs index 27183d2cae..31e46e2b60 100644 --- a/crates/factor-otel/src/lib.rs +++ b/crates/factor-otel/src/lib.rs @@ -1,6 +1,6 @@ mod host; -use anyhow::bail; +use anyhow::{anyhow, bail, Error, Result}; use indexmap::IndexMap; use opentelemetry::{ trace::{SpanContext, SpanId, TraceContextExt}, @@ -58,15 +58,13 @@ impl Factor for OtelFactor { } impl OtelFactor { - pub fn new() -> anyhow::Result { - // This is a hack b/c we know the version of this crate will be the same as the version of Spin - let spin_version = env!("CARGO_PKG_VERSION").to_string(); - + pub fn new(spin_version: &str) -> anyhow::Result { let resource = Resource::builder() .with_detectors(&[ // Set service.name from env OTEL_SERVICE_NAME > env OTEL_RESOURCE_ATTRIBUTES > spin // Set service.version from Spin metadata - Box::new(SpinResourceDetector::new(spin_version)) as Box, + Box::new(SpinResourceDetector::new(spin_version.to_string())) + as Box, // Sets fields from env OTEL_RESOURCE_ATTRIBUTES Box::new(EnvResourceDetector::new()), // Sets telemetry.sdk{name, language, version} @@ -180,14 +178,18 @@ impl OtelFactorState { /// This MUST only be called from a factor host implementation function that is instrumented. /// /// This MUST be called at the very start of the function before any awaits. - pub fn reparent_tracing_span(&self) { + pub fn reparent_tracing_span(&self) -> Result<(), Error> { // If state is None then we want to return early b/c the factor doesn't depend on the // Otel factor and therefore there is nothing to do - let Some(state) = self.state.as_ref() { state.read().unwrap() } else { return }; + let state = if let Some(state) = self.state.as_ref() { + state.read().unwrap() + } else { + return Ok(()); + }; // If there are no active guest spans then there is nothing to do let Some((_, active_span_context)) = state.guest_span_contexts.last() else { - return; + return Ok(()); }; // Ensure that we are not reparenting the original host span @@ -199,12 +201,13 @@ impl OtelFactorState { .span_id() .eq(&original_host_span_id) { - panic!("Incorrectly attempting to reparent the original host span. Likely `reparent_tracing_span` was called in an incorrect location.") + return Err(anyhow!("Incorrectly attempting to reparent the original host span. Likely `reparent_tracing_span` was called in an incorrect location.")); } } // Now reparent the current span to the last active guest span let parent_context = Context::new().with_remote_span_context(active_span_context.clone()); tracing::Span::current().set_parent(parent_context); + Ok(()) } } diff --git a/crates/factor-outbound-http/src/spin.rs b/crates/factor-outbound-http/src/spin.rs index b4fe9f6d0b..3c16eb48ac 100644 --- a/crates/factor-outbound-http/src/spin.rs +++ b/crates/factor-outbound-http/src/spin.rs @@ -15,7 +15,10 @@ impl spin_http::Host for crate::InstanceState { fields(otel.kind = "client", url.full = Empty, http.request.method = Empty, http.response.status_code = Empty, otel.name = Empty, server.address = Empty, server.port = Empty))] async fn send_request(&mut self, req: Request) -> Result { - self.otel_context.reparent_tracing_span(); + if let Err(e) = self.otel_context.reparent_tracing_span() { + tracing::error!("{}", e.to_string()); + return Err(HttpError::RuntimeError); + }; let span = Span::current(); record_request_fields(&span, &req); diff --git a/crates/factor-outbound-mqtt/src/host.rs b/crates/factor-outbound-mqtt/src/host.rs index a39d1a4b60..cd59e1f700 100644 --- a/crates/factor-outbound-mqtt/src/host.rs +++ b/crates/factor-outbound-mqtt/src/host.rs @@ -79,7 +79,9 @@ impl v2::HostConnection for InstanceState { password: String, keep_alive_interval: u64, ) -> Result, Error> { - self.otel_context.reparent_tracing_span(); + if let Err(e) = self.otel_context.reparent_tracing_span() { + return Err(Error::Other(e.to_string())); + }; if !self .is_address_allowed(&address) @@ -114,7 +116,9 @@ impl v2::HostConnection for InstanceState { payload: Vec, qos: Qos, ) -> Result<(), Error> { - self.otel_context.reparent_tracing_span(); + if let Err(e) = self.otel_context.reparent_tracing_span() { + return Err(Error::Other(e.to_string())); + }; let conn = self.get_conn(connection).await.map_err(other_error)?; diff --git a/crates/factor-outbound-mysql/src/host.rs b/crates/factor-outbound-mysql/src/host.rs index ca113206aa..26a646c5a0 100644 --- a/crates/factor-outbound-mysql/src/host.rs +++ b/crates/factor-outbound-mysql/src/host.rs @@ -38,7 +38,9 @@ impl v2::Host for InstanceState {} impl v2::HostConnection for InstanceState { #[instrument(name = "spin_outbound_mysql.open", skip(self, address), err(level = Level::INFO), fields(otel.kind = "client", db.system = "mysql", db.address = Empty, server.port = Empty, db.namespace = Empty))] async fn open(&mut self, address: String) -> Result, v2::Error> { - self.otel_context.reparent_tracing_span(); + if let Err(e) = self.otel_context.reparent_tracing_span() { + return Err(v2::Error::Other(e.to_string())); + }; spin_factor_outbound_networking::record_address_fields(&address); if !self @@ -60,7 +62,9 @@ impl v2::HostConnection for InstanceState { statement: String, params: Vec, ) -> Result<(), v2::Error> { - self.otel_context.reparent_tracing_span(); + if let Err(e) = self.otel_context.reparent_tracing_span() { + return Err(v2::Error::Other(e.to_string())); + }; self.get_client(connection) .await? .execute(statement, params) @@ -74,7 +78,9 @@ impl v2::HostConnection for InstanceState { statement: String, params: Vec, ) -> Result { - self.otel_context.reparent_tracing_span(); + if let Err(e) = self.otel_context.reparent_tracing_span() { + return Err(v2::Error::Other(e.to_string())); + }; self.get_client(connection) .await? .query(statement, params) diff --git a/crates/factor-outbound-pg/src/host.rs b/crates/factor-outbound-pg/src/host.rs index 81dda9bbe6..d11a991f96 100644 --- a/crates/factor-outbound-pg/src/host.rs +++ b/crates/factor-outbound-pg/src/host.rs @@ -219,7 +219,9 @@ impl v2::Host for InstanceState {} impl v2::HostConnection for InstanceState { #[instrument(name = "spin_outbound_pg.open", skip(self, address), err(level = Level::INFO), fields(otel.kind = "client", db.system = "postgresql", db.address = Empty, server.port = Empty, db.namespace = Empty))] async fn open(&mut self, address: String) -> Result, v2::Error> { - self.otel_context.reparent_tracing_span(); + if let Err(e) = self.otel_context.reparent_tracing_span() { + return Err(v2::Error::Other(e.to_string())); + }; spin_factor_outbound_networking::record_address_fields(&address); if !self @@ -241,8 +243,9 @@ impl v2::HostConnection for InstanceState { statement: String, params: Vec, ) -> Result { - self.otel_context.reparent_tracing_span(); - + if let Err(e) = self.otel_context.reparent_tracing_span() { + return Err(v2::Error::Other(e.to_string())); + }; Ok(self .get_client(connection) .await? @@ -257,7 +260,9 @@ impl v2::HostConnection for InstanceState { statement: String, params: Vec, ) -> Result { - self.otel_context.reparent_tracing_span(); + if let Err(e) = self.otel_context.reparent_tracing_span() { + return Err(v2::Error::Other(e.to_string())); + }; Ok(self .get_client(connection) .await? diff --git a/crates/factor-outbound-redis/src/host.rs b/crates/factor-outbound-redis/src/host.rs index 2f265b90dc..c7eae93902 100644 --- a/crates/factor-outbound-redis/src/host.rs +++ b/crates/factor-outbound-redis/src/host.rs @@ -65,7 +65,9 @@ impl v2::Host for crate::InstanceState { impl v2::HostConnection for crate::InstanceState { #[instrument(name = "spin_outbound_redis.open_connection", skip(self, address), err(level = Level::INFO), fields(otel.kind = "client", db.system = "redis", db.address = Empty, server.port = Empty, db.namespace = Empty))] async fn open(&mut self, address: String) -> Result, Error> { - self.otel_context.reparent_tracing_span(); + if let Err(e) = self.otel_context.reparent_tracing_span() { + return Err(Error::Other(e.to_string())); + }; if !self .is_address_allowed(&address) .await @@ -84,7 +86,9 @@ impl v2::HostConnection for crate::InstanceState { channel: String, payload: Vec, ) -> Result<(), Error> { - self.otel_context.reparent_tracing_span(); + if let Err(e) = self.otel_context.reparent_tracing_span() { + return Err(Error::Other(e.to_string())); + }; let conn = self.get_conn(connection).await.map_err(other_error)?; // The `let () =` syntax is needed to suppress a warning when the result type is inferred. @@ -102,7 +106,9 @@ impl v2::HostConnection for crate::InstanceState { connection: Resource, key: String, ) -> Result>, Error> { - self.otel_context.reparent_tracing_span(); + if let Err(e) = self.otel_context.reparent_tracing_span() { + return Err(Error::Other(e.to_string())); + }; let conn = self.get_conn(connection).await.map_err(other_error)?; let value = conn.get(&key).await.map_err(other_error)?; @@ -116,7 +122,9 @@ impl v2::HostConnection for crate::InstanceState { key: String, value: Vec, ) -> Result<(), Error> { - self.otel_context.reparent_tracing_span(); + if let Err(e) = self.otel_context.reparent_tracing_span() { + return Err(Error::Other(e.to_string())); + }; let conn = self.get_conn(connection).await.map_err(other_error)?; // The `let () =` syntax is needed to suppress a warning when the result type is inferred. @@ -131,7 +139,9 @@ impl v2::HostConnection for crate::InstanceState { connection: Resource, key: String, ) -> Result { - self.otel_context.reparent_tracing_span(); + if let Err(e) = self.otel_context.reparent_tracing_span() { + return Err(Error::Other(e.to_string())); + }; let conn = self.get_conn(connection).await.map_err(other_error)?; let value = conn.incr(&key, 1).await.map_err(other_error)?; @@ -144,7 +154,9 @@ impl v2::HostConnection for crate::InstanceState { connection: Resource, keys: Vec, ) -> Result { - self.otel_context.reparent_tracing_span(); + if let Err(e) = self.otel_context.reparent_tracing_span() { + return Err(Error::Other(e.to_string())); + }; let conn = self.get_conn(connection).await.map_err(other_error)?; let value = conn.del(&keys).await.map_err(other_error)?; @@ -158,7 +170,9 @@ impl v2::HostConnection for crate::InstanceState { key: String, values: Vec, ) -> Result { - self.otel_context.reparent_tracing_span(); + if let Err(e) = self.otel_context.reparent_tracing_span() { + return Err(Error::Other(e.to_string())); + }; let conn = self.get_conn(connection).await.map_err(other_error)?; let value = conn.sadd(&key, &values).await.map_err(|e| { @@ -177,7 +191,9 @@ impl v2::HostConnection for crate::InstanceState { connection: Resource, key: String, ) -> Result, Error> { - self.otel_context.reparent_tracing_span(); + if let Err(e) = self.otel_context.reparent_tracing_span() { + return Err(Error::Other(e.to_string())); + }; let conn = self.get_conn(connection).await.map_err(other_error)?; let value = conn.smembers(&key).await.map_err(other_error)?; @@ -191,7 +207,9 @@ impl v2::HostConnection for crate::InstanceState { key: String, values: Vec, ) -> Result { - self.otel_context.reparent_tracing_span(); + if let Err(e) = self.otel_context.reparent_tracing_span() { + return Err(Error::Other(e.to_string())); + }; let conn = self.get_conn(connection).await.map_err(other_error)?; let value = conn.srem(&key, &values).await.map_err(other_error)?; @@ -205,7 +223,9 @@ impl v2::HostConnection for crate::InstanceState { command: String, arguments: Vec, ) -> Result, Error> { - self.otel_context.reparent_tracing_span(); + if let Err(e) = self.otel_context.reparent_tracing_span() { + return Err(Error::Other(e.to_string())); + }; let conn = self.get_conn(connection).await?; let mut cmd = redis::cmd(&command); diff --git a/crates/factor-sqlite/src/host.rs b/crates/factor-sqlite/src/host.rs index ddc6d0f5a8..3011f72e4d 100644 --- a/crates/factor-sqlite/src/host.rs +++ b/crates/factor-sqlite/src/host.rs @@ -158,7 +158,9 @@ impl v2::Host for InstanceState { impl v2::HostConnection for InstanceState { #[instrument(name = "spin_sqlite.open", skip(self), err(level = Level::INFO), fields(otel.kind = "client", db.system = "sqlite", sqlite.backend = Empty))] async fn open(&mut self, database: String) -> Result, v2::Error> { - self.otel_context.reparent_tracing_span(); + if let Err(e) = self.otel_context.reparent_tracing_span() { + return Err(v2::Error::Io(e.to_string())); + }; self.open_impl(database).await.map_err(to_v2_error) } @@ -169,7 +171,9 @@ impl v2::HostConnection for InstanceState { query: String, parameters: Vec, ) -> Result { - self.otel_context.reparent_tracing_span(); + if let Err(e) = self.otel_context.reparent_tracing_span() { + return Err(v2::Error::Io(e.to_string())); + }; self.execute_impl( connection, query, diff --git a/crates/factor-variables/src/host.rs b/crates/factor-variables/src/host.rs index 784cebd280..bbef549987 100644 --- a/crates/factor-variables/src/host.rs +++ b/crates/factor-variables/src/host.rs @@ -8,7 +8,9 @@ use crate::InstanceState; impl variables::Host for InstanceState { #[instrument(name = "spin_variables.get", skip(self), fields(otel.kind = "client"))] async fn get(&mut self, key: String) -> Result { - self.otel_context.reparent_tracing_span(); + if let Err(e) = self.otel_context.reparent_tracing_span() { + return Err(variables::Error::Other(e.to_string())); + }; let key = spin_expressions::Key::new(&key).map_err(expressions_to_variables_err)?; self.expression_resolver .resolve(&self.component_id, key) diff --git a/crates/runtime-factors/src/build.rs b/crates/runtime-factors/src/build.rs index c09ee39337..da50f3cd98 100644 --- a/crates/runtime-factors/src/build.rs +++ b/crates/runtime-factors/src/build.rs @@ -46,10 +46,14 @@ impl RuntimeFactorsBuilder for FactorsBuilder { runtime_config.summarize(config.runtime_config_file.as_deref()); + // This is a hack b/c we know the version of this crate will be the same as the version of Spin + let spin_version = env!("CARGO_PKG_VERSION"); + let factors = TriggerFactors::new( runtime_config.state_dir(), config.working_dir.clone(), args.allow_transient_write, + spin_version, ) .context("failed to create factors")?; Ok((factors, runtime_config)) diff --git a/crates/runtime-factors/src/lib.rs b/crates/runtime-factors/src/lib.rs index b1865e444c..a5e2ca6ea7 100644 --- a/crates/runtime-factors/src/lib.rs +++ b/crates/runtime-factors/src/lib.rs @@ -45,9 +45,10 @@ impl TriggerFactors { state_dir: Option, working_dir: impl Into, allow_transient_writes: bool, + spin_version: &str, ) -> anyhow::Result { Ok(Self { - otel: OtelFactor::new()?, + otel: OtelFactor::new(spin_version)?, wasi: wasi_factor(working_dir, allow_transient_writes), variables: VariablesFactor::default(), key_value: KeyValueFactor::new(), From 3f3875232c48ea1cf0a11fa500f05246f179c835 Mon Sep 17 00:00:00 2001 From: Andrew Steurer <94206073+asteurer@users.noreply.github.com> Date: Mon, 24 Nov 2025 16:11:31 +0000 Subject: [PATCH 06/13] fix: misc refactors Signed-off-by: Andrew Steurer <94206073+asteurer@users.noreply.github.com> --- crates/telemetry/src/env.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/telemetry/src/env.rs b/crates/telemetry/src/env.rs index 487aad6227..b234476638 100644 --- a/crates/telemetry/src/env.rs +++ b/crates/telemetry/src/env.rs @@ -19,7 +19,7 @@ const SPIN_DISABLE_LOG_TO_TRACING: &str = "SPIN_DISABLE_LOG_TO_TRACING"; /// - `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` /// /// Note that this is overridden if OTEL_SDK_DISABLED is set and not empty. -pub fn otel_tracing_enabled() -> bool { +pub(crate) fn otel_tracing_enabled() -> bool { any_vars_set(&[ OTEL_EXPORTER_OTLP_ENDPOINT, OTEL_EXPORTER_OTLP_TRACES_ENDPOINT, From 0332cb9dd8a0cb13ce06a6ec6198d9e164218c78 Mon Sep 17 00:00:00 2001 From: Andrew Steurer <94206073+asteurer@users.noreply.github.com> Date: Tue, 25 Nov 2025 05:38:40 +0000 Subject: [PATCH 07/13] feat(wasi-otel): more refactoring Signed-off-by: Andrew Steurer <94206073+asteurer@users.noreply.github.com> --- crates/factor-key-value/src/host.rs | 12 +- crates/factor-llm/src/host.rs | 8 +- crates/factor-otel/src/lib.rs | 11 +- crates/factor-outbound-http/src/spin.rs | 5 +- crates/factor-outbound-mqtt/src/host.rs | 8 +- crates/factor-outbound-mysql/src/host.rs | 12 +- crates/factor-outbound-pg/src/host.rs | 12 +- crates/factor-outbound-redis/src/host.rs | 40 +--- crates/factor-sqlite/src/host.rs | 8 +- crates/factor-variables/src/host.rs | 4 +- crates/wasi-otel/src/common_conversions.rs | 58 +++++ crates/wasi-otel/src/lib.rs | 4 +- ...{conversions.rs => metrics_conversions.rs} | 215 +----------------- crates/wasi-otel/src/trace_conversions.rs | 155 +++++++++++++ 14 files changed, 252 insertions(+), 300 deletions(-) create mode 100644 crates/wasi-otel/src/common_conversions.rs rename crates/wasi-otel/src/{conversions.rs => metrics_conversions.rs} (55%) create mode 100644 crates/wasi-otel/src/trace_conversions.rs diff --git a/crates/factor-key-value/src/host.rs b/crates/factor-key-value/src/host.rs index f77d105579..6d5c103386 100644 --- a/crates/factor-key-value/src/host.rs +++ b/crates/factor-key-value/src/host.rs @@ -118,7 +118,7 @@ impl key_value::HostStore for KeyValueDispatch { #[instrument(name = "spin_key_value.open", skip(self), err, fields(otel.kind = "client", kv.backend=self.manager.summary(&name).unwrap_or("unknown".to_string())))] async fn open(&mut self, name: String) -> Result, Error>> { if let Some(otel_context) = self.otel_context.as_ref() { - otel_context.reparent_tracing_span()?; + otel_context.reparent_tracing_span(); } Ok(async { if self.allowed_stores.contains(&name) { @@ -143,7 +143,7 @@ impl key_value::HostStore for KeyValueDispatch { key: String, ) -> Result>, Error>> { if let Some(otel_context) = self.otel_context.as_ref() { - otel_context.reparent_tracing_span()?; + otel_context.reparent_tracing_span(); } let store = self.get_store(store)?; Ok(store.get(&key).await.map_err(track_error_on_span)) @@ -157,7 +157,7 @@ impl key_value::HostStore for KeyValueDispatch { value: Vec, ) -> Result> { if let Some(otel_context) = self.otel_context.as_ref() { - otel_context.reparent_tracing_span()?; + otel_context.reparent_tracing_span(); } let store = self.get_store(store)?; Ok(store.set(&key, &value).await.map_err(track_error_on_span)) @@ -170,7 +170,7 @@ impl key_value::HostStore for KeyValueDispatch { key: String, ) -> Result> { if let Some(otel_context) = self.otel_context.as_ref() { - otel_context.reparent_tracing_span()?; + otel_context.reparent_tracing_span(); } let store = self.get_store(store)?; Ok(store.delete(&key).await.map_err(track_error_on_span)) @@ -183,7 +183,7 @@ impl key_value::HostStore for KeyValueDispatch { key: String, ) -> Result> { if let Some(otel_context) = self.otel_context.as_ref() { - otel_context.reparent_tracing_span()?; + otel_context.reparent_tracing_span(); } let store = self.get_store(store)?; Ok(store.exists(&key).await.map_err(track_error_on_span)) @@ -195,7 +195,7 @@ impl key_value::HostStore for KeyValueDispatch { store: Resource, ) -> Result, Error>> { if let Some(otel_context) = self.otel_context.as_ref() { - otel_context.reparent_tracing_span()?; + otel_context.reparent_tracing_span(); } let store = self.get_store(store)?; Ok(store.get_keys().await.map_err(track_error_on_span)) diff --git a/crates/factor-llm/src/host.rs b/crates/factor-llm/src/host.rs index 42aa457e59..61c49b5313 100644 --- a/crates/factor-llm/src/host.rs +++ b/crates/factor-llm/src/host.rs @@ -13,9 +13,7 @@ impl v2::Host for InstanceState { prompt: String, params: Option, ) -> Result { - if let Err(e) = self.otel_context.reparent_tracing_span() { - return Err(v2::Error::RuntimeError(e.to_string())); - }; + self.otel_context.reparent_tracing_span(); if !self.allowed_models.contains(&model) { return Err(access_denied_error(&model)); @@ -44,9 +42,7 @@ impl v2::Host for InstanceState { model: v1::EmbeddingModel, data: Vec, ) -> Result { - if let Err(e) = self.otel_context.reparent_tracing_span() { - return Err(v2::Error::RuntimeError(e.to_string())); - }; + self.otel_context.reparent_tracing_span(); if !self.allowed_models.contains(&model) { return Err(access_denied_error(&model)); diff --git a/crates/factor-otel/src/lib.rs b/crates/factor-otel/src/lib.rs index 31e46e2b60..3cd00d71cf 100644 --- a/crates/factor-otel/src/lib.rs +++ b/crates/factor-otel/src/lib.rs @@ -1,6 +1,6 @@ mod host; -use anyhow::{anyhow, bail, Error, Result}; +use anyhow::bail; use indexmap::IndexMap; use opentelemetry::{ trace::{SpanContext, SpanId, TraceContextExt}, @@ -178,18 +178,18 @@ impl OtelFactorState { /// This MUST only be called from a factor host implementation function that is instrumented. /// /// This MUST be called at the very start of the function before any awaits. - pub fn reparent_tracing_span(&self) -> Result<(), Error> { + pub fn reparent_tracing_span(&self) { // If state is None then we want to return early b/c the factor doesn't depend on the // Otel factor and therefore there is nothing to do let state = if let Some(state) = self.state.as_ref() { state.read().unwrap() } else { - return Ok(()); + return; }; // If there are no active guest spans then there is nothing to do let Some((_, active_span_context)) = state.guest_span_contexts.last() else { - return Ok(()); + return; }; // Ensure that we are not reparenting the original host span @@ -201,13 +201,12 @@ impl OtelFactorState { .span_id() .eq(&original_host_span_id) { - return Err(anyhow!("Incorrectly attempting to reparent the original host span. Likely `reparent_tracing_span` was called in an incorrect location.")); + panic!("Incorrectly attempting to reparent the original host span. Likely `reparent_tracing_span` was called in an incorrect location."); } } // Now reparent the current span to the last active guest span let parent_context = Context::new().with_remote_span_context(active_span_context.clone()); tracing::Span::current().set_parent(parent_context); - Ok(()) } } diff --git a/crates/factor-outbound-http/src/spin.rs b/crates/factor-outbound-http/src/spin.rs index 3c16eb48ac..b4fe9f6d0b 100644 --- a/crates/factor-outbound-http/src/spin.rs +++ b/crates/factor-outbound-http/src/spin.rs @@ -15,10 +15,7 @@ impl spin_http::Host for crate::InstanceState { fields(otel.kind = "client", url.full = Empty, http.request.method = Empty, http.response.status_code = Empty, otel.name = Empty, server.address = Empty, server.port = Empty))] async fn send_request(&mut self, req: Request) -> Result { - if let Err(e) = self.otel_context.reparent_tracing_span() { - tracing::error!("{}", e.to_string()); - return Err(HttpError::RuntimeError); - }; + self.otel_context.reparent_tracing_span(); let span = Span::current(); record_request_fields(&span, &req); diff --git a/crates/factor-outbound-mqtt/src/host.rs b/crates/factor-outbound-mqtt/src/host.rs index cd59e1f700..a39d1a4b60 100644 --- a/crates/factor-outbound-mqtt/src/host.rs +++ b/crates/factor-outbound-mqtt/src/host.rs @@ -79,9 +79,7 @@ impl v2::HostConnection for InstanceState { password: String, keep_alive_interval: u64, ) -> Result, Error> { - if let Err(e) = self.otel_context.reparent_tracing_span() { - return Err(Error::Other(e.to_string())); - }; + self.otel_context.reparent_tracing_span(); if !self .is_address_allowed(&address) @@ -116,9 +114,7 @@ impl v2::HostConnection for InstanceState { payload: Vec, qos: Qos, ) -> Result<(), Error> { - if let Err(e) = self.otel_context.reparent_tracing_span() { - return Err(Error::Other(e.to_string())); - }; + self.otel_context.reparent_tracing_span(); let conn = self.get_conn(connection).await.map_err(other_error)?; diff --git a/crates/factor-outbound-mysql/src/host.rs b/crates/factor-outbound-mysql/src/host.rs index 26a646c5a0..ca113206aa 100644 --- a/crates/factor-outbound-mysql/src/host.rs +++ b/crates/factor-outbound-mysql/src/host.rs @@ -38,9 +38,7 @@ impl v2::Host for InstanceState {} impl v2::HostConnection for InstanceState { #[instrument(name = "spin_outbound_mysql.open", skip(self, address), err(level = Level::INFO), fields(otel.kind = "client", db.system = "mysql", db.address = Empty, server.port = Empty, db.namespace = Empty))] async fn open(&mut self, address: String) -> Result, v2::Error> { - if let Err(e) = self.otel_context.reparent_tracing_span() { - return Err(v2::Error::Other(e.to_string())); - }; + self.otel_context.reparent_tracing_span(); spin_factor_outbound_networking::record_address_fields(&address); if !self @@ -62,9 +60,7 @@ impl v2::HostConnection for InstanceState { statement: String, params: Vec, ) -> Result<(), v2::Error> { - if let Err(e) = self.otel_context.reparent_tracing_span() { - return Err(v2::Error::Other(e.to_string())); - }; + self.otel_context.reparent_tracing_span(); self.get_client(connection) .await? .execute(statement, params) @@ -78,9 +74,7 @@ impl v2::HostConnection for InstanceState { statement: String, params: Vec, ) -> Result { - if let Err(e) = self.otel_context.reparent_tracing_span() { - return Err(v2::Error::Other(e.to_string())); - }; + self.otel_context.reparent_tracing_span(); self.get_client(connection) .await? .query(statement, params) diff --git a/crates/factor-outbound-pg/src/host.rs b/crates/factor-outbound-pg/src/host.rs index d11a991f96..59ec645dff 100644 --- a/crates/factor-outbound-pg/src/host.rs +++ b/crates/factor-outbound-pg/src/host.rs @@ -219,9 +219,7 @@ impl v2::Host for InstanceState {} impl v2::HostConnection for InstanceState { #[instrument(name = "spin_outbound_pg.open", skip(self, address), err(level = Level::INFO), fields(otel.kind = "client", db.system = "postgresql", db.address = Empty, server.port = Empty, db.namespace = Empty))] async fn open(&mut self, address: String) -> Result, v2::Error> { - if let Err(e) = self.otel_context.reparent_tracing_span() { - return Err(v2::Error::Other(e.to_string())); - }; + self.otel_context.reparent_tracing_span(); spin_factor_outbound_networking::record_address_fields(&address); if !self @@ -243,9 +241,7 @@ impl v2::HostConnection for InstanceState { statement: String, params: Vec, ) -> Result { - if let Err(e) = self.otel_context.reparent_tracing_span() { - return Err(v2::Error::Other(e.to_string())); - }; + self.otel_context.reparent_tracing_span(); Ok(self .get_client(connection) .await? @@ -260,9 +256,7 @@ impl v2::HostConnection for InstanceState { statement: String, params: Vec, ) -> Result { - if let Err(e) = self.otel_context.reparent_tracing_span() { - return Err(v2::Error::Other(e.to_string())); - }; + self.otel_context.reparent_tracing_span(); Ok(self .get_client(connection) .await? diff --git a/crates/factor-outbound-redis/src/host.rs b/crates/factor-outbound-redis/src/host.rs index c7eae93902..2f265b90dc 100644 --- a/crates/factor-outbound-redis/src/host.rs +++ b/crates/factor-outbound-redis/src/host.rs @@ -65,9 +65,7 @@ impl v2::Host for crate::InstanceState { impl v2::HostConnection for crate::InstanceState { #[instrument(name = "spin_outbound_redis.open_connection", skip(self, address), err(level = Level::INFO), fields(otel.kind = "client", db.system = "redis", db.address = Empty, server.port = Empty, db.namespace = Empty))] async fn open(&mut self, address: String) -> Result, Error> { - if let Err(e) = self.otel_context.reparent_tracing_span() { - return Err(Error::Other(e.to_string())); - }; + self.otel_context.reparent_tracing_span(); if !self .is_address_allowed(&address) .await @@ -86,9 +84,7 @@ impl v2::HostConnection for crate::InstanceState { channel: String, payload: Vec, ) -> Result<(), Error> { - if let Err(e) = self.otel_context.reparent_tracing_span() { - return Err(Error::Other(e.to_string())); - }; + self.otel_context.reparent_tracing_span(); let conn = self.get_conn(connection).await.map_err(other_error)?; // The `let () =` syntax is needed to suppress a warning when the result type is inferred. @@ -106,9 +102,7 @@ impl v2::HostConnection for crate::InstanceState { connection: Resource, key: String, ) -> Result>, Error> { - if let Err(e) = self.otel_context.reparent_tracing_span() { - return Err(Error::Other(e.to_string())); - }; + self.otel_context.reparent_tracing_span(); let conn = self.get_conn(connection).await.map_err(other_error)?; let value = conn.get(&key).await.map_err(other_error)?; @@ -122,9 +116,7 @@ impl v2::HostConnection for crate::InstanceState { key: String, value: Vec, ) -> Result<(), Error> { - if let Err(e) = self.otel_context.reparent_tracing_span() { - return Err(Error::Other(e.to_string())); - }; + self.otel_context.reparent_tracing_span(); let conn = self.get_conn(connection).await.map_err(other_error)?; // The `let () =` syntax is needed to suppress a warning when the result type is inferred. @@ -139,9 +131,7 @@ impl v2::HostConnection for crate::InstanceState { connection: Resource, key: String, ) -> Result { - if let Err(e) = self.otel_context.reparent_tracing_span() { - return Err(Error::Other(e.to_string())); - }; + self.otel_context.reparent_tracing_span(); let conn = self.get_conn(connection).await.map_err(other_error)?; let value = conn.incr(&key, 1).await.map_err(other_error)?; @@ -154,9 +144,7 @@ impl v2::HostConnection for crate::InstanceState { connection: Resource, keys: Vec, ) -> Result { - if let Err(e) = self.otel_context.reparent_tracing_span() { - return Err(Error::Other(e.to_string())); - }; + self.otel_context.reparent_tracing_span(); let conn = self.get_conn(connection).await.map_err(other_error)?; let value = conn.del(&keys).await.map_err(other_error)?; @@ -170,9 +158,7 @@ impl v2::HostConnection for crate::InstanceState { key: String, values: Vec, ) -> Result { - if let Err(e) = self.otel_context.reparent_tracing_span() { - return Err(Error::Other(e.to_string())); - }; + self.otel_context.reparent_tracing_span(); let conn = self.get_conn(connection).await.map_err(other_error)?; let value = conn.sadd(&key, &values).await.map_err(|e| { @@ -191,9 +177,7 @@ impl v2::HostConnection for crate::InstanceState { connection: Resource, key: String, ) -> Result, Error> { - if let Err(e) = self.otel_context.reparent_tracing_span() { - return Err(Error::Other(e.to_string())); - }; + self.otel_context.reparent_tracing_span(); let conn = self.get_conn(connection).await.map_err(other_error)?; let value = conn.smembers(&key).await.map_err(other_error)?; @@ -207,9 +191,7 @@ impl v2::HostConnection for crate::InstanceState { key: String, values: Vec, ) -> Result { - if let Err(e) = self.otel_context.reparent_tracing_span() { - return Err(Error::Other(e.to_string())); - }; + self.otel_context.reparent_tracing_span(); let conn = self.get_conn(connection).await.map_err(other_error)?; let value = conn.srem(&key, &values).await.map_err(other_error)?; @@ -223,9 +205,7 @@ impl v2::HostConnection for crate::InstanceState { command: String, arguments: Vec, ) -> Result, Error> { - if let Err(e) = self.otel_context.reparent_tracing_span() { - return Err(Error::Other(e.to_string())); - }; + self.otel_context.reparent_tracing_span(); let conn = self.get_conn(connection).await?; let mut cmd = redis::cmd(&command); diff --git a/crates/factor-sqlite/src/host.rs b/crates/factor-sqlite/src/host.rs index 3011f72e4d..ddc6d0f5a8 100644 --- a/crates/factor-sqlite/src/host.rs +++ b/crates/factor-sqlite/src/host.rs @@ -158,9 +158,7 @@ impl v2::Host for InstanceState { impl v2::HostConnection for InstanceState { #[instrument(name = "spin_sqlite.open", skip(self), err(level = Level::INFO), fields(otel.kind = "client", db.system = "sqlite", sqlite.backend = Empty))] async fn open(&mut self, database: String) -> Result, v2::Error> { - if let Err(e) = self.otel_context.reparent_tracing_span() { - return Err(v2::Error::Io(e.to_string())); - }; + self.otel_context.reparent_tracing_span(); self.open_impl(database).await.map_err(to_v2_error) } @@ -171,9 +169,7 @@ impl v2::HostConnection for InstanceState { query: String, parameters: Vec, ) -> Result { - if let Err(e) = self.otel_context.reparent_tracing_span() { - return Err(v2::Error::Io(e.to_string())); - }; + self.otel_context.reparent_tracing_span(); self.execute_impl( connection, query, diff --git a/crates/factor-variables/src/host.rs b/crates/factor-variables/src/host.rs index bbef549987..784cebd280 100644 --- a/crates/factor-variables/src/host.rs +++ b/crates/factor-variables/src/host.rs @@ -8,9 +8,7 @@ use crate::InstanceState; impl variables::Host for InstanceState { #[instrument(name = "spin_variables.get", skip(self), fields(otel.kind = "client"))] async fn get(&mut self, key: String) -> Result { - if let Err(e) = self.otel_context.reparent_tracing_span() { - return Err(variables::Error::Other(e.to_string())); - }; + self.otel_context.reparent_tracing_span(); let key = spin_expressions::Key::new(&key).map_err(expressions_to_variables_err)?; self.expression_resolver .resolve(&self.component_id, key) diff --git a/crates/wasi-otel/src/common_conversions.rs b/crates/wasi-otel/src/common_conversions.rs new file mode 100644 index 0000000000..06c53fce1f --- /dev/null +++ b/crates/wasi-otel/src/common_conversions.rs @@ -0,0 +1,58 @@ +use super::wasi::{self, clocks0_2_0::wall_clock}; +use std::time::{Duration, SystemTime, UNIX_EPOCH}; + +impl From for opentelemetry::KeyValue { + fn from(kv: wasi::otel::types::KeyValue) -> Self { + opentelemetry::KeyValue::new(kv.key, kv.value) + } +} + +impl From<&wasi::otel::types::KeyValue> for opentelemetry::KeyValue { + fn from(kv: &wasi::otel::types::KeyValue) -> Self { + opentelemetry::KeyValue::new(kv.key.to_owned(), kv.value.to_owned()) + } +} + +impl From for opentelemetry::Value { + fn from(value: wasi::otel::types::Value) -> Self { + match value { + wasi::otel::types::Value::String(v) => v.into(), + wasi::otel::types::Value::Bool(v) => v.into(), + wasi::otel::types::Value::F64(v) => v.into(), + wasi::otel::types::Value::S64(v) => v.into(), + wasi::otel::types::Value::StringArray(v) => opentelemetry::Value::Array( + v.into_iter() + .map(opentelemetry::StringValue::from) + .collect::>() + .into(), + ), + wasi::otel::types::Value::BoolArray(v) => opentelemetry::Value::Array(v.into()), + wasi::otel::types::Value::F64Array(v) => opentelemetry::Value::Array(v.into()), + wasi::otel::types::Value::S64Array(v) => opentelemetry::Value::Array(v.into()), + } + } +} + +impl From for opentelemetry::InstrumentationScope { + fn from(value: wasi::otel::tracing::InstrumentationScope) -> Self { + let builder = + Self::builder(value.name).with_attributes(value.attributes.into_iter().map(Into::into)); + match (value.version, value.schema_url) { + (Some(version), Some(schema_url)) => builder + .with_version(version) + .with_schema_url(schema_url) + .build(), + (Some(version), None) => builder.with_version(version).build(), + (None, Some(schema_url)) => builder.with_schema_url(schema_url).build(), + (None, None) => builder.build(), + } + } +} + +impl From for SystemTime { + fn from(timestamp: wall_clock::Datetime) -> Self { + UNIX_EPOCH + + Duration::from_secs(timestamp.seconds) + + Duration::from_nanos(timestamp.nanoseconds as u64) + } +} diff --git a/crates/wasi-otel/src/lib.rs b/crates/wasi-otel/src/lib.rs index 52c8a5e63f..fc9619e675 100644 --- a/crates/wasi-otel/src/lib.rs +++ b/crates/wasi-otel/src/lib.rs @@ -46,4 +46,6 @@ wasmtime::component::bindgen!({ pub use fermyon::spin as v1; pub use fermyon::spin2_0_0 as v2; -mod conversions; +mod common_conversions; +mod metrics_conversions; +mod trace_conversions; diff --git a/crates/wasi-otel/src/conversions.rs b/crates/wasi-otel/src/metrics_conversions.rs similarity index 55% rename from crates/wasi-otel/src/conversions.rs rename to crates/wasi-otel/src/metrics_conversions.rs index d8b21719ce..ddb7af498e 100644 --- a/crates/wasi-otel/src/conversions.rs +++ b/crates/wasi-otel/src/metrics_conversions.rs @@ -1,9 +1,5 @@ -use super::*; -use opentelemetry::StringValue; -use opentelemetry_sdk::trace::{SpanEvents, SpanLinks}; +use super::wasi; use std::borrow::Cow; -use std::time::{Duration, SystemTime, UNIX_EPOCH}; -use wasi::clocks0_2_0::wall_clock; impl From for opentelemetry_sdk::metrics::data::ResourceMetrics @@ -273,212 +269,3 @@ impl From for opentelemetry_sdk::metrics::Temp } } } - -impl From for opentelemetry_sdk::trace::SpanData { - fn from(value: wasi::otel::tracing::SpanData) -> Self { - let mut span_events = SpanEvents::default(); - span_events.events = value.events.into_iter().map(Into::into).collect(); - span_events.dropped_count = value.dropped_events; - let mut span_links = SpanLinks::default(); - span_links.links = value.links.into_iter().map(Into::into).collect(); - span_links.dropped_count = value.dropped_links; - Self { - span_context: value.span_context.into(), - parent_span_id: opentelemetry::trace::SpanId::from_hex(&value.parent_span_id) - .unwrap_or(opentelemetry::trace::SpanId::INVALID), - span_kind: value.span_kind.into(), - name: value.name.into(), - start_time: value.start_time.into(), - end_time: value.end_time.into(), - attributes: value.attributes.into_iter().map(Into::into).collect(), - dropped_attributes_count: value.dropped_attributes, - events: span_events, - links: span_links, - status: value.status.into(), - instrumentation_scope: value.instrumentation_scope.into(), - } - } -} - -impl From for opentelemetry::trace::SpanContext { - fn from(sc: wasi::otel::tracing::SpanContext) -> Self { - let trace_id = opentelemetry::trace::TraceId::from_hex(&sc.trace_id) - .unwrap_or(opentelemetry::trace::TraceId::INVALID); - let span_id = opentelemetry::trace::SpanId::from_hex(&sc.span_id) - .unwrap_or(opentelemetry::trace::SpanId::INVALID); - let trace_state = opentelemetry::trace::TraceState::from_key_value(sc.trace_state) - .unwrap_or_else(|_| opentelemetry::trace::TraceState::default()); - Self::new( - trace_id, - span_id, - sc.trace_flags.into(), - sc.is_remote, - trace_state, - ) - } -} - -impl From for wasi::otel::tracing::SpanContext { - fn from(sc: opentelemetry::trace::SpanContext) -> Self { - Self { - trace_id: format!("{:x}", sc.trace_id()), - span_id: format!("{:x}", sc.span_id()), - trace_flags: sc.trace_flags().into(), - is_remote: sc.is_remote(), - trace_state: sc - .trace_state() - .header() - .split(',') - .filter_map(|s| { - if let Some((key, value)) = s.split_once('=') { - Some((key.to_string(), value.to_string())) - } else { - None - } - }) - .collect(), - } - } -} - -impl From for opentelemetry::trace::TraceFlags { - fn from(flags: wasi::otel::tracing::TraceFlags) -> Self { - Self::new(flags.as_array()[0] as u8) - } -} - -impl From for wasi::otel::tracing::TraceFlags { - fn from(flags: opentelemetry::trace::TraceFlags) -> Self { - if flags.is_sampled() { - wasi::otel::tracing::TraceFlags::SAMPLED - } else { - wasi::otel::tracing::TraceFlags::empty() - } - } -} - -impl From for opentelemetry::trace::SpanKind { - fn from(kind: wasi::otel::tracing::SpanKind) -> Self { - match kind { - wasi::otel::tracing::SpanKind::Client => opentelemetry::trace::SpanKind::Client, - wasi::otel::tracing::SpanKind::Server => opentelemetry::trace::SpanKind::Server, - wasi::otel::tracing::SpanKind::Producer => opentelemetry::trace::SpanKind::Producer, - wasi::otel::tracing::SpanKind::Consumer => opentelemetry::trace::SpanKind::Consumer, - wasi::otel::tracing::SpanKind::Internal => opentelemetry::trace::SpanKind::Internal, - } - } -} - -impl From for opentelemetry::KeyValue { - fn from(kv: wasi::otel::tracing::KeyValue) -> Self { - opentelemetry::KeyValue::new(kv.key, kv.value) - } -} - -impl From<&wasi::otel::tracing::KeyValue> for opentelemetry::KeyValue { - fn from(kv: &wasi::otel::tracing::KeyValue) -> Self { - opentelemetry::KeyValue::new(kv.key.to_owned(), kv.value.to_owned()) - } -} - -impl From for opentelemetry::Value { - fn from(value: wasi::otel::types::Value) -> Self { - match value { - wasi::otel::types::Value::String(v) => v.into(), - wasi::otel::types::Value::Bool(v) => v.into(), - wasi::otel::types::Value::F64(v) => v.into(), - wasi::otel::types::Value::S64(v) => v.into(), - wasi::otel::types::Value::StringArray(v) => opentelemetry::Value::Array( - v.into_iter() - .map(StringValue::from) - .collect::>() - .into(), - ), - wasi::otel::types::Value::BoolArray(v) => opentelemetry::Value::Array(v.into()), - wasi::otel::types::Value::F64Array(v) => opentelemetry::Value::Array(v.into()), - wasi::otel::types::Value::S64Array(v) => opentelemetry::Value::Array(v.into()), - } - } -} - -impl From for opentelemetry::trace::Event { - fn from(event: wasi::otel::tracing::Event) -> Self { - Self::new( - event.name, - event.time.into(), - event.attributes.into_iter().map(Into::into).collect(), - 0, - ) - } -} - -impl From for opentelemetry::trace::Link { - fn from(link: wasi::otel::tracing::Link) -> Self { - Self::new( - link.span_context.into(), - link.attributes.into_iter().map(Into::into).collect(), - 0, - ) - } -} - -impl From for opentelemetry::trace::Status { - fn from(status: wasi::otel::tracing::Status) -> Self { - match status { - wasi::otel::tracing::Status::Unset => Self::Unset, - wasi::otel::tracing::Status::Ok => Self::Ok, - wasi::otel::tracing::Status::Error(s) => Self::Error { - description: s.into(), - }, - } - } -} - -impl From for opentelemetry::InstrumentationScope { - fn from(value: wasi::otel::tracing::InstrumentationScope) -> Self { - let builder = - Self::builder(value.name).with_attributes(value.attributes.into_iter().map(Into::into)); - match (value.version, value.schema_url) { - (Some(version), Some(schema_url)) => builder - .with_version(version) - .with_schema_url(schema_url) - .build(), - (Some(version), None) => builder.with_version(version).build(), - (None, Some(schema_url)) => builder.with_schema_url(schema_url).build(), - (None, None) => builder.build(), - } - } -} - -impl From for SystemTime { - fn from(timestamp: wall_clock::Datetime) -> Self { - UNIX_EPOCH - + Duration::from_secs(timestamp.seconds) - + Duration::from_nanos(timestamp.nanoseconds as u64) - } -} - -mod test { - #[test] - fn trace_flags() { - let flags = opentelemetry::trace::TraceFlags::SAMPLED; - let flags2 = crate::wasi::otel::tracing::TraceFlags::from(flags); - let flags3 = opentelemetry::trace::TraceFlags::from(flags2); - assert_eq!(flags, flags3); - } - - #[test] - fn span_context() { - let sc = opentelemetry::trace::SpanContext::new( - opentelemetry::trace::TraceId::from_hex("4fb34cb4484029f7881399b149e41e98").unwrap(), - opentelemetry::trace::SpanId::from_hex("9ffd58d3cd4dd90b").unwrap(), - opentelemetry::trace::TraceFlags::SAMPLED, - false, - opentelemetry::trace::TraceState::from_key_value(vec![("foo", "bar"), ("baz", "qux")]) - .unwrap(), - ); - let sc2 = crate::wasi::otel::tracing::SpanContext::from(sc.clone()); - let sc3 = opentelemetry::trace::SpanContext::from(sc2); - assert_eq!(sc, sc3); - } -} diff --git a/crates/wasi-otel/src/trace_conversions.rs b/crates/wasi-otel/src/trace_conversions.rs new file mode 100644 index 0000000000..37e9fa1231 --- /dev/null +++ b/crates/wasi-otel/src/trace_conversions.rs @@ -0,0 +1,155 @@ +use super::wasi; +use opentelemetry_sdk::trace::{SpanEvents, SpanLinks}; + +impl From for opentelemetry_sdk::trace::SpanData { + fn from(value: wasi::otel::tracing::SpanData) -> Self { + let mut span_events = SpanEvents::default(); + span_events.events = value.events.into_iter().map(Into::into).collect(); + span_events.dropped_count = value.dropped_events; + let mut span_links = SpanLinks::default(); + span_links.links = value.links.into_iter().map(Into::into).collect(); + span_links.dropped_count = value.dropped_links; + Self { + span_context: value.span_context.into(), + parent_span_id: opentelemetry::trace::SpanId::from_hex(&value.parent_span_id) + .unwrap_or(opentelemetry::trace::SpanId::INVALID), + span_kind: value.span_kind.into(), + name: value.name.into(), + start_time: value.start_time.into(), + end_time: value.end_time.into(), + attributes: value.attributes.into_iter().map(Into::into).collect(), + dropped_attributes_count: value.dropped_attributes, + events: span_events, + links: span_links, + status: value.status.into(), + instrumentation_scope: value.instrumentation_scope.into(), + } + } +} + +impl From for opentelemetry::trace::SpanContext { + fn from(sc: wasi::otel::tracing::SpanContext) -> Self { + let trace_id = opentelemetry::trace::TraceId::from_hex(&sc.trace_id) + .unwrap_or(opentelemetry::trace::TraceId::INVALID); + let span_id = opentelemetry::trace::SpanId::from_hex(&sc.span_id) + .unwrap_or(opentelemetry::trace::SpanId::INVALID); + let trace_state = opentelemetry::trace::TraceState::from_key_value(sc.trace_state) + .unwrap_or_else(|_| opentelemetry::trace::TraceState::default()); + Self::new( + trace_id, + span_id, + sc.trace_flags.into(), + sc.is_remote, + trace_state, + ) + } +} + +impl From for wasi::otel::tracing::SpanContext { + fn from(sc: opentelemetry::trace::SpanContext) -> Self { + Self { + trace_id: format!("{:x}", sc.trace_id()), + span_id: format!("{:x}", sc.span_id()), + trace_flags: sc.trace_flags().into(), + is_remote: sc.is_remote(), + trace_state: sc + .trace_state() + .header() + .split(',') + .filter_map(|s| { + if let Some((key, value)) = s.split_once('=') { + Some((key.to_string(), value.to_string())) + } else { + None + } + }) + .collect(), + } + } +} + +impl From for opentelemetry::trace::TraceFlags { + fn from(flags: wasi::otel::tracing::TraceFlags) -> Self { + Self::new(flags.as_array()[0] as u8) + } +} + +impl From for wasi::otel::tracing::TraceFlags { + fn from(flags: opentelemetry::trace::TraceFlags) -> Self { + if flags.is_sampled() { + wasi::otel::tracing::TraceFlags::SAMPLED + } else { + wasi::otel::tracing::TraceFlags::empty() + } + } +} + +impl From for opentelemetry::trace::SpanKind { + fn from(kind: wasi::otel::tracing::SpanKind) -> Self { + match kind { + wasi::otel::tracing::SpanKind::Client => opentelemetry::trace::SpanKind::Client, + wasi::otel::tracing::SpanKind::Server => opentelemetry::trace::SpanKind::Server, + wasi::otel::tracing::SpanKind::Producer => opentelemetry::trace::SpanKind::Producer, + wasi::otel::tracing::SpanKind::Consumer => opentelemetry::trace::SpanKind::Consumer, + wasi::otel::tracing::SpanKind::Internal => opentelemetry::trace::SpanKind::Internal, + } + } +} + +impl From for opentelemetry::trace::Event { + fn from(event: wasi::otel::tracing::Event) -> Self { + Self::new( + event.name, + event.time.into(), + event.attributes.into_iter().map(Into::into).collect(), + 0, + ) + } +} + +impl From for opentelemetry::trace::Link { + fn from(link: wasi::otel::tracing::Link) -> Self { + Self::new( + link.span_context.into(), + link.attributes.into_iter().map(Into::into).collect(), + 0, + ) + } +} + +impl From for opentelemetry::trace::Status { + fn from(status: wasi::otel::tracing::Status) -> Self { + match status { + wasi::otel::tracing::Status::Unset => Self::Unset, + wasi::otel::tracing::Status::Ok => Self::Ok, + wasi::otel::tracing::Status::Error(s) => Self::Error { + description: s.into(), + }, + } + } +} + +mod test { + #[test] + fn trace_flags() { + let flags = opentelemetry::trace::TraceFlags::SAMPLED; + let flags2 = crate::wasi::otel::tracing::TraceFlags::from(flags); + let flags3 = opentelemetry::trace::TraceFlags::from(flags2); + assert_eq!(flags, flags3); + } + + #[test] + fn span_context() { + let sc = opentelemetry::trace::SpanContext::new( + opentelemetry::trace::TraceId::from_hex("4fb34cb4484029f7881399b149e41e98").unwrap(), + opentelemetry::trace::SpanId::from_hex("9ffd58d3cd4dd90b").unwrap(), + opentelemetry::trace::TraceFlags::SAMPLED, + false, + opentelemetry::trace::TraceState::from_key_value(vec![("foo", "bar"), ("baz", "qux")]) + .unwrap(), + ); + let sc2 = crate::wasi::otel::tracing::SpanContext::from(sc.clone()); + let sc3 = opentelemetry::trace::SpanContext::from(sc2); + assert_eq!(sc, sc3); + } +} From 0010ec6dec3b81889f92f3a2e8c1a45ae0e0c6b8 Mon Sep 17 00:00:00 2001 From: Andrew Steurer <94206073+asteurer@users.noreply.github.com> Date: Tue, 25 Nov 2025 22:28:11 +0000 Subject: [PATCH 08/13] feat(test): adding tests Signed-off-by: Andrew Steurer <94206073+asteurer@users.noreply.github.com> --- .../components/wasi-otel-tracing/src/lib.rs | 27 +++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/tests/test-components/components/wasi-otel-tracing/src/lib.rs b/tests/test-components/components/wasi-otel-tracing/src/lib.rs index c7d427b8bc..c604e2f3b5 100644 --- a/tests/test-components/components/wasi-otel-tracing/src/lib.rs +++ b/tests/test-components/components/wasi-otel-tracing/src/lib.rs @@ -1,5 +1,3 @@ -use std::time; - use opentelemetry::{ global::{self, BoxedTracer, ObjectSafeSpan}, trace::{TraceContextExt, Tracer}, @@ -11,6 +9,7 @@ use spin_sdk::{ http::{IntoResponse, Method, Params, Request, Response, Router}, http_component, }; +use std::time; #[http_component] fn handle(req: Request) -> anyhow::Result { @@ -21,6 +20,8 @@ fn handle(req: Request) -> anyhow::Result { router.get("/events", events); router.get("/links", links); router.get_async("/root-span", root_span); + router.get("/start-called-end-not-called", start_called_end_not_called); + router.get("/child-span-outlives-parent", child_span_outlives_parent); Ok(router.handle(req)) } @@ -125,6 +126,22 @@ async fn make_request() { let _res: Response = spin_sdk::http::send(req).await.unwrap(); } -// TODO: Test what happens if start is called but not end -// TODO: Test what happens if end is called but not start -// TODO: What happens if child span outlives parent +fn start_called_end_not_called(_req: Request, _params: Params) -> Response { + let (tracer, _ctx) = setup_tracer(false); + let _span = tracer.start("start_called_end_not_called"); + // span.end() is not called... + Response::new(200, "") +} + +fn child_span_outlives_parent(_req: Request, _params: Params) -> Response { + let (tracer, _ctx) = setup_tracer(false); + let child = { + let parent = tracer.start("parent"); + let parent_ctx = Context::current_with_span(parent); + let _guard = parent_ctx.clone().attach(); + let child = tracer.start("child"); + child + }; + drop(child); + Response::new(200, "") +} From e9017eaeb0d0bffd5ba59bd8d72bad0fa8d257f9 Mon Sep 17 00:00:00 2001 From: Andrew Steurer <94206073+asteurer@users.noreply.github.com> Date: Tue, 25 Nov 2025 22:29:43 +0000 Subject: [PATCH 09/13] removing unhelpful comments Signed-off-by: Andrew Steurer <94206073+asteurer@users.noreply.github.com> --- crates/factor-otel/src/host.rs | 1 - crates/factor-otel/src/lib.rs | 1 - 2 files changed, 2 deletions(-) diff --git a/crates/factor-otel/src/host.rs b/crates/factor-otel/src/host.rs index b9b7baf5c3..aeae4ea08c 100644 --- a/crates/factor-otel/src/host.rs +++ b/crates/factor-otel/src/host.rs @@ -6,7 +6,6 @@ use opentelemetry_sdk::error::OTelSdkError; use opentelemetry_sdk::metrics::exporter::PushMetricExporter; use opentelemetry_sdk::trace::SpanProcessor; use tracing_opentelemetry::OpenTelemetrySpanExt; -// TODO: This feels weird. I'm wondering if it can be fixed by wrangling the bindgen macro in `crates/wasi_otel/lib.rs`. use wasi_otel::wasi; impl wasi::otel::tracing::Host for InstanceState { diff --git a/crates/factor-otel/src/lib.rs b/crates/factor-otel/src/lib.rs index 3cd00d71cf..626944a0e4 100644 --- a/crates/factor-otel/src/lib.rs +++ b/crates/factor-otel/src/lib.rs @@ -29,7 +29,6 @@ impl Factor for OtelFactor { type InstanceBuilder = InstanceState; fn init(&mut self, ctx: &mut impl spin_factors::InitContext) -> anyhow::Result<()> { - // TODO: This feels weird. I'm wondering if it can be fixed by wrangling the bindgen macro in `crates/wasi_otel/lib.rs`. ctx.link_bindings(wasi_otel::wasi::otel::tracing::add_to_linker::<_, FactorData>)?; ctx.link_bindings(wasi_otel::wasi::otel::metrics::add_to_linker::<_, FactorData>)?; Ok(()) From bdbc5d494d6605e394fb5b8ac41d09b45957f54f Mon Sep 17 00:00:00 2001 From: Andrew Steurer <94206073+asteurer@users.noreply.github.com> Date: Tue, 25 Nov 2025 22:47:45 +0000 Subject: [PATCH 10/13] fix: removing empty test Signed-off-by: Andrew Steurer <94206073+asteurer@users.noreply.github.com> --- .../components/otel-smoke-test/Cargo.toml | 12 ---------- .../components/otel-smoke-test/src/lib.rs | 22 ------------------- 2 files changed, 34 deletions(-) delete mode 100644 tests/test-components/components/otel-smoke-test/Cargo.toml delete mode 100644 tests/test-components/components/otel-smoke-test/src/lib.rs diff --git a/tests/test-components/components/otel-smoke-test/Cargo.toml b/tests/test-components/components/otel-smoke-test/Cargo.toml deleted file mode 100644 index 521468b790..0000000000 --- a/tests/test-components/components/otel-smoke-test/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "otel-smoke-test" -version = "0.1.0" -edition = "2021" - -[lib] -crate-type = ["cdylib"] - -[dependencies] -anyhow = "1" -http = "0.2" -spin-sdk = "2.2.0" diff --git a/tests/test-components/components/otel-smoke-test/src/lib.rs b/tests/test-components/components/otel-smoke-test/src/lib.rs deleted file mode 100644 index 85c4326102..0000000000 --- a/tests/test-components/components/otel-smoke-test/src/lib.rs +++ /dev/null @@ -1,22 +0,0 @@ -use spin_sdk::{ - http::{Method, Params, Request, Response, Router}, - http_component, -}; - -#[http_component] -fn handle(req: http::Request<()>) -> Response { - let mut router = Router::new(); - router.get_async("/one", one); - router.get_async("/two", two); - router.handle(req) -} - -async fn one(_req: Request, _params: Params) -> Response { - let req = Request::builder().method(Method::Get).uri("/two").build(); - let _res: Response = spin_sdk::http::send(req).await.unwrap(); - Response::new(200, "") -} - -async fn two(_req: Request, _params: Params) -> Response { - Response::new(201, "") -} From 355cee5d68920c3842bd495e60199784f2df063a Mon Sep 17 00:00:00 2001 From: Andrew Steurer <94206073+asteurer@users.noreply.github.com> Date: Tue, 25 Nov 2025 22:47:53 +0000 Subject: [PATCH 11/13] fix: removing empty test Signed-off-by: Andrew Steurer <94206073+asteurer@users.noreply.github.com> --- tests/test-components/components/Cargo.lock | 9 --------- 1 file changed, 9 deletions(-) diff --git a/tests/test-components/components/Cargo.lock b/tests/test-components/components/Cargo.lock index 44ed4f0b48..fc46090628 100644 --- a/tests/test-components/components/Cargo.lock +++ b/tests/test-components/components/Cargo.lock @@ -859,15 +859,6 @@ dependencies = [ "thiserror 2.0.17", ] -[[package]] -name = "otel-smoke-test" -version = "0.1.0" -dependencies = [ - "anyhow", - "http 0.2.12", - "spin-sdk 2.2.0", -] - [[package]] name = "outbound-http-component" version = "0.1.0" From 879f70a8ce449c58b746984d7dcdaaae4159df66 Mon Sep 17 00:00:00 2001 From: Andrew Steurer <94206073+asteurer@users.noreply.github.com> Date: Tue, 25 Nov 2025 22:49:34 +0000 Subject: [PATCH 12/13] fix: removing empty test Signed-off-by: Andrew Steurer <94206073+asteurer@users.noreply.github.com> --- tests/testcases/otel-smoke-test/spin.toml | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100644 tests/testcases/otel-smoke-test/spin.toml diff --git a/tests/testcases/otel-smoke-test/spin.toml b/tests/testcases/otel-smoke-test/spin.toml deleted file mode 100644 index 909149421f..0000000000 --- a/tests/testcases/otel-smoke-test/spin.toml +++ /dev/null @@ -1,13 +0,0 @@ -spin_version = "1" -authors = ["Fermyon Engineering "] -description = "A simple application that tests otel." -name = "otel-smoke-test" -trigger = { type = "http" } -version = "1.0.0" - -[[component]] -id = "otel" -source = "%{source=otel-smoke-test}" -allowed_outbound_hosts = ["http://self"] -[component.trigger] -route = "/..." From d69860d4e4d73a24431aeb66944132eec5ddc6d3 Mon Sep 17 00:00:00 2001 From: Andrew Steurer <94206073+asteurer@users.noreply.github.com> Date: Wed, 26 Nov 2025 15:49:53 -0600 Subject: [PATCH 13/13] fix: linting Signed-off-by: Andrew Steurer <94206073+asteurer@users.noreply.github.com> --- tests/test-components/components/wasi-otel-tracing/src/lib.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/test-components/components/wasi-otel-tracing/src/lib.rs b/tests/test-components/components/wasi-otel-tracing/src/lib.rs index c604e2f3b5..c32c3123f0 100644 --- a/tests/test-components/components/wasi-otel-tracing/src/lib.rs +++ b/tests/test-components/components/wasi-otel-tracing/src/lib.rs @@ -139,8 +139,7 @@ fn child_span_outlives_parent(_req: Request, _params: Params) -> Response { let parent = tracer.start("parent"); let parent_ctx = Context::current_with_span(parent); let _guard = parent_ctx.clone().attach(); - let child = tracer.start("child"); - child + tracer.start("child") }; drop(child); Response::new(200, "")