From 93b7702016f98f1cc83f137649bc065286ec8466 Mon Sep 17 00:00:00 2001 From: Gabor Javorszky Date: Thu, 17 Oct 2024 15:08:59 +0100 Subject: [PATCH 1/6] otel: add opentelemetry rust crate code This is purely the source code of the rust end of opentelemetry. It does not have build tooling wired up yet, nor is this used from the C code. Signed-off-by: Ava Hahn Signed-off-by: Gabor Javorszky Co-authored-by: Ava Hahn --- src/otel/Cargo.lock | 2166 +++++++++++++++++++++++++++++++++++++++++++ src/otel/Cargo.toml | 23 + src/otel/src/lib.rs | 319 +++++++ 3 files changed, 2508 insertions(+) create mode 100644 src/otel/Cargo.lock create mode 100644 src/otel/Cargo.toml create mode 100644 src/otel/src/lib.rs diff --git a/src/otel/Cargo.lock b/src/otel/Cargo.lock new file mode 100644 index 000000000..c1a0e4399 --- /dev/null +++ b/src/otel/Cargo.lock @@ -0,0 +1,2166 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5fb1d8e4442bd405fdfd1dacb42792696b0cf9cb15882e5d097b742a676d375" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + +[[package]] +name = "anyhow" +version = "1.0.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" + +[[package]] +name = "async-channel" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" +dependencies = [ + "concurrent-queue", + "event-listener 2.5.3", + "futures-core", +] + +[[package]] +name = "async-channel" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a" +dependencies = [ + "concurrent-queue", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-executor" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30ca9a001c1e8ba5149f91a74362376cc6bc5b919d92d988668657bd570bdcec" +dependencies = [ + "async-task", + "concurrent-queue", + "fastrand", + "futures-lite", + "slab", +] + +[[package]] +name = "async-global-executor" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c" +dependencies = [ + "async-channel 2.3.1", + "async-executor", + "async-io", + "async-lock", + "blocking", + "futures-lite", + "once_cell", +] + +[[package]] +name = "async-io" +version = "2.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "444b0228950ee6501b3568d3c93bf1176a1fdbc3b758dcd9475046d30f4dc7e8" +dependencies = [ + "async-lock", + "cfg-if", + "concurrent-queue", + "futures-io", + "futures-lite", + "parking", + "polling", + "rustix", + "slab", + "tracing", + "windows-sys 0.59.0", +] + +[[package]] +name = "async-lock" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" +dependencies = [ + "event-listener 5.3.1", + "event-listener-strategy", + "pin-project-lite", +] + +[[package]] +name = "async-std" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c634475f29802fde2b8f0b505b1bd00dfe4df7d4a000f0b36f7671197d5c3615" +dependencies = [ + "async-channel 1.9.0", + "async-global-executor", + "async-io", + "async-lock", + "crossbeam-utils", + "futures-channel", + "futures-core", + "futures-io", + "futures-lite", + "gloo-timers", + "kv-log-macro", + "log", + "memchr", + "once_cell", + "pin-project-lite", + "pin-utils", + "slab", + "wasm-bindgen-futures", +] + +[[package]] +name = "async-stream" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" +dependencies = [ + "async-stream-impl", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-stream-impl" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "async-task" +version = "4.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" + +[[package]] +name = "async-trait" +version = "0.1.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "axum" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "504e3947307ac8326a5437504c517c4b56716c9d98fac0028c2acc7ca47d70ae" +dependencies = [ + "async-trait", + "axum-core", + "bytes", + "futures-util", + "http", + "http-body", + "http-body-util", + "itoa", + "matchit", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "rustversion", + "serde", + "sync_wrapper 1.0.1", + "tower 0.5.1", + "tower-layer", + "tower-service", +] + +[[package]] +name = "axum-core" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199" +dependencies = [ + "async-trait", + "bytes", + "futures-util", + "http", + "http-body", + "http-body-util", + "mime", + "pin-project-lite", + "rustversion", + "sync_wrapper 1.0.1", + "tower-layer", + "tower-service", +] + +[[package]] +name = "backtrace" +version = "0.3.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-targets", +] + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "blocking" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "703f41c54fc768e63e091340b424302bb1c29ef4aa0c7f10fe849dfb114d29ea" +dependencies = [ + "async-channel 2.3.1", + "async-task", + "futures-io", + "futures-lite", + "piper", +] + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" + +[[package]] +name = "cc" +version = "1.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "812acba72f0a070b003d3697490d2b55b837230ae7c6c6497f05cc2ddbb8d938" +dependencies = [ + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "crossbeam-utils" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "encoding_rs" +version = "0.8.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + +[[package]] +name = "event-listener" +version = "5.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" +dependencies = [ + "event-listener 5.3.1", + "pin-project-lite", +] + +[[package]] +name = "fastrand" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-executor" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[package]] +name = "futures-lite" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "parking", + "pin-project-lite", +] + +[[package]] +name = "futures-macro" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "gimli" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64" + +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + +[[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 = "h2" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http", + "indexmap 2.6.0", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" + +[[package]] +name = "http" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +dependencies = [ + "bytes", + "futures-util", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "hyper" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" +dependencies = [ + "futures-util", + "http", + "hyper", + "hyper-util", + "rustls", + "rustls-native-certs", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", + "webpki-roots", +] + +[[package]] +name = "hyper-timeout" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3203a961e5c83b6f5498933e78b6b263e208c197b63e9c6c53cc82ffd3f63793" +dependencies = [ + "hyper", + "hyper-util", + "pin-project-lite", + "tokio", + "tower-service", +] + +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", +] + +[[package]] +name = "idna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", +] + +[[package]] +name = "indexmap" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +dependencies = [ + "equivalent", + "hashbrown 0.15.0", +] + +[[package]] +name = "ipnet" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "187674a687eed5fe42285b40c6291f9a01517d415fad1c3cbc6a9f778af7fcd4" + +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "js-sys" +version = "0.3.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" +dependencies = [ + "wasm-bindgen", +] + +[[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 = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.159" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" + +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +dependencies = [ + "value-bag", +] + +[[package]] +name = "matchit" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", +] + +[[package]] +name = "mio" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +dependencies = [ + "hermit-abi 0.3.9", + "libc", + "wasi", + "windows-sys 0.52.0", +] + +[[package]] +name = "native-tls" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "object" +version = "0.36.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82881c4be219ab5faaf2ad5e5e5ecdff8c66bd7402ca3160975c93b24961afd1" +dependencies = [ + "portable-atomic", +] + +[[package]] +name = "openssl" +version = "0.10.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" +dependencies = [ + "bitflags", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "opentelemetry" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c365a63eec4f55b7efeceb724f1336f26a9cf3427b70e59e2cd2a5b947fba96" +dependencies = [ + "futures-core", + "futures-sink", + "js-sys", + "once_cell", + "pin-project-lite", + "thiserror", +] + +[[package]] +name = "opentelemetry-http" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad31e9de44ee3538fb9d64fe3376c1362f406162434609e79aea2a41a0af78ab" +dependencies = [ + "async-trait", + "bytes", + "http", + "opentelemetry", + "reqwest", +] + +[[package]] +name = "opentelemetry-otlp" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b925a602ffb916fb7421276b86756027b37ee708f9dce2dbdcc51739f07e727" +dependencies = [ + "async-trait", + "futures-core", + "http", + "opentelemetry", + "opentelemetry-http", + "opentelemetry-proto", + "opentelemetry_sdk", + "prost", + "reqwest", + "thiserror", + "tokio", + "tonic", +] + +[[package]] +name = "opentelemetry-proto" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30ee9f20bff9c984511a02f082dc8ede839e4a9bf15cc2487c8d6fea5ad850d9" +dependencies = [ + "opentelemetry", + "opentelemetry_sdk", + "prost", + "tonic", +] + +[[package]] +name = "opentelemetry-semantic-conventions" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cefe0543875379e47eb5f1e68ff83f45cc41366a92dfd0d073d513bf68e9a05" + +[[package]] +name = "opentelemetry_sdk" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "692eac490ec80f24a17828d49b40b60f5aeaccdfe6a503f939713afd22bc28df" +dependencies = [ + "async-trait", + "futures-channel", + "futures-executor", + "futures-util", + "glob", + "http", + "once_cell", + "opentelemetry", + "percent-encoding", + "rand", + "serde_json", + "thiserror", + "tokio", + "tokio-stream", +] + +[[package]] +name = "otel" +version = "0.1.0" +dependencies = [ + "async-std", + "lazy_static", + "once_cell", + "opentelemetry", + "opentelemetry-otlp", + "opentelemetry-semantic-conventions", + "opentelemetry_sdk", + "reqwest", + "tokio", + "tracing", + "tracing-core", + "tracing-subscriber", +] + +[[package]] +name = "parking" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets", +] + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pin-project" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "piper" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" +dependencies = [ + "atomic-waker", + "fastrand", + "futures-io", +] + +[[package]] +name = "pkg-config" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" + +[[package]] +name = "polling" +version = "3.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc2790cd301dec6cd3b7a025e4815cf825724a51c98dccfe6a3e55f05ffb6511" +dependencies = [ + "cfg-if", + "concurrent-queue", + "hermit-abi 0.4.0", + "pin-project-lite", + "rustix", + "tracing", + "windows-sys 0.59.0", +] + +[[package]] +name = "portable-atomic" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2" + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "prost" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b0487d90e047de87f984913713b85c601c05609aad5b0df4b4573fbf69aa13f" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-derive" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9552f850d5f0964a4e4d0bf306459ac29323ddfbae05e35a7c0d35cb0803cc5" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "quinn" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c7c5fdde3cdae7203427dc4f0a68fe0ed09833edc525a03456b153b79828684" +dependencies = [ + "bytes", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls", + "socket2", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "quinn-proto" +version = "0.11.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fadfaed2cd7f389d0161bb73eeb07b7b78f8691047a6f3e73caaeae55310a4a6" +dependencies = [ + "bytes", + "rand", + "ring", + "rustc-hash", + "rustls", + "slab", + "thiserror", + "tinyvec", + "tracing", +] + +[[package]] +name = "quinn-udp" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fe68c2e9e1a1234e218683dbdf9f9dfcb094113c5ac2b938dfcb9bab4c4140b" +dependencies = [ + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.59.0", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "redox_syscall" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +dependencies = [ + "bitflags", +] + +[[package]] +name = "reqwest" +version = "0.12.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" +dependencies = [ + "base64", + "bytes", + "encoding_rs", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-tls", + "hyper-util", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "quinn", + "rustls", + "rustls-native-certs", + "rustls-pemfile", + "rustls-pki-types", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper 1.0.1", + "system-configuration", + "tokio", + "tokio-native-tls", + "tokio-rustls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "webpki-roots", + "windows-registry", +] + +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustc-hash" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" + +[[package]] +name = "rustix" +version = "0.38.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustls" +version = "0.23.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2dabaac7466917e566adb06783a81ca48944c6898a1b08b9374106dd671f4c8" +dependencies = [ + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-native-certs" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcaf18a4f2be7326cd874a5fa579fae794320a0f388d365dca7e480e55f83f8a" +dependencies = [ + "openssl-probe", + "rustls-pemfile", + "rustls-pki-types", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" + +[[package]] +name = "rustls-webpki" +version = "0.102.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "rustversion" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "schannel" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9aaafd5a2b6e3d657ff009d82fbd630b6bd54dd4eb06f21693925cdf80f9b8b" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "security-framework" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "serde" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.128" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signal-hook-registry" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +dependencies = [ + "libc", +] + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "socket2" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "2.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + +[[package]] +name = "sync_wrapper" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +dependencies = [ + "futures-core", +] + +[[package]] +name = "system-configuration" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +dependencies = [ + "bitflags", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "tempfile" +version = "3.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" +dependencies = [ + "cfg-if", + "fastrand", + "once_cell", + "rustix", + "windows-sys 0.59.0", +] + +[[package]] +name = "thiserror" +version = "1.0.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tinyvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.40.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys 0.52.0", +] + +[[package]] +name = "tokio-macros" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +dependencies = [ + "rustls", + "rustls-pki-types", + "tokio", +] + +[[package]] +name = "tokio-stream" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tonic" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877c5b330756d856ffcc4553ab34a5684481ade925ecc54bcd1bf02b1d0d4d52" +dependencies = [ + "async-stream", + "async-trait", + "axum", + "base64", + "bytes", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-timeout", + "hyper-util", + "percent-encoding", + "pin-project", + "prost", + "socket2", + "tokio", + "tokio-stream", + "tower 0.4.13", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "indexmap 1.9.3", + "pin-project", + "pin-project-lite", + "rand", + "slab", + "tokio", + "tokio-util", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2873938d487c3cfb9aed7546dc9f2711d867c9f90c46b889989a2cb84eba6b4f" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper 0.1.2", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +dependencies = [ + "tracing-core", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "unicode-bidi" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" + +[[package]] +name = "unicode-ident" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" + +[[package]] +name = "unicode-normalization" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "url" +version = "2.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "value-bag" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a84c137d37ab0142f0f2ddfe332651fdbf252e7b7dbb4e67b6c1f1b2e925101" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" + +[[package]] +name = "web-sys" +version = "0.3.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki-roots" +version = "0.26.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841c67bff177718f1d4dfefde8d8f0e78f9b6589319ba88312f567fc5841a958" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "windows-registry" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" +dependencies = [ + "windows-result", + "windows-strings", + "windows-targets", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result", + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" diff --git a/src/otel/Cargo.toml b/src/otel/Cargo.toml new file mode 100644 index 000000000..286647313 --- /dev/null +++ b/src/otel/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "otel" +version = "0.1.0" +edition = "2021" + +[lib] +crate-type = ["staticlib"] +bench = false + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[dependencies] +once_cell = "1.19" +opentelemetry = "0.24.0" +opentelemetry_sdk = { version = "0.24.1", features = ["rt-tokio", "http", "tokio", "trace"] } +lazy_static = "1.5.0" +opentelemetry-otlp = { version = "0.17.0", features = ["http-proto", "tokio", "grpc-tonic","tonic","trace","reqwest-rustls"]} +tokio = { version = "1", features = ["full"] } +opentelemetry-semantic-conventions = "0.16.0" +tracing = { version = "0.1", default-features = false } +tracing-core = { version = "0.1", default-features = false } +tracing-subscriber = { version = "0.3", default-features = false } +async-std = "1.12.0" +reqwest = { version = "0.12.7", features = ["rustls-tls"] } diff --git a/src/otel/src/lib.rs b/src/otel/src/lib.rs new file mode 100644 index 000000000..349338043 --- /dev/null +++ b/src/otel/src/lib.rs @@ -0,0 +1,319 @@ +use opentelemetry::global::BoxedSpan; +use opentelemetry::trace::{ + Span, SpanBuilder, SpanKind, TraceId, Tracer, TracerProvider, +}; +use opentelemetry::{global, KeyValue}; +use opentelemetry_otlp::Protocol; +use opentelemetry_otlp::WithExportConfig; +use opentelemetry_sdk::trace::{Config, BatchConfigBuilder, Sampler}; +use opentelemetry_sdk::{runtime, Resource}; +use std::ffi::{CStr, CString}; +use std::{ptr, time}; +use std::ptr::addr_of; +use std::slice; +use std::sync::{Arc, OnceLock}; +use tokio::sync::mpsc; +use tokio::sync::mpsc::{Receiver, Sender}; + + +const TRACEPARENT_HEADER_LEN: u8 = 55; +const TIMEOUT: time::Duration = std::time::Duration::from_secs(10); + +#[repr(C)] +pub struct nxt_str_t { + pub len: usize, + pub start: *const u8, +} + +// Stored sender channel to send spans or a shutdown message to within the +// Tokio runtime. +unsafe fn nxt_otel_rs_span_tx(destruct: bool) -> *const OnceLock> { + static mut SPAN_TX: OnceLock> = OnceLock::new(); + if destruct { + SPAN_TX.take(); + } + + addr_of!(SPAN_TX) +} + +// Message type to send on the channel. Either a span or a shutdown message for +// graceful termination of the tokio runtime. +enum SpanMessage { + Span { + s: Arc + }, + Shutdown, +} + +#[no_mangle] +unsafe fn nxt_otel_rs_is_init() -> u8 { + (*nxt_otel_rs_span_tx(false)).get().map_or(0, |_| 1) +} + +#[no_mangle] +unsafe fn nxt_otel_rs_uninit() { + if nxt_otel_rs_is_init() == 1 { + nxt_otel_rs_shutdown_tracer(); + nxt_otel_rs_span_tx(true); + } +} + +// potentially returns an error message +#[no_mangle] +unsafe fn nxt_otel_rs_init( + log_callback: unsafe extern "C" fn(*mut i8), + endpoint: *const nxt_str_t, + protocol: *const nxt_str_t, + sample_fraction: f64, + batch_size: f64 +) { + if endpoint.is_null() || + protocol.is_null() { + return + } + + let ep = String::from_utf8_unchecked( + slice::from_raw_parts((*endpoint).start, (*endpoint).len).to_vec() + ).clone(); // we want our own memory + + let proto: Protocol; + match String::from_utf8_unchecked( + slice::from_raw_parts((*protocol).start, (*protocol).len).to_vec() + ).to_lowercase() + .as_str() { + "http" => proto = Protocol::HttpBinary, + "grpc" => proto = Protocol::Grpc, + e => { + let msg_string = format!("unknown tracer type: {:#?}", e); + let msg = CString::from_vec_unchecked(msg_string.as_bytes().to_vec()); + log_callback(msg.into_raw() as _); + return; + } + } + + // make sure we are starting with a clean state + nxt_otel_rs_uninit(); + + // Create a new mpsc channel. Tokio runtime gets receiver, the send + // trace function gets sender. + let (tx, rx): (Sender, Receiver) = mpsc::channel(32); + + // Store the sender so the other function can also reach it. + match (*nxt_otel_rs_span_tx(false)).set(tx) { + /* spawn a new thread with the tokio runtime and forget about it. + * This function will return that allows the C code to carry on + * doing its thing, whereas the runtime function is a long lived + * process that only exits when a shutdown message is sent. + */ + Ok(_) => { + std::thread::spawn(move || nxt_otel_rs_runtime( + log_callback, + ep, + proto, + batch_size, + sample_fraction, + rx + )); + }, + Err(e) => { + let msg_string = format!("couldn't initialize tracer: {:#?}", e); + let msg = CString::from_vec_unchecked(msg_string.as_bytes().to_vec()); + log_callback(msg.into_raw() as _); + } + } +} + + +/* function that we wrap around Tokio's runtime code. This is long lived, + * which means it stops only when a shutdown signal is sent to the rx + * channel, or we terminate the process and leave memory all over. + */ +#[tokio::main] +async unsafe fn nxt_otel_rs_runtime( + log_callback: unsafe extern "C" fn(*mut i8), + endpoint: String, + proto: Protocol, + batch_size: f64, + sample_fraction: f64, + mut rx: Receiver +) { + let pipeline = opentelemetry_otlp::new_pipeline() + .tracing() + .with_trace_config( + Config::default() + .with_resource( + Resource::new(vec![KeyValue::new( + opentelemetry_semantic_conventions::resource::SERVICE_NAME, + "NGINX Unit", + )]) + ) + .with_sampler(Sampler::TraceIdRatioBased(sample_fraction)) + ) + .with_batch_config( + BatchConfigBuilder::default() + .with_max_export_batch_size(batch_size as _) + .with_max_queue_size(4098) + .build() + ); + + let res = match proto { + Protocol::HttpBinary | Protocol::HttpJson => pipeline + .with_exporter( + opentelemetry_otlp::new_exporter() + .http() + .with_http_client(reqwest::Client::new()) // needed because rustls feature + .with_endpoint(endpoint) + .with_protocol(proto) + .with_timeout(TIMEOUT) + ).install_batch(runtime::Tokio), + Protocol::Grpc => pipeline + .with_exporter( + opentelemetry_otlp::new_exporter() + .tonic() + .with_endpoint(endpoint) + .with_protocol(proto) + .with_timeout(TIMEOUT) + ).install_batch(runtime::Tokio), + }; + + match res { + Err(e) => { + let msg = CString::from_vec_unchecked(e.to_string().as_bytes().to_vec()); + log_callback(msg.into_raw() as _); + return; + } + Ok(t) => { + global::set_tracer_provider(t); + let msg = CString::from_vec_unchecked("otel exporter has been initialised".as_bytes().to_vec()); + log_callback(msg.into_raw() as _); + } + } + + // this is the block that keeps this function running until it gets shut down. + // @see https://tokio.rs/tokio/tutorial/channels for the inspiration. + while let Some(message) = rx.recv().await { + match message { + SpanMessage::Shutdown => { + eprintln!("it was a shutdown"); + break; + } + SpanMessage::Span { s: _s } => { + // do nothing, because the point is for this _s var to be dropped + // here rather than where it was sent from. + } + } + } +} + +// it's on the caller to pass in a buf of proper length +#[no_mangle] +pub unsafe fn nxt_otel_rs_copy_traceparent(buf: *mut i8, span: *const BoxedSpan) { + if buf.is_null() || span.is_null() { + return; + } + + let traceparent = format!( + "00-{:032x}-{:016x}-{:02x}", + (*span).span_context().trace_id(), // 16 chars, 32 hex + (*span).span_context().span_id(), // 8 byte, 16 hex + (*span).span_context().trace_flags() // 1 char, 2 hex + ); + + assert_eq!(traceparent.len(), TRACEPARENT_HEADER_LEN as usize); + + ptr::copy_nonoverlapping( + traceparent.as_bytes().as_ptr(), + buf as _, + TRACEPARENT_HEADER_LEN as _, + ); + // set null terminator + *buf.add(TRACEPARENT_HEADER_LEN as _) = b'\0' as _; +} + +#[no_mangle] +pub unsafe fn nxt_otel_rs_add_event_to_trace( + trace: *mut BoxedSpan, + key: *const nxt_str_t, + val: *const nxt_str_t, +) { + if !key.is_null() && !val.is_null() && !trace.is_null() { + /* We need .clone() here because when using the batch exporter, when the + * trace gets exported, the request object that these pointers pointed to + * no longer exists. + */ + let key = String::from_utf8_unchecked( + slice::from_raw_parts((*key).start, (*key).len).to_vec() + ).clone(); + let val = String::from_utf8_unchecked( + slice::from_raw_parts((*val).start, (*val).len).to_vec() + ).clone(); + + (*trace).add_event( + String::from("Unit Attribute"), + vec![KeyValue::new(key, val)] + ); + } +} + +#[no_mangle] +pub unsafe fn nxt_otel_rs_get_or_create_trace(trace_id: *mut i8) -> *mut BoxedSpan { + let mut trace_key = None; + let trace_cstr: &CStr; + if !trace_id.is_null() { + trace_cstr = CStr::from_ptr(trace_id as _); + // We need .into_owned() here as well to avoid referencing a deallocated piece of memory. + if let Ok(id) = TraceId::from_hex(&trace_cstr.to_string_lossy().into_owned()) { + trace_key = Some(id); + } + } + + let tracer = global::tracer_provider().tracer("NGINX Unit"); + let span = tracer.build(SpanBuilder { + trace_id: trace_key, + span_kind: Some(SpanKind::Server), + ..Default::default() + }); + + Arc::::into_raw(Arc::new(span)) as *mut BoxedSpan +} + +#[no_mangle] +pub unsafe fn nxt_otel_rs_send_trace(trace: *mut BoxedSpan) { + // damage nothing on an improper call + if trace.is_null() { + eprintln!("trace was null, returning"); + return; + } + + /* memory needs to be accounted for via arc here + * see the final return statement from + * nxt_otel_get_or_create_trace + */ + let arc_span = Arc::from_raw(trace); + + /* Instead of dropping the reference at the end of this function + * we'll send the entire Arc through the channel to the long + * running process that will drop it there. The reason we need to + * drop it there, rather than here is because that code block is + * within the tokio runtime context with the mpsc channels still + * open, whereas if we tried to do it here, it would fail for + * a number of different reasons: + * - channel closed + * - not a tokio runtime + * - different tokio runtime + */ + (*nxt_otel_rs_span_tx(false)) + .get() + .and_then(|x| Some(x.try_send(SpanMessage::Span{ s: arc_span }))); +} + +/* Function to send a shutdown signal to the tokio runtime. + * The receive loop will break and exit. + * It might be better to close the channels here instead. + */ +#[no_mangle] +pub unsafe fn nxt_otel_rs_shutdown_tracer() { + (*nxt_otel_rs_span_tx(false)) + .get() + .and_then(|x| Some(x.try_send(SpanMessage::Shutdown))); +} From 6b6f9c6b7768a803368b8572dad51d6194d8fcb6 Mon Sep 17 00:00:00 2001 From: Gabor Javorszky Date: Thu, 17 Oct 2024 15:23:38 +0100 Subject: [PATCH 2/6] otel: add build tooling to include otel code Adds the --otel flag to the configure command and the various build time variables and checks that are needed in this flow. It also includes the nxt_otel.c and nxt_otel.h files that are needed for the rest of Unit to talk to the compiled static library that's generated from the rust crate. Signed-off-by: Ava Hahn Signed-off-by: Gabor Javorszky Co-authored-by: Ava Hahn --- auto/help | 2 + auto/make | 49 +++-- auto/options | 2 + auto/otel | 50 ++++++ auto/sources | 4 + auto/summary | 1 + configure | 6 + src/nxt_http.h | 7 + src/nxt_http_error.c | 9 + src/nxt_http_request.c | 10 +- src/nxt_otel.c | 397 +++++++++++++++++++++++++++++++++++++++++ src/nxt_otel.h | 75 ++++++++ 12 files changed, 600 insertions(+), 12 deletions(-) create mode 100644 auto/otel create mode 100644 src/nxt_otel.c create mode 100644 src/nxt_otel.h diff --git a/auto/help b/auto/help index 6a6aee19e..948547623 100644 --- a/auto/help +++ b/auto/help @@ -52,6 +52,8 @@ cat << END --njs enable njs library usage + --otel enable otel library usage + --debug enable debug logging --fuzz=ENGINE enable fuzz testing diff --git a/auto/make b/auto/make index f21a2dfc5..05d7b17c6 100644 --- a/auto/make +++ b/auto/make @@ -7,7 +7,6 @@ $echo "creating $NXT_MAKEFILE" - cat << END > $NXT_MAKEFILE # Pretty print compiler etc actions... @@ -22,6 +21,8 @@ AR = $AR EXTRA_CFLAGS = CFLAGS = $NXT_CFLAGS $NXT_CC_OPT $CFLAGS \$(EXTRA_CFLAGS) +RUST_FLAGS = +NXT_OTEL_LIB_LOC = NXT_EXEC_LINK = $NXT_EXEC_LINK $NXT_LD_OPT NXT_SHARED_LOCAL_LINK = $NXT_SHARED_LOCAL_LINK $NXT_LD_OPT @@ -62,6 +63,9 @@ D := 0 ifeq (\$D,1) CFLAGS += -O0 + RUST_FLAGS += --debug +else + RUST_FLAGS += --release endif # Optionally disable -Werror with @@ -76,6 +80,18 @@ END fi +# potentially set otel lib location +if [ $NXT_OTEL = YES ]; then +cat << END >> $NXT_MAKEFILE + +ifeq (\$D,1) + NXT_OTEL_LIB_LOC = $NXT_OTEL_LIB_DIR/target/debug/libotel.a +else + NXT_OTEL_LIB_LOC = $NXT_OTEL_LIB_DIR/target/release/libotel.a +endif + +END +fi # The include paths list. @@ -138,14 +154,14 @@ cat << END >> $NXT_MAKEFILE libnxt: $NXT_BUILD_DIR/lib/$NXT_LIB_SHARED $NXT_BUILD_DIR/lib/$NXT_LIB_STATIC -$NXT_BUILD_DIR/lib/$NXT_LIB_SHARED: \$(NXT_LIB_OBJS) +$NXT_BUILD_DIR/lib/$NXT_LIB_SHARED: \$(NXT_LIB_OBJS) \$(NXT_OTEL_LIB_LOC) \$(PP_LD) \$@ \$(v)\$(NXT_SHARED_LOCAL_LINK) -o \$@ \$(NXT_LIB_OBJS) \\ - $NXT_LIBM $NXT_LIBS $NXT_LIB_AUX_LIBS + $NXT_LIBM $NXT_LIBS $NXT_LIB_AUX_LIBS \$(NXT_OTEL_LIB_LOC) -$NXT_BUILD_DIR/lib/$NXT_LIB_STATIC: \$(NXT_LIB_OBJS) +$NXT_BUILD_DIR/lib/$NXT_LIB_STATIC: \$(NXT_LIB_OBJS) \$(NXT_OTEL_LIB_LOC) \$(PP_AR) \$@ - \$(v)$NXT_STATIC_LINK \$@ \$(NXT_LIB_OBJS) + \$(v)$NXT_STATIC_LINK \$@ \$(NXT_LIB_OBJS) \$(NXT_OTEL_LIB_LOC) $NXT_BUILD_DIR/lib/$NXT_LIB_UNIT_STATIC: \$(NXT_LIB_UNIT_OBJS) \\ $NXT_BUILD_DIR/share/pkgconfig/unit.pc \\ @@ -359,11 +375,11 @@ $echo >> $NXT_MAKEFILE cat << END >> $NXT_MAKEFILE $NXT_BUILD_DIR/sbin/$NXT_DAEMON: $NXT_BUILD_DIR/lib/$NXT_LIB_STATIC \\ - \$(NXT_OBJS) + \$(NXT_OBJS) \$(NXT_OTEL_LIB_LOC) \$(PP_LD) \$@ \$(v)\$(NXT_EXEC_LINK) -o \$@ \$(CFLAGS) \\ \$(NXT_OBJS) $NXT_BUILD_DIR/lib/$NXT_LIB_STATIC \\ - $NXT_LIBM $NXT_LIBS $NXT_LIB_AUX_LIBS + $NXT_LIBM $NXT_LIBS $NXT_LIB_AUX_LIBS \$(NXT_OTEL_LIB_LOC) END @@ -535,10 +551,6 @@ cat << END > Makefile include $NXT_MAKEFILE -.PHONY: clean -clean: - rm -rf $NXT_BUILD_DIR *.dSYM Makefile - .PHONY: help help: @echo "Variables to control make/build behaviour:" @@ -551,4 +563,19 @@ help: @echo @echo " Variables can be combined." +.PHONY: clean +clean: + rm -rf $NXT_BUILD_DIR *.dSYM Makefile +END + +if [ $NXT_OTEL = YES ]; then + cat << END >> Makefile + cd "$NXT_OTEL_LIB_DIR" && cargo clean +END + + cat << END >> $NXT_MAKEFILE + +\$(NXT_OTEL_LIB_LOC): + cargo build \$(RUST_FLAGS) --manifest-path $NXT_OTEL_LIB_DIR/Cargo.toml END +fi diff --git a/auto/options b/auto/options index 5be1ebe18..7aa7a73a9 100644 --- a/auto/options +++ b/auto/options @@ -27,6 +27,7 @@ NXT_CYASSL=NO NXT_POLARSSL=NO NXT_NJS=NO +NXT_OTEL=NO NXT_TEST_BUILD_EPOLL=NO NXT_TEST_BUILD_EVENTPORT=NO @@ -112,6 +113,7 @@ do --polarssl) NXT_POLARSSL=YES ;; --njs) NXT_NJS=YES ;; + --otel) NXT_OTEL=YES ;; --test-build-epoll) NXT_TEST_BUILD_EPOLL=YES ;; --test-build-eventport) NXT_TEST_BUILD_EVENTPORT=YES ;; diff --git a/auto/otel b/auto/otel new file mode 100644 index 000000000..0de7538e3 --- /dev/null +++ b/auto/otel @@ -0,0 +1,50 @@ + +# Copyright (C) NGINX, Inc. + +if [ $NXT_OTEL = YES ]; then + + $echo -n "looking for rust compiler ... " + if [ -z `which rustc 2>/dev/null` ]; then + $echo "not found." + exit 1; + fi + $echo "found." + + $echo -n "looking for cargo ... " + if [ -z `which cargo 2>/dev/null` ]; then + $echo "not found." + exit 1; + fi + $echo "found." + + nxt_feature="OpenSSL library" + nxt_feature_run=yes + nxt_feature_incs= + nxt_feature_libs="-lssl -lcrypto" + nxt_feature_test="#include + + int main(void) { + SSL_library_init(); + return 0; + }" + . auto/feature + + if [ ! $nxt_found = yes ]; then + $echo + $echo $0: error: OpenTelemetry support requires OpenSSL. + $echo + exit 1; + fi + + NXT_OTEL_LIBS="-lssl -lcrypto" + if [ $(which pkg-config) ]; then + NXT_OTEL_LIBS="$(pkg-config openssl --cflags --libs)" + fi + cat << END >> $NXT_AUTO_CONFIG_H + +#ifndef NXT_HAVE_OTEL +#define NXT_HAVE_OTEL 1 +#endif + +END +fi diff --git a/auto/sources b/auto/sources index dfabf7cf2..027403970 100644 --- a/auto/sources +++ b/auto/sources @@ -127,6 +127,10 @@ if [ "$NXT_NJS" != "NO" ]; then NXT_LIB_SRCS="$NXT_LIB_SRCS src/nxt_js.c src/nxt_http_js.c src/nxt_script.c" fi +if [ "$NXT_OTEL" != "NO" ]; then + NXT_LIB_SRCS="$NXT_LIB_SRCS src/nxt_otel.c" +fi + NXT_LIB_EPOLL_SRCS="src/nxt_epoll_engine.c" NXT_LIB_KQUEUE_SRCS="src/nxt_kqueue_engine.c" NXT_LIB_EVENTPORT_SRCS="src/nxt_eventport_engine.c" diff --git a/auto/summary b/auto/summary index b6caee6c6..eba88be4c 100644 --- a/auto/summary +++ b/auto/summary @@ -30,6 +30,7 @@ Unit configuration summary: TLS support: ............... $NXT_OPENSSL Regex support: ............. $NXT_REGEX njs support: ............... $NXT_NJS + otel support: .............. $NXT_OTEL process isolation: ......... $NXT_ISOLATION cgroupv2: .................. $NXT_HAVE_CGROUP diff --git a/configure b/configure index 6929d41da..05a992ee2 100755 --- a/configure +++ b/configure @@ -179,6 +179,12 @@ if [ $NXT_NJS != NO ]; then . auto/njs fi +NXT_OTEL_LIB_DIR=src/otel +if [ $NXT_OTEL != NO ]; then + . auto/otel + NXT_LIB_AUX_LIBS="$NXT_LIB_AUX_LIBS $NXT_OTEL_LIBS" +fi + . auto/make . auto/fuzzing . auto/summary diff --git a/src/nxt_http.h b/src/nxt_http.h index 5369c8e16..bc76d67eb 100644 --- a/src/nxt_http.h +++ b/src/nxt_http.h @@ -9,6 +9,9 @@ #include +#if (NXT_HAVE_OTEL) +#include +#endif typedef enum { NXT_HTTP_UNSET = -1, @@ -190,6 +193,10 @@ struct nxt_http_request_s { nxt_http_response_t resp; +#if (NXT_HAVE_OTEL) + nxt_otel_state_t *otel; +#endif + nxt_http_status_t status:16; uint8_t log_route; /* 1 bit */ diff --git a/src/nxt_http_error.c b/src/nxt_http_error.c index 370b12dbc..be5aef101 100644 --- a/src/nxt_http_error.c +++ b/src/nxt_http_error.c @@ -8,6 +8,11 @@ #include +#if (NXT_HAVE_OTEL) +#include +#endif + + static void nxt_http_request_send_error_body(nxt_task_t *task, void *r, void *data); @@ -55,6 +60,10 @@ nxt_http_request_error(nxt_task_t *task, nxt_http_request_t *r, r->resp.content_length = NULL; r->resp.content_length_n = NXT_HTTP_ERROR_LEN; +#if (NXT_HAVE_OTEL) + nxt_otel_request_error_path(task, r); +#endif + r->state = &nxt_http_request_send_error_body_state; nxt_http_request_header_send(task, r, diff --git a/src/nxt_http_request.c b/src/nxt_http_request.c index a7e9ff69a..d32226991 100644 --- a/src/nxt_http_request.c +++ b/src/nxt_http_request.c @@ -283,7 +283,15 @@ nxt_http_request_create(nxt_task_t *task) task->thread->engine->requests_cnt++; r->tstr_cache.var.pool = mp; - +#if (NXT_HAVE_OTEL) + if (nxt_otel_rs_is_init()) { + r->otel = nxt_mp_zget(r->mem_pool, sizeof(nxt_otel_state_t)); + if (r->otel == NULL) { + goto fail; + } + r->otel->status = NXT_OTEL_INIT_STATE; + } +#endif return r; fail: diff --git a/src/nxt_otel.c b/src/nxt_otel.c new file mode 100644 index 000000000..40be19309 --- /dev/null +++ b/src/nxt_otel.c @@ -0,0 +1,397 @@ + +/* + * Copyright (C) F5, Inc. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define NXT_OTEL_TRACEPARENT_LEN 55 +#define NXT_OTEL_BODY_SIZE_TAG "body size" +#define NXT_OTEL_METHOD_TAG "method" +#define NXT_OTEL_PATH_TAG "path" +#define NXT_OTEL_STATUS_CODE_TAG "status" + + +static void +nxt_otel_state_transition(nxt_otel_state_t *state, nxt_otel_status_t status) +{ + if (status == NXT_OTEL_ERROR_STATE + || state->status != NXT_OTEL_ERROR_STATE) { + state->status = status; + } +} + + +static void +nxt_otel_propagate_header(nxt_task_t *task, nxt_http_request_t *r) +{ + u_char *traceval; + nxt_str_t traceparent_name, traceparent; + nxt_http_field_t *f; + + traceval = nxt_mp_zalloc(r->mem_pool, NXT_OTEL_TRACEPARENT_LEN + 1); + if (traceval == NULL) { + /* + * let it go blank here. + * span still gets populated and sent + * but data is not propagated to peer or app. + */ + nxt_log(task, NXT_LOG_ERR, + "couldn't allocate traceparent header. span will not propagate"); + return; + } + + if (r->otel->trace_id != NULL) { + // copy in the pre-existing traceparent for the response + sprintf((char *) traceval, "%s-%s-%s-%s", + (char *) r->otel->version, + (char *) r->otel->trace_id, + (char *) r->otel->parent_id, + (char *) r->otel->trace_flags); + + /* + * if we didnt inherit a trace id then we need to add then + * traceparent header to the request + */ + } else if (r->otel->trace_id == NULL) { + + nxt_otel_rs_copy_traceparent(traceval, r->otel->trace); + f = nxt_list_add(r->fields); + if (f == NULL) { + return; + } + + nxt_http_field_name_set(f, "traceparent"); + f->value = traceval; + f->value_length = nxt_strlen(traceval); + traceparent_name = (nxt_str_t){ + .start = f->name, + .length = f->name_length, + }; + traceparent = (nxt_str_t){ + .start = f->value, + .length = f->value_length, + }; + nxt_otel_rs_add_event_to_trace(r->otel->trace, + &traceparent_name, + &traceparent); + + // potentially nxt_http_request_error called before headers finished parsing + } else { + nxt_log(task, NXT_LOG_DEBUG, + "not propagating tracing headers for missing trace"); + return; + } + + f = nxt_list_add(r->resp.fields); + if (f == NULL) { + nxt_log(task, NXT_LOG_ERR, + "couldn't allocate traceparent header in response"); + return; + } + + nxt_http_field_name_set(f, "traceparent"); + f->value = traceval; + f->value_length = nxt_strlen(traceval); +} + + +static void +nxt_otel_span_add_headers(nxt_task_t *task, nxt_http_request_t *r) +{ + nxt_str_t method_name, path_name; + nxt_http_field_t *cur; + + nxt_log(task, NXT_LOG_DEBUG, "adding headers to trace"); + + if (r->otel == NULL || r->otel->trace == NULL) { + nxt_log(task, NXT_LOG_ERR, "no trace to add events to!"); + nxt_otel_state_transition(r->otel, NXT_OTEL_ERROR_STATE); + return; + } + + nxt_list_each(cur, r->fields) { + nxt_str_t name, val; + name = (nxt_str_t){ + .start = cur->name, + .length = cur->name_length, + }; + + val = (nxt_str_t){ + .start = cur->value, + .length = cur->value_length, + }; + + nxt_otel_rs_add_event_to_trace(r->otel->trace, &name, &val); + } nxt_list_loop; + + nxt_str_set(&method_name, NXT_OTEL_METHOD_TAG); + nxt_otel_rs_add_event_to_trace(r->otel->trace, &method_name, r->method); + nxt_str_set(&path_name, NXT_OTEL_PATH_TAG); + nxt_otel_rs_add_event_to_trace(r->otel->trace, &path_name, r->path); + nxt_otel_propagate_header(task, r); + + nxt_otel_state_transition(r->otel, NXT_OTEL_BODY_STATE); +} + + +static void +nxt_otel_span_add_body(nxt_http_request_t *r) +{ + size_t body_size = 0; + size_t buf_size; + u_char *body_buf, *body_size_buf; + nxt_str_t body_key, body_val; + nxt_int_t cur; + + if (r->body != NULL) { + body_size = nxt_buf_used_size(r->body); + } + + buf_size = 1; // first digit + if (body_size != 0) { + buf_size += log10(body_size); // subsequent digits + } + buf_size += 1; // \0 + buf_size += nxt_length(NXT_OTEL_BODY_SIZE_TAG); + buf_size += 1; // \0 + + body_buf = nxt_mp_alloc(r->mem_pool, buf_size); + if (body_buf == NULL) { + return; + } + + cur = sprintf((char *) body_buf, "%lu", body_size); + if (cur < 0) { + return; + } + + cur += 1; + body_size_buf = body_buf + cur; + nxt_cpystr(body_buf + cur, (const u_char *) NXT_OTEL_BODY_SIZE_TAG); + + body_key = (nxt_str_t){ + .start = body_size_buf, + .length = nxt_length(body_size_buf), + }; + body_val = (nxt_str_t){ + .start = body_buf, + .length = nxt_length(body_buf), + }; + + nxt_otel_rs_add_event_to_trace(r->otel->trace, &body_key, &body_val); + nxt_otel_state_transition(r->otel, NXT_OTEL_COLLECT_STATE); +} + + +static void +nxt_otel_span_add_status(nxt_task_t *task, nxt_http_request_t *r) +{ + u_char *status_buf; + nxt_str_t status_key, status_val; + + // dont bother logging an unset status + if (r->status == 0) { + return; + } + + // add specific 3 byte status to span + status_buf = nxt_mp_alloc(r->mem_pool, 4); + if (status_buf == NULL) { + return; + } + + sprintf((char *) status_buf, "%i", r->status); + + // set up event + status_key = (nxt_str_t){ + .start = (u_char *) NXT_OTEL_STATUS_CODE_TAG, + .length = nxt_length(NXT_OTEL_STATUS_CODE_TAG), + }; + status_val = (nxt_str_t){ + .start = status_buf, + .length = 4, + }; + nxt_otel_rs_add_event_to_trace(r->otel->trace, &status_key, &status_val); +} + + +static void +nxt_otel_span_collect(nxt_task_t *task, nxt_http_request_t *r) +{ + if (r->otel->trace == NULL) { + nxt_log(task, NXT_LOG_ERR, "otel error: no trace to send!"); + nxt_otel_state_transition(r->otel, NXT_OTEL_ERROR_STATE); + return; + } + + nxt_otel_span_add_status(task, r); + nxt_otel_state_transition(r->otel, NXT_OTEL_UNINIT_STATE); + nxt_otel_rs_send_trace(r->otel->trace); + + r->otel->trace = NULL; +} + + +static void +nxt_otel_error(nxt_task_t *task, nxt_http_request_t *r) +{ + // purposefully not using state transition helper + r->otel->status = NXT_OTEL_UNINIT_STATE; + nxt_log(task, NXT_LOG_ERR, "otel error condition"); + + /* + * assumable at time of writing that there is no + * r->otel->trace to leak. This state is only set + * in cases where trace fails to generate or is missing + */ +} + + +static void +nxt_otel_trace_and_span_init(nxt_task_t *task, nxt_http_request_t *r) +{ + r->otel->trace = + nxt_otel_rs_get_or_create_trace(r->otel->trace_id); + if (r->otel->trace == NULL) { + nxt_log(task, NXT_LOG_ERR, "error generating otel span"); + nxt_otel_state_transition(r->otel, NXT_OTEL_ERROR_STATE); + return; + } + + nxt_otel_state_transition(r->otel, NXT_OTEL_HEADER_STATE); +} + + +void +nxt_otel_test_and_call_state(nxt_task_t *task, nxt_http_request_t *r) +{ + if (r == NULL || r->otel == NULL) { + return; + } + + switch (r->otel->status) { + case NXT_OTEL_UNINIT_STATE: + return; + case NXT_OTEL_INIT_STATE: + nxt_otel_trace_and_span_init(task, r); + break; + case NXT_OTEL_HEADER_STATE: + nxt_otel_span_add_headers(task, r); + break; + case NXT_OTEL_BODY_STATE: + nxt_otel_span_add_body(r); + break; + case NXT_OTEL_COLLECT_STATE: + nxt_otel_span_collect(task, r); + break; + case NXT_OTEL_ERROR_STATE: + nxt_otel_error(task, r); + break; + } +} + + +// called in nxt_http_request_error +void +nxt_otel_request_error_path(nxt_task_t *task, nxt_http_request_t *r) +{ + if (r->otel->trace == NULL) { + return; + } + + // response headers have been cleared + nxt_otel_propagate_header(task, r); + + // collect span immediately + if (r->otel) { + nxt_otel_state_transition(r->otel, NXT_OTEL_COLLECT_STATE); + } + nxt_otel_test_and_call_state(task, r); +} + + +nxt_int_t +nxt_otel_parse_traceparent(void *ctx, nxt_http_field_t *field, uintptr_t data) +{ + char *copy; + nxt_http_request_t *r; + + /* + * For information on parsing the traceparent header: + * https://www.w3.org/TR/trace-context/#traceparent-header + * A summary of the traceparent header value format follows: + * Traceparent: "$a-$b-$c-$d" + * a. version (2 hex digits) (ff is forbidden) + * b. trace_id (32 hex digits) (all zeroes forbidden) + * c. parent_id (16 hex digits) (all zeroes forbidden) + * d. flags (2 hex digits) + */ + + r = ctx; + if (field->value_length != NXT_OTEL_TRACEPARENT_LEN) { + goto error_state; + } + + /* strsep is destructive so we make a copy of the field + */ + copy = nxt_mp_zalloc(r->mem_pool, field->value_length + 1); + if (copy == NULL) { + goto error_state; + } + memcpy(copy, field->value, field->value_length); + + r->otel->version = (u_char *) strsep(©, "-"); + r->otel->trace_id = (u_char *) strsep(©, "-"); + r->otel->parent_id = (u_char *) strsep(©, "-"); + r->otel->trace_flags = (u_char *) strsep(©, "-"); + + if (r->otel->version == NULL + || r->otel->trace_id == NULL + || r->otel->parent_id == NULL + || r->otel->trace_flags == NULL) { + goto error_state; + } + + return NXT_OK; + +error_state: + nxt_otel_state_transition(r->otel, NXT_OTEL_ERROR_STATE); + return NXT_ERROR; +} + + +nxt_int_t +nxt_otel_parse_tracestate(void *ctx, nxt_http_field_t *field, uintptr_t data) +{ + nxt_str_t s; + nxt_http_field_t *f; + nxt_http_request_t *r; + + s.length = field->value_length; + s.start = field->value; + r = ctx; + r->otel->trace_state = s; + + // maybe someday this should get sent down into the otel lib + // when we can figure out what to do with it at least + + f = nxt_list_add(r->resp.fields); + if (f != NULL) { + *f = *field; + } + + return NXT_OK; +} diff --git a/src/nxt_otel.h b/src/nxt_otel.h new file mode 100644 index 000000000..f833b1eea --- /dev/null +++ b/src/nxt_otel.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) F5, Inc. + */ + +#ifndef _NXT_OTEL_H_INCLUDED_ +#define _NXT_OTEL_H_INCLUDED_ + +#include +#include + +// forward declared +struct nxt_http_field_t; +struct nxt_conf_validation_t; +struct nxt_conf_value_t; +struct nxt_http_request_t; + +extern void nxt_otel_rs_send_trace(void *trace); +extern void * nxt_otel_rs_get_or_create_trace(u_char *trace_id); +extern void nxt_otel_rs_init(void (*log_callback)(u_char *log_string), + const nxt_str_t *endpoint, + const nxt_str_t *protocol, + double sample_fraction, + double batch_size); +extern void nxt_otel_rs_copy_traceparent(u_char *buffer, void *span); +extern void nxt_otel_rs_add_event_to_trace(void *trace, + nxt_str_t *key, + nxt_str_t *val); +extern uint8_t nxt_otel_rs_is_init(void); +extern void nxt_otel_rs_uninit(void); + + +typedef enum nxt_otel_status_e nxt_otel_status_t; +typedef struct nxt_otel_state_s nxt_otel_state_t; + + +/* + * nxt_otel_status_t + * more efficient than a single handler state struct + */ +enum nxt_otel_status_e { + NXT_OTEL_UNINIT_STATE = 0, + NXT_OTEL_INIT_STATE, + NXT_OTEL_HEADER_STATE, + NXT_OTEL_BODY_STATE, + NXT_OTEL_COLLECT_STATE, + NXT_OTEL_ERROR_STATE, +}; + +/* + * nxt_otel_state_t + * cache of trace data needed per request and + * includes indicator as to current flow state + */ +struct nxt_otel_state_s { + u_char *trace_id; + u_char *version; + u_char *parent_id; + u_char *trace_flags; + void *trace; + nxt_otel_status_t status; + nxt_str_t trace_state; +}; + + +nxt_int_t nxt_otel_parse_traceparent(void *ctx, + nxt_http_field_t *field, + uintptr_t data); +nxt_int_t nxt_otel_parse_tracestate(void *ctx, + nxt_http_field_t *field, + uintptr_t data); + +void nxt_otel_test_and_call_state(nxt_task_t *task, nxt_http_request_t *r); +void nxt_otel_request_error_path(nxt_task_t *task, nxt_http_request_t *r); + +#endif // _NXT_OTEL_H_INCLUDED_ From 2ef8f21f8d3d47a286c05e9cd37a973c29394b62 Mon Sep 17 00:00:00 2001 From: Ava Hahn Date: Wed, 23 Oct 2024 16:30:39 -0700 Subject: [PATCH 3/6] otel: add header parsing and test call state Enables Unit to parse the tracestate and traceparent headers and add it to the list, as well as calls to nxt_otel_test_and_call_state. Signed-off-by: Ava Hahn --- src/nxt_h1proto.c | 12 ++++++++++++ src/nxt_http_request.c | 12 ++++++++++++ 2 files changed, 24 insertions(+) diff --git a/src/nxt_h1proto.c b/src/nxt_h1proto.c index 48c2697bc..3e45de501 100644 --- a/src/nxt_h1proto.c +++ b/src/nxt_h1proto.c @@ -178,6 +178,10 @@ static nxt_http_field_proc_t nxt_h1p_fields[] = { { nxt_string("Content-Length"), &nxt_http_request_content_length, 0 }, { nxt_string("Authorization"), &nxt_http_request_field, offsetof(nxt_http_request_t, authorization) }, +#if (NXT_HAVE_OTEL) + { nxt_string("Traceparent"), &nxt_otel_parse_traceparent, 0 }, + { nxt_string("Tracestate"), &nxt_otel_parse_tracestate, 0 }, +#endif }; @@ -518,6 +522,10 @@ nxt_h1p_conn_request_init(nxt_task_t *task, void *obj, void *data) h1p->parser.discard_unsafe_fields = skcf->discard_unsafe_fields; nxt_h1p_conn_request_header_parse(task, c, h1p); +#if (NXT_HAVE_OTEL) + nxt_otel_test_and_call_state(task, r); +#endif + return; } @@ -1332,6 +1340,10 @@ nxt_h1p_request_header_send(nxt_task_t *task, nxt_http_request_t *r, nxt_debug(task, "h1p request header send"); +#if (NXT_HAVE_OTEL) + nxt_otel_test_and_call_state(task, r); +#endif + r->header_sent = 1; h1p = r->proto.h1; n = r->status; diff --git a/src/nxt_http_request.c b/src/nxt_http_request.c index d32226991..4a208b584 100644 --- a/src/nxt_http_request.c +++ b/src/nxt_http_request.c @@ -7,6 +7,10 @@ #include #include +#if(NXT_HAVE_OTEL) +#include +#endif + static nxt_int_t nxt_http_validate_host(nxt_str_t *host, nxt_mp_t *mp); static void nxt_http_request_start(nxt_task_t *task, void *obj, void *data); @@ -319,6 +323,10 @@ nxt_http_request_start(nxt_task_t *task, void *obj, void *data) r = obj; +#if (NXT_HAVE_OTEL) + nxt_otel_test_and_call_state(task, r); +#endif + r->state = &nxt_http_request_body_state; skcf = r->conf->socket_conf; @@ -590,6 +598,10 @@ nxt_http_request_ready(nxt_task_t *task, void *obj, void *data) r = obj; action = r->conf->socket_conf->action; +#if (NXT_HAVE_OTEL) + nxt_otel_test_and_call_state(task, r); +#endif + if (r->chunked) { ret = nxt_http_request_chunked_transform(r); if (nxt_slow_path(ret != NXT_OK)) { From 91d1d2f136220c91e3a8df47b5ecff8c36c30092 Mon Sep 17 00:00:00 2001 From: Gabor Javorszky Date: Thu, 17 Oct 2024 18:49:06 +0100 Subject: [PATCH 4/6] otel: configuration items and their validation Adds code responsible for users to apply the `telemetry` configuration options. configuration snippet as follows: { "settings": { "telemetry": { "batch_size": 20, "endpoint": "http://lgtm:4318/v1/traces", "protocol": "http", "sampling_ratio": 1 } }, "listeners": { "*:80": { "pass": "routes" } }, "routes": [ { "match": { "headers": { "accept": "*text/html*" } }, "action": { "share": "/usr/share/unit/welcome/welcome.html" } }, { "action": { "share": "/usr/share/unit/welcome/welcome.md" } } ] } Signed-off-by: Ava Hahn Signed-off-by: Gabor Javorszky Co-authored-by: Ava Hahn --- src/nxt_conf_validation.c | 117 ++++++++++++++++++++++++++++++++++++++ src/nxt_router.c | 45 +++++++++++++++ 2 files changed, 162 insertions(+) diff --git a/src/nxt_conf_validation.c b/src/nxt_conf_validation.c index 5d7f7c52b..b597d8654 100644 --- a/src/nxt_conf_validation.c +++ b/src/nxt_conf_validation.c @@ -241,6 +241,21 @@ static nxt_int_t nxt_conf_vldt_js_module_element(nxt_conf_validation_t *vldt, nxt_conf_value_t *value); #endif +#if (NXT_HAVE_OTEL) +nxt_inline nxt_int_t nxt_otel_validate_endpoint(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, + void *data); +nxt_int_t nxt_otel_validate_batch_size(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, + void *data); +nxt_int_t nxt_otel_validate_sample_ratio(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, + void *data); +nxt_int_t nxt_otel_validate_protocol(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, + void *data); +#endif + static nxt_conf_vldt_object_t nxt_conf_vldt_setting_members[]; static nxt_conf_vldt_object_t nxt_conf_vldt_http_members[]; @@ -307,6 +322,34 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_root_members[] = { }; + +#if (NXT_HAVE_OTEL) +static nxt_conf_vldt_object_t nxt_conf_vldt_otel_members[] = { + { + .name = nxt_string("endpoint"), + .type = NXT_CONF_VLDT_STRING, + .validator = nxt_otel_validate_endpoint, + .flags = NXT_CONF_VLDT_REQUIRED + }, { + .name = nxt_string("batch_size"), + .type = NXT_CONF_VLDT_INTEGER, + .validator = nxt_otel_validate_batch_size, + }, { + .name = nxt_string("protocol"), + .type = NXT_CONF_VLDT_STRING, + .validator = nxt_otel_validate_protocol, + .flags = NXT_CONF_VLDT_REQUIRED + }, { + .name = nxt_string("sampling_ratio"), + .type = NXT_CONF_VLDT_NUMBER, + .validator = nxt_otel_validate_sample_ratio, + }, + + NXT_CONF_VLDT_END +}; +#endif + + static nxt_conf_vldt_object_t nxt_conf_vldt_setting_members[] = { { .name = nxt_string("listen_threads"), @@ -317,6 +360,13 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_setting_members[] = { .type = NXT_CONF_VLDT_OBJECT, .validator = nxt_conf_vldt_object, .u.members = nxt_conf_vldt_http_members, +#if (NXT_HAVE_OTEL) + }, { + .name = nxt_string("telemetry"), + .type = NXT_CONF_VLDT_OBJECT, + .validator = nxt_conf_vldt_object, + .u.members = nxt_conf_vldt_otel_members, +#endif #if (NXT_HAVE_NJS) }, { .name = nxt_string("js_module"), @@ -1465,6 +1515,73 @@ nxt_conf_validate(nxt_conf_validation_t *vldt) "a number, a string, an array, or an object" + +#if (NXT_HAVE_OTEL) +inline nxt_int_t +nxt_otel_validate_endpoint(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, + void *data) +{ + // This function is a stub for now + return NXT_OK; +} + + +nxt_int_t +nxt_otel_validate_batch_size(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, + void *data) +{ + double batch_size; + batch_size = nxt_conf_get_number(value); + if (batch_size <= 0) { + return NXT_ERROR; + } + + return NXT_OK; +} + +nxt_int_t +nxt_otel_validate_sample_ratio(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, + void *data) +{ + double sample_ratio; + + sample_ratio = nxt_conf_get_number(value); + if (sample_ratio < 0 || sample_ratio > 1) { + return NXT_ERROR; + } + + return NXT_OK; +} + +nxt_int_t +nxt_otel_validate_protocol(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, + void *data) +{ + nxt_str_t proto; + + nxt_conf_get_string(value, &proto); + if (nxt_str_eq(&proto, "HTTP", 4) || + nxt_str_eq(&proto, "http", 4)) { + goto happy; + } + + if (nxt_str_eq(&proto, "GRPC", 4) || + nxt_str_eq(&proto, "grpc", 4)) { + goto happy; + } + + return NXT_ERROR; + + happy: + return NXT_OK; +} +#endif + + static nxt_int_t nxt_conf_vldt_type(nxt_conf_validation_t *vldt, const nxt_str_t *name, nxt_conf_value_t *value, nxt_conf_vldt_type_t type) diff --git a/src/nxt_router.c b/src/nxt_router.c index 076cd134b..4d6c241c9 100644 --- a/src/nxt_router.c +++ b/src/nxt_router.c @@ -23,6 +23,10 @@ #include #define NXT_SHARED_PORT_ID 0xFFFFu +#if (NXT_HAVE_OTEL) +#define NXT_OTEL_BATCH_DEFAULT 128 +#define NXT_OTEL_SAMPLING_DEFAULT 1 +#endif typedef struct { nxt_str_t type; @@ -1613,6 +1617,12 @@ static nxt_conf_map_t nxt_router_websocket_conf[] = { }; +#if (NXT_HAVE_OTEL) +static void nxt_otel_log_callback(u_char *arg) { + printf("otel: %s", (char *) arg); +} +#endif + static nxt_int_t nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, u_char *start, u_char *end) @@ -1635,6 +1645,11 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, #endif #if (NXT_HAVE_NJS) nxt_conf_value_t *js_module; +#endif +#if (NXT_HAVE_OTEL) + nxt_conf_value_t *otel, *otel_endpoint, *otel_sampling, *otel_batching, *otel_proto; + nxt_str_t telemetry_endpoint, telemetry_proto; + double telemetry_sample_fraction, telemetry_batching; #endif nxt_conf_value_t *root, *conf, *http, *value, *websocket; nxt_conf_value_t *applications, *application, *settings; @@ -1671,6 +1686,13 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, nxt_string("/settings/http/websocket"); static const nxt_str_t forwarded_path = nxt_string("/forwarded"); static const nxt_str_t client_ip_path = nxt_string("/client_ip"); +#if (NXT_HAVE_OTEL) + static const nxt_str_t telemetry_path = nxt_string("/settings/telemetry"); + static const nxt_str_t telemetry_endpoint_path = nxt_string("/settings/telemetry/endpoint"); + static const nxt_str_t telemetry_batch_path = nxt_string("/settings/telemetry/batch_size"); + static const nxt_str_t telemetry_sample_path = nxt_string("/settings/telemetry/sampling_ratio"); + static const nxt_str_t telemetry_proto_path = nxt_string("/settings/telemetry/protocol"); +#endif root = nxt_conf_json_parse(tmcf->mem_pool, start, end, NULL); if (root == NULL) { @@ -2172,6 +2194,29 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, #endif +#if (NXT_HAVE_OTEL) + otel = nxt_conf_get_path(root, &telemetry_path); + otel_endpoint = nxt_conf_get_path(root, &telemetry_endpoint_path); + otel_batching = nxt_conf_get_path(root, &telemetry_batch_path); + otel_sampling = nxt_conf_get_path(root, &telemetry_sample_path); + otel_proto = nxt_conf_get_path(root, &telemetry_proto_path); + + if (otel) { + nxt_conf_get_string(otel_endpoint, &telemetry_endpoint); + nxt_conf_get_string(otel_proto, &telemetry_proto); + telemetry_batching = otel_batching ? nxt_conf_get_number(otel_batching) : NXT_OTEL_BATCH_DEFAULT; + telemetry_sample_fraction = otel_sampling ? nxt_conf_get_number(otel_sampling) : NXT_OTEL_SAMPLING_DEFAULT; + + nxt_otel_rs_init(&nxt_otel_log_callback, + &telemetry_endpoint, + &telemetry_proto, + telemetry_sample_fraction, + telemetry_batching); + } else { + nxt_otel_rs_uninit(); + } +#endif + nxt_queue_add(&deleting_sockets, &router->sockets); nxt_queue_init(&router->sockets); From efffea4240d38cd4adecd1dda65c019f0e0d861d Mon Sep 17 00:00:00 2001 From: Ava Hahn Date: Thu, 17 Oct 2024 19:12:46 +0100 Subject: [PATCH 5/6] .editorconfig: fix bracket balance of editorconfig file Tiny bracket balance fix. Signed-off-by: Ava Hahn Signed-off-by: Gabor Javorszky --- .editorconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.editorconfig b/.editorconfig index 86ae7df56..00dac6304 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,6 +1,6 @@ root = true -[{configure,{*.{c,cpp,h,go,java,js,py,rs}}] +[{configure,{*.{c,cpp,h,go,java,js,py,rs}}}] charset = utf-8 end_of_line = lf insert_final_newline = true From ee3b440e135a7047cc45ee5dd9d8c344223d785f Mon Sep 17 00:00:00 2001 From: Ava Hahn Date: Thu, 17 Oct 2024 19:13:41 +0100 Subject: [PATCH 6/6] docs/openapi: update OpenAPI references These changes are generated by the openapi generator through a make command. Signed-off-by: Ava Hahn Signed-off-by: Gabor Javorszky --- docs/unit-openapi.yaml | 85 ++++++++++++++++++++++++++++ tools/unitctl/unit-openapi/README.md | 7 +++ 2 files changed, 92 insertions(+) diff --git a/docs/unit-openapi.yaml b/docs/unit-openapi.yaml index efe2f63b9..0d9a2203c 100644 --- a/docs/unit-openapi.yaml +++ b/docs/unit-openapi.yaml @@ -3090,6 +3090,68 @@ paths: "404": $ref: "#/components/responses/responseNotFound" + /config/settings/telemetry: + summary: "Endpoint for the `telemetry` object in `settings`" + get: + operationId: getSettingsTelemetry + summary: "Retrieve the `telemetry` object from settings" + description: "Retrieves the `telemetry` object that represents Unit's + [Telemetry settings](https://unit.nginx.org/configuration/#settings)." + tags: + - settings + - config + responses: + "200": + description: "Ok; the `telemetry` object exists in the configuration." + content: + application/json: + schema: + $ref: "#/components/schemas/configSettingsTelemetry" + "404": + $ref: "#/components/responses/responseNotFound" + + put: + operationId: putSettingsTelemetry + summary: "Create or update the `telemetry` object in settings" + description: "Creates or updates the `telemetry` object that represents Unit's + [Telemetry settings](https://unit.nginx.org/configuration/#settings)." + tags: + - settings + - config + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/configSettingsTelemetry" + responses: + "200": + $ref: "#/components/responses/responseOkUpdated" + + "400": + $ref: "#/components/responses/responseBadRequest" + + "404": + $ref: "#/components/responses/responseNotFound" + + "500": + $ref: "#/components/responses/responseInternalError" + + delete: + operationId: deleteSettingsTelemetry + summary: "Delete the telemetry object" + description: "Deletes the `telemetry` object from the configuration." + tags: + - settings + - config + + responses: + "200": + $ref: "#/components/responses/responseOkDeleted" + + "404": + $ref: "#/components/responses/responseNotFound" + /config/settings/http: summary: "Endpoint for the `http` object in `settings`" @@ -6545,10 +6607,33 @@ components: Unit settings." properties: + telemetry: + description: "Represents global telemetry settings in Unit." + $ref: "#/components/schemas/configSettingsTelemetry" + http: description: "Represents global HTTP settings in Unit." $ref: "#/components/schemas/configSettingsHttp" + # /config/settings/telemetry + configSettingsTelemetry: + type: object + description: "An object whose options represent global telemetry settings in Unit." + required: ["endpoint"] + properties: + batch_size: + type: integer + description: "Number of spans to cache before sending to telemetry collector." + default: 128 + + endpoint: + type: string + description: "A valid endpoint to which Unit can send OpenTelemetry spans." + + protocol: + type: string + description: "Protocol to use when communicating with the aforementioned endpoint." + # /config/settings/http configSettingsHttp: type: object diff --git a/tools/unitctl/unit-openapi/README.md b/tools/unitctl/unit-openapi/README.md index 3a792b6eb..55cbf39d2 100644 --- a/tools/unitctl/unit-openapi/README.md +++ b/tools/unitctl/unit-openapi/README.md @@ -109,6 +109,7 @@ Class | Method | HTTP request | Description *ConfigApi* | [**delete_settings_http_static_mime_types**](docs/ConfigApi.md#delete_settings_http_static_mime_types) | **Delete** /config/settings/http/static/mime_types | Delete the mime_types object *ConfigApi* | [**delete_settings_log_route**](docs/ConfigApi.md#delete_settings_log_route) | **Delete** /config/settings/http/log_route | Delete the log_route option *ConfigApi* | [**delete_settings_server_version**](docs/ConfigApi.md#delete_settings_server_version) | **Delete** /config/settings/http/server_version | Delete the server_version option +*ConfigApi* | [**delete_settings_telemetry**](docs/ConfigApi.md#delete_settings_telemetry) | **Delete** /config/settings/telemetry | Delete the telemetry object *ConfigApi* | [**get_access_log**](docs/ConfigApi.md#get_access_log) | **Get** /config/access_log | Retrieve the access log *ConfigApi* | [**get_access_log_format**](docs/ConfigApi.md#get_access_log_format) | **Get** /config/access_log/format | Retrieve the access log format option *ConfigApi* | [**get_access_log_path**](docs/ConfigApi.md#get_access_log_path) | **Get** /config/access_log/path | Retrieve the access log path option @@ -141,6 +142,7 @@ Class | Method | HTTP request | Description *ConfigApi* | [**get_settings_http_static_mime_types**](docs/ConfigApi.md#get_settings_http_static_mime_types) | **Get** /config/settings/http/static/mime_types | Retrieve the mime_types object from static settings *ConfigApi* | [**get_settings_log_route**](docs/ConfigApi.md#get_settings_log_route) | **Get** /config/settings/http/log_route | Retrieve the log_route option from http settings *ConfigApi* | [**get_settings_server_version**](docs/ConfigApi.md#get_settings_server_version) | **Get** /config/settings/http/server_version | Retrieve the server_version option from http settings +*ConfigApi* | [**get_settings_telemetry**](docs/ConfigApi.md#get_settings_telemetry) | **Get** /config/settings/telemetry | Retrieve the `telemetry` object from settings *ConfigApi* | [**insert_listener_forwarded_source**](docs/ConfigApi.md#insert_listener_forwarded_source) | **Post** /config/listeners/{listenerName}/forwarded/source | Add a new source array item in a listener *ConfigApi* | [**insert_listener_tls_certificate**](docs/ConfigApi.md#insert_listener_tls_certificate) | **Post** /config/listeners/{listenerName}/tls/certificate | Add a new certificate array item in a listener *ConfigApi* | [**insert_listener_tls_session_ticket**](docs/ConfigApi.md#insert_listener_tls_session_ticket) | **Post** /config/listeners/{listenerName}/tls/session/tickets | Add a new tickets array item in a listener @@ -148,6 +150,7 @@ Class | Method | HTTP request | Description *ConfigApi* | [**list_listener_tls_certificates**](docs/ConfigApi.md#list_listener_tls_certificates) | **Get** /config/listeners/{listenerName}/tls/certificate | Retrieve the certificate option in a listener *ConfigApi* | [**list_listener_tls_conf_commands**](docs/ConfigApi.md#list_listener_tls_conf_commands) | **Get** /config/listeners/{listenerName}/tls/conf_commands | Retrieve the conf_commands object in a listener *ConfigApi* | [**list_listener_tls_session_tickets**](docs/ConfigApi.md#list_listener_tls_session_tickets) | **Get** /config/listeners/{listenerName}/tls/session/tickets | Retrieve the tickets option in a listener +*ConfigApi* | [**put_settings_telemetry**](docs/ConfigApi.md#put_settings_telemetry) | **Put** /config/settings/telemetry | Create or update the `telemetry` object in settings *ConfigApi* | [**update_access_log**](docs/ConfigApi.md#update_access_log) | **Put** /config/access_log | Create or overwrite the access log *ConfigApi* | [**update_access_log_format**](docs/ConfigApi.md#update_access_log_format) | **Put** /config/access_log/format | Create or overwrite the access log format *ConfigApi* | [**update_access_log_path**](docs/ConfigApi.md#update_access_log_path) | **Put** /config/access_log/path | Create or overwrite the access log path @@ -249,6 +252,7 @@ Class | Method | HTTP request | Description *SettingsApi* | [**delete_settings_http_static_mime_types**](docs/SettingsApi.md#delete_settings_http_static_mime_types) | **Delete** /config/settings/http/static/mime_types | Delete the mime_types object *SettingsApi* | [**delete_settings_log_route**](docs/SettingsApi.md#delete_settings_log_route) | **Delete** /config/settings/http/log_route | Delete the log_route option *SettingsApi* | [**delete_settings_server_version**](docs/SettingsApi.md#delete_settings_server_version) | **Delete** /config/settings/http/server_version | Delete the server_version option +*SettingsApi* | [**delete_settings_telemetry**](docs/SettingsApi.md#delete_settings_telemetry) | **Delete** /config/settings/telemetry | Delete the telemetry object *SettingsApi* | [**get_settings**](docs/SettingsApi.md#get_settings) | **Get** /config/settings | Retrieve the settings object *SettingsApi* | [**get_settings_discard_unsafe_fields**](docs/SettingsApi.md#get_settings_discard_unsafe_fields) | **Get** /config/settings/http/discard_unsafe_fields | Retrieve the discard_unsafe_fields option from http settings *SettingsApi* | [**get_settings_http**](docs/SettingsApi.md#get_settings_http) | **Get** /config/settings/http | Retrieve the http object from settings @@ -262,6 +266,8 @@ Class | Method | HTTP request | Description *SettingsApi* | [**get_settings_http_static_mime_types**](docs/SettingsApi.md#get_settings_http_static_mime_types) | **Get** /config/settings/http/static/mime_types | Retrieve the mime_types object from static settings *SettingsApi* | [**get_settings_log_route**](docs/SettingsApi.md#get_settings_log_route) | **Get** /config/settings/http/log_route | Retrieve the log_route option from http settings *SettingsApi* | [**get_settings_server_version**](docs/SettingsApi.md#get_settings_server_version) | **Get** /config/settings/http/server_version | Retrieve the server_version option from http settings +*SettingsApi* | [**get_settings_telemetry**](docs/SettingsApi.md#get_settings_telemetry) | **Get** /config/settings/telemetry | Retrieve the `telemetry` object from settings +*SettingsApi* | [**put_settings_telemetry**](docs/SettingsApi.md#put_settings_telemetry) | **Put** /config/settings/telemetry | Create or update the `telemetry` object in settings *SettingsApi* | [**update_settings**](docs/SettingsApi.md#update_settings) | **Put** /config/settings | Create or overwrite the settings object *SettingsApi* | [**update_settings_discard_unsafe_fields**](docs/SettingsApi.md#update_settings_discard_unsafe_fields) | **Put** /config/settings/http/discard_unsafe_fields | Create or overwrite the discard_unsafe_fields option *SettingsApi* | [**update_settings_http**](docs/SettingsApi.md#update_settings_http) | **Put** /config/settings/http | Create or overwrite the http object @@ -389,6 +395,7 @@ Class | Method | HTTP request | Description - [ConfigSettingsHttp](docs/ConfigSettingsHttp.md) - [ConfigSettingsHttpStatic](docs/ConfigSettingsHttpStatic.md) - [ConfigSettingsHttpStaticMimeType](docs/ConfigSettingsHttpStaticMimeType.md) + - [ConfigSettingsTelemetry](docs/ConfigSettingsTelemetry.md) - [Status](docs/Status.md) - [StatusApplicationsApp](docs/StatusApplicationsApp.md) - [StatusApplicationsAppProcesses](docs/StatusApplicationsAppProcesses.md)