From 430e202360631ab6b7faa46b22b4a94c2fcb0822 Mon Sep 17 00:00:00 2001 From: outductor Date: Sun, 2 Aug 2026 09:16:14 +0900 Subject: [PATCH 1/2] =?UTF-8?q?fix:=20Docker=E3=82=A4=E3=83=A1=E3=83=BC?= =?UTF-8?q?=E3=82=B8=E3=83=93=E3=83=AB=E3=83=89=E3=81=AE=E5=A4=B1=E6=95=97?= =?UTF-8?q?=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - cargo-chefイメージをrust 1.87から1.97.1に更新 (rust-toolchain.tomlと同期)。 sentry 0.48.5やtime 0.3.47がrustc 1.88以上を要求するため、2026-04-10以降 Build and releaseワークフローが失敗し続けていた - 実行ステージのubuntu:24.04 (glibc 2.39) でバイナリが動くよう、 デフォルトのtrixie (glibc 2.41) ではなくbookworm variantを明示指定 - mariadb_repo_setupのsha256をMariaDB公式の現行版 (2026-06-30) に更新 Co-Authored-By: Claude Fable 5 --- Dockerfile | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index abd6d56..8949009 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,8 @@ # syntax=docker/dockerfile:1.25 -FROM lukemathwalker/cargo-chef:latest-rust-1.87 AS chef +# NOTE: Rustのバージョンはrust-toolchain.tomlと合わせること (Renovateはこのタグ形式を追跡できない)。 +# また、実行ステージ (ubuntu:24.04, glibc 2.39) で動くバイナリにするため、 +# glibcがより古いbookworm variantを使う (デフォルトのtrixieはglibc 2.41) +FROM lukemathwalker/cargo-chef:latest-rust-1.97.1-bookworm AS chef WORKDIR /app FROM chef AS planner @@ -21,7 +24,7 @@ LABEL org.opencontainers.image.source=https://github.com/GiganticMinecraft/gacha RUN apt-get update -y && apt-get install -y curl RUN curl -LsSO https://downloads.mariadb.com/MariaDB/mariadb_repo_setup -RUN echo "73f4ab14ccc3ceb8c03bb283dd131a3235cfc28086475f43e9291d2060d48c97 mariadb_repo_setup" \ +RUN echo "7325ac7755809ca3312b446bd832542421699298f25b701f9a111bb42df0c7c1 mariadb_repo_setup" \ | sha256sum -c - RUN chmod +x mariadb_repo_setup RUN ./mariadb_repo_setup \ From 8d37e5b87e3ec895a8725e7fa75d7daced7ce5d3 Mon Sep 17 00:00:00 2001 From: outductor Date: Sun, 2 Aug 2026 09:19:48 +0900 Subject: [PATCH 2/2] =?UTF-8?q?feat:=20Sentry=20=E3=82=92=E6=92=A4?= =?UTF-8?q?=E5=8E=BB=E3=81=97=20OpenTelemetry=20+=20Pyroscope=20=E3=81=B8?= =?UTF-8?q?=E7=A7=BB=E8=A1=8C=E3=81=99=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 旧 Sentry (sentry.onp.admin.seichi.click) は配信面が撤去済みで (GiganticMinecraft/seichi_infra#5613)、ハードコードされた DSN への 送信は既に到達不能だった。seichi-portal-backend と同じ観測スタックへ移行する: - OTel トレーシング: OTLP http/protobuf、OTEL_* 環境変数で設定。 OTEL_EXPORTER_OTLP_ENDPOINT 未設定 / OTEL_SDK_DISABLED=true なら無効 - HTTP サーバースパン: axum-tracing-opentelemetry (Sentry の tower layer を置換) - stdout ログ: 本番は 1 行 JSON + OTel trace_id 注入 (json-subscriber)。 panic hook が panic=true / level=ERROR を付ける (seichi_infra の LogQL ルールとの契約。portal-backend の panic_hook.rs と同一) - handler 内 panic は CatchPanicLayer で 500 を返しつつ hook がログに残す - 継続プロファイリング: Pyroscope への push (pyroscope crate、 PYROSCOPE_SERVER_ADDRESS 未設定なら無効) telemetry / logging / panic_hook は seichi-portal-backend の実装 (レビュー済み) の移植。 Co-Authored-By: Claude Fable 5 --- server/Cargo.lock | 980 ++++++++++++++++++++++++--------------- server/Cargo.toml | 15 +- server/src/logging.rs | 143 ++++++ server/src/main.rs | 105 ++++- server/src/panic_hook.rs | 99 ++++ server/src/telemetry.rs | 97 ++++ 6 files changed, 1043 insertions(+), 396 deletions(-) create mode 100644 server/src/logging.rs create mode 100644 server/src/panic_hook.rs create mode 100644 server/src/telemetry.rs diff --git a/server/Cargo.lock b/server/Cargo.lock index 87076d8..051189f 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -8,7 +8,7 @@ version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ - "gimli", + "gimli 0.31.1", ] [[package]] @@ -17,6 +17,12 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" +[[package]] +name = "adler32" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" + [[package]] name = "aho-corasick" version = "1.1.3" @@ -26,12 +32,33 @@ dependencies = [ "memchr", ] +[[package]] +name = "aligned-vec" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc890384c8602f339876ded803c97ad529f3842aba97f6392b3dba0dd171769b" +dependencies = [ + "equator", +] + +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + [[package]] name = "anyhow" version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "330a5ed07fa54e4702c9d6c4174f74427fc0ef6e214bbd677ae50a5099946470" +[[package]] +name = "arrayvec" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3fb67a6e08acf24fdeccbac2cb6ac4305825bd1f117462e0e6f2f193345ad56" + [[package]] name = "async-trait" version = "0.1.91" @@ -129,6 +156,25 @@ dependencies = [ "tracing", ] +[[package]] +name = "axum-tracing-opentelemetry" +version = "0.38.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c938150bbecf4b43a24964bea0780f99d538b6654455e45b1784d410f122822" +dependencies = [ + "axum", + "futures-core", + "futures-util", + "http", + "opentelemetry", + "opentelemetry-semantic-conventions", + "pin-project-lite", + "tower", + "tracing", + "tracing-opentelemetry", + "tracing-opentelemetry-instrumentation-sdk", +] + [[package]] name = "backtrace" version = "0.3.74" @@ -139,7 +185,7 @@ dependencies = [ "cfg-if", "libc", "miniz_oxide", - "object", + "object 0.36.7", "rustc-demangle", "windows-targets 0.52.6", ] @@ -240,22 +286,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] -name = "debugid" -version = "0.8.0" +name = "crc32fast" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef552e6f588e446098f6ba40d89ac146c8c7b64aade83c051ee00bb5d2bc18d" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" dependencies = [ - "serde", - "uuid", + "cfg-if", ] [[package]] -name = "deranged" -version = "0.5.8" +name = "dary_heap" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b1e3a325bc115f096c8b77bbf027a7c2592230e70be2d985be950d3d5e60ebe" + +[[package]] +name = "debugid" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" +checksum = "bef552e6f588e446098f6ba40d89ac146c8c7b64aade83c051ee00bb5d2bc18d" dependencies = [ - "powerfmt", + "uuid", ] [[package]] @@ -275,6 +326,12 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" +[[package]] +name = "either" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5e8f6c15a24b9a3ee5efec809ccd006d3b30e8b3bb63c39af737c7f87daa1d" + [[package]] name = "envy" version = "0.4.2" @@ -284,12 +341,54 @@ dependencies = [ "serde", ] +[[package]] +name = "equator" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4711b213838dfee0117e3be6ac926007d7f433d7bbe33595975d4190cb07e6fc" +dependencies = [ + "equator-macro", +] + +[[package]] +name = "equator-macro" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.98", +] + [[package]] name = "equivalent" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "fallible-iterator" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" + +[[package]] +name = "fastrand" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223" + [[package]] name = "find-msvc-tools" version = "0.1.9" @@ -308,12 +407,28 @@ dependencies = [ "winapi", ] +[[package]] +name = "flate2" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + [[package]] name = "fnv" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + [[package]] name = "form_urlencoded" version = "1.2.1" @@ -323,6 +438,20 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "framehop" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f54fe4785e899d4d6f43793b151c63c5647240fc630b005509d2614a939f693" +dependencies = [ + "arrayvec", + "cfg-if", + "fallible-iterator", + "gimli 0.33.0", + "macho-unwind-info", + "pe-unwind-info", +] + [[package]] name = "fs_extra" version = "1.3.0" @@ -345,12 +474,34 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" +[[package]] +name = "futures-executor" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + [[package]] name = "futures-io" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.98", +] + [[package]] name = "futures-sink" version = "0.3.31" @@ -371,6 +522,7 @@ checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-core", "futures-io", + "futures-macro", "futures-sink", "futures-task", "memchr", @@ -386,13 +538,21 @@ dependencies = [ "anyhow", "async-trait", "axum", + "axum-tracing-opentelemetry", "bytes", "envy", - "sentry", + "json-subscriber", + "opentelemetry", + "opentelemetry-otlp", + "opentelemetry_sdk", + "pyroscope", "serde", + "serde_json", "tokio", "tower", + "tower-http 0.7.0", "tracing", + "tracing-opentelemetry", "tracing-subscriber", ] @@ -417,10 +577,21 @@ checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", "libc", - "r-efi", + "r-efi 5.3.0", "wasip2", ] +[[package]] +name = "getrandom" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" +dependencies = [ + "cfg-if", + "libc", + "r-efi 6.0.0", +] + [[package]] name = "gimli" version = "0.31.1" @@ -428,22 +599,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] -name = "h2" -version = "0.4.13" +name = "gimli" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f44da3a8150a6703ed5d34e164b875fd14c2cdab9af1252a9a1020bde2bdc54" +checksum = "0bf7f043f89559805f8c7cacc432749b2fa0d0a0a9ee46ce47164ed5ba7f126c" dependencies = [ - "atomic-waker", - "bytes", - "fnv", - "futures-core", - "futures-sink", - "http", - "indexmap", - "slab", - "tokio", - "tokio-util", - "tracing", + "stable_deref_trait", ] [[package]] @@ -451,22 +612,10 @@ name = "hashbrown" version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "hostname" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9c7c7c8ac16c798734b8a24560c1362120597c40d5e1459f09498f8f6c8f2ba" dependencies = [ - "cfg-if", - "libc", - "windows", + "allocator-api2", + "equivalent", + "foldhash", ] [[package]] @@ -525,7 +674,6 @@ dependencies = [ "bytes", "futures-channel", "futures-core", - "h2", "http", "http-body", "httparse", @@ -718,16 +866,6 @@ dependencies = [ "icu_properties", ] -[[package]] -name = "indexmap" -version = "2.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45a8a2b9cb3e0b0c1803dbb0758ffac5de2f425b23c28f518faabd9d805342ff" -dependencies = [ - "equivalent", - "hashbrown", -] - [[package]] name = "ipnet" version = "2.10.1" @@ -744,6 +882,15 @@ dependencies = [ "serde", ] +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.14" @@ -814,6 +961,23 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "json-subscriber" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1a3442048fd2d18bf39b182881bea8de640062f86cbacf6d949478af61651d6" +dependencies = [ + "opentelemetry", + "serde", + "serde_json", + "tracing", + "tracing-core", + "tracing-opentelemetry", + "tracing-serde", + "tracing-subscriber", + "uuid", +] + [[package]] name = "lazy_static" version = "1.5.0" @@ -822,9 +986,39 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.184" +version = "0.2.189" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" + +[[package]] +name = "libflate" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48f5d2a454e16a5ea0f4ced81bd44e4cfc7bd3a507b61887c99fd3538b28e4af" +checksum = "a4da9b700e758e57152a1fd1c52cbdc5727c1aa6d8743dc1acda917398f1d76c" +dependencies = [ + "adler32", + "crc32fast", + "dary_heap", + "libflate_lz77", + "no_std_io2", +] + +[[package]] +name = "libflate_lz77" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff7a10e427698aef6eef269482776debfef63384d30f13aad39a1a95e0e098fd" +dependencies = [ + "hashbrown", + "no_std_io2", + "rle-decode-fast", +] + +[[package]] +name = "linux-raw-sys" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" [[package]] name = "litemap" @@ -848,6 +1042,17 @@ version = "0.4.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" +[[package]] +name = "macho-unwind-info" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb4bdc8b0ce69932332cf76d24af69c3a155242af95c226b2ab6c2e371ed1149" +dependencies = [ + "thiserror 2.0.17", + "zerocopy 0.8.27", + "zerocopy-derive 0.8.27", +] + [[package]] name = "matchers" version = "0.2.0" @@ -869,6 +1074,15 @@ version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +[[package]] +name = "memmap2" +version = "0.9.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1219ed1b7f229ee7104d281dd01d6802fe28bb6e95d292942c4daacdeb798c0" +dependencies = [ + "libc", +] + [[package]] name = "mime" version = "0.3.17" @@ -877,11 +1091,12 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "miniz_oxide" -version = "0.8.3" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8402cab7aefae129c6977bb0ff1b8fd9a04eb5b51efc50a70bea51cda0c7924" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ "adler2", + "simd-adler32", ] [[package]] @@ -895,6 +1110,27 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "nix" +version = "0.31.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf20d2fde8ff38632c426f1165ed7436270b44f199fc55284c38276f9db47c3d" +dependencies = [ + "bitflags", + "cfg-if", + "cfg_aliases", + "libc", +] + +[[package]] +name = "no_std_io2" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418abd1b6d34fbf6cae440dc874771b0525a604428704c76e48b29a5e67b8003" +dependencies = [ + "memchr", +] + [[package]] name = "nu-ansi-term" version = "0.50.1" @@ -905,18 +1141,23 @@ dependencies = [ ] [[package]] -name = "num-conv" -version = "0.2.1" +name = "object" +version = "0.36.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6673768db2d862beb9b39a78fdcb1a69439615d5794a1be50caa9bc92c81967" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" +dependencies = [ + "memchr", +] [[package]] name = "object" -version = "0.36.7" +version = "0.39.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" +checksum = "2e5a6c098c7a3b6547378093f5cc30bc54fd361ce711e05293a5cc589562739b" dependencies = [ + "flate2", "memchr", + "ruzstd", ] [[package]] @@ -932,14 +1173,79 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" [[package]] -name = "os_info" -version = "3.9.0" +name = "opentelemetry" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ca711d8b83edbb00b44d504503cd247c9c0bd8b0fa2694f2a1a3d8165379ce" +checksum = "b0142c63252a9e054e68a4c61a5778f7b14f576274d593f8ce883d191a099682" dependencies = [ - "log", - "serde", - "windows-sys 0.52.0", + "futures-core", + "futures-sink", + "js-sys", + "pin-project-lite", + "thiserror 2.0.17", + "tracing", +] + +[[package]] +name = "opentelemetry-http" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5683015d09e2df236ef005b17f6f196f0d5f6313c4fa43a7b6a53b52776e4331" +dependencies = [ + "async-trait", + "bytes", + "http", + "opentelemetry", + "reqwest", +] + +[[package]] +name = "opentelemetry-otlp" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9966929966d17620d7c316c643ba62631826e10021409357772d5eea84f62c35" +dependencies = [ + "http", + "opentelemetry", + "opentelemetry-http", + "opentelemetry-proto", + "opentelemetry_sdk", + "prost", + "reqwest", + "thiserror 2.0.17", +] + +[[package]] +name = "opentelemetry-proto" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56d658ba1faf63f7b9c492cfbe6e0ec365440a16132d3270c1065f7b33f1b638" +dependencies = [ + "opentelemetry", + "opentelemetry_sdk", + "prost", +] + +[[package]] +name = "opentelemetry-semantic-conventions" +version = "0.32.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c913ac17a6c451661ee255f4625d143e51647ae78ebd969b75e41c4442f4fe47" + +[[package]] +name = "opentelemetry_sdk" +version = "0.32.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b59f80e1ac4d5ff7a2db8fb6c80badb7f0f3f858211fba08dd9aaec750894f9" +dependencies = [ + "futures-channel", + "futures-executor", + "futures-util", + "opentelemetry", + "percent-encoding", + "portable-atomic", + "rand 0.9.4", + "thiserror 2.0.17", ] [[package]] @@ -966,30 +1272,23 @@ dependencies = [ ] [[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.7" +name = "pe-unwind-info" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be57f64e946e500c8ee36ef6331845d40a93055567ec57e8fae13efd33759b95" +checksum = "97f6fccfd2d9d2df765ca23ff85fe5cc437fb0e6d3e164e4d3cbe09d14780c93" dependencies = [ - "pin-project-internal", + "arrayvec", + "bitflags", + "thiserror 2.0.17", + "zerocopy 0.8.27", + "zerocopy-derive 0.8.27", ] [[package]] -name = "pin-project-internal" -version = "1.1.7" +name = "percent-encoding" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.98", -] +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pin-project-lite" @@ -1004,10 +1303,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] -name = "powerfmt" -version = "0.2.0" +name = "portable-atomic" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" +checksum = "3d20d5497ef88037a52ff98267d066e7f11fcc5e99bbfbd58a42336193aacec3" [[package]] name = "ppv-lite86" @@ -1015,7 +1314,7 @@ version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" dependencies = [ - "zerocopy", + "zerocopy 0.7.35", ] [[package]] @@ -1027,6 +1326,58 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "prost" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "528ac67416ff8646872a3c02cad9cc4ee5dc9f9540c9b10771855c95cb2e5ae1" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-derive" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b570b25f7617e43d59005d0990ccb79e950a423952cea19671b7a876da390adf" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn 2.0.98", +] + +[[package]] +name = "pyroscope" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59b1989a61e856eba4ef903eadad8313f8376e88e7c9cc5d5db8217d832a64d9" +dependencies = [ + "aligned-vec", + "backtrace", + "findshlibs", + "framehop", + "libc", + "libflate", + "log", + "memmap2", + "nix", + "object 0.39.1", + "once_cell", + "prost", + "reqwest", + "serde_json", + "smallvec", + "spin 0.12.2", + "symbolic-demangle", + "tempfile", + "thiserror 2.0.17", + "url", + "uuid", +] + [[package]] name = "quinn" version = "0.11.6" @@ -1095,6 +1446,12 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + [[package]] name = "rand" version = "0.8.5" @@ -1163,18 +1520,6 @@ dependencies = [ "bitflags", ] -[[package]] -name = "regex" -version = "1.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - [[package]] name = "regex-automata" version = "0.4.9" @@ -1203,7 +1548,6 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "h2", "http", "http-body", "http-body-util", @@ -1219,12 +1563,12 @@ dependencies = [ "rustls-pki-types", "rustls-platform-verifier", "serde", - "serde_json", + "serde_urlencoded", "sync_wrapper", "tokio", "tokio-rustls", "tower", - "tower-http", + "tower-http 0.6.8", "tower-service", "url", "wasm-bindgen", @@ -1242,11 +1586,17 @@ dependencies = [ "cfg-if", "getrandom 0.2.15", "libc", - "spin", + "spin 0.9.8", "untrusted", "windows-sys 0.52.0", ] +[[package]] +name = "rle-decode-fast" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3582f63211428f83597b51b2ddb88e2a91a9d52d12831f9d08f5e624e8977422" + [[package]] name = "rustc-demangle" version = "0.1.24" @@ -1260,12 +1610,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7fb8039b3032c191086b10f11f319a6e99e1e82889c5cc6046f515c9db1d497" [[package]] -name = "rustc_version" -version = "0.4.1" +name = "rustix" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ - "semver", + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.61.2", ] [[package]] @@ -1275,9 +1629,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "533f54bc6a7d4f647e46ad909549eda97bf5afc1585190ef692b4286b198bd8f" dependencies = [ "aws-lc-rs", - "log", "once_cell", - "ring", "rustls-pki-types", "rustls-webpki", "subtle", @@ -1351,6 +1703,15 @@ version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" +[[package]] +name = "ruzstd" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7c1c839d570d835527c9a5e4db7cb2198683a988cb9d7293fc8674e6bd58fc8" +dependencies = [ + "twox-hash", +] + [[package]] name = "ryu" version = "1.0.18" @@ -1404,147 +1765,6 @@ dependencies = [ "libc", ] -[[package]] -name = "semver" -version = "1.0.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" - -[[package]] -name = "sentry" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d631477761f57c76148456e55e80e9a479ff3fa4c65b2b4a0c3acf1167fd4638" -dependencies = [ - "cfg_aliases", - "httpdate", - "reqwest", - "rustls", - "sentry-anyhow", - "sentry-backtrace", - "sentry-contexts", - "sentry-core", - "sentry-debug-images", - "sentry-panic", - "sentry-tower", - "sentry-tracing", - "tokio", - "ureq", -] - -[[package]] -name = "sentry-anyhow" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8f73466a403f4da78c7e576049d6044b31d2b16dfcc26b51705f318ed74b804" -dependencies = [ - "anyhow", - "sentry-backtrace", - "sentry-core", -] - -[[package]] -name = "sentry-backtrace" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "448b0981fbde6cdc9eb087ba3dc01035a253fef9a0d9e79aaf198fc26acb2e64" -dependencies = [ - "backtrace", - "regex", - "sentry-core", -] - -[[package]] -name = "sentry-contexts" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e5e909d02170ba6d1dc5ebd05bef7999280f5d960e3eaee5d1a18d88d41b334" -dependencies = [ - "hostname", - "libc", - "os_info", - "rustc_version", - "sentry-core", - "uname", -] - -[[package]] -name = "sentry-core" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecf0b1a4a4e9ec88395b52e6fa4868b95564c1fa96b26a0606f5f6288a0f7149" -dependencies = [ - "rand 0.9.4", - "sentry-types", - "serde", - "serde_json", - "url", -] - -[[package]] -name = "sentry-debug-images" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f81d7749c57fc78ed52134889e8121da874065bc40da788d5798cce0f8c19f15" -dependencies = [ - "findshlibs", - "sentry-core", -] - -[[package]] -name = "sentry-panic" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7d93d6ecb55d2251c5fc084c55c03a2bc68904918d76117e602c999e92f00f" -dependencies = [ - "sentry-backtrace", - "sentry-core", -] - -[[package]] -name = "sentry-tower" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a64a8a0a33239c65f95ff719fcb56655f398f4e4e74a01af8daca725cf7c2b5f" -dependencies = [ - "http", - "pin-project", - "sentry-core", - "tower-layer", - "tower-service", - "url", -] - -[[package]] -name = "sentry-tracing" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58d26379236c4ef97eaf081bca3c7bf0ef6f06b3aa881eca2ee8e8dbc923e5b8" -dependencies = [ - "bitflags", - "sentry-backtrace", - "sentry-core", - "tracing-core", - "tracing-subscriber", -] - -[[package]] -name = "sentry-types" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2239099d47e76857b0825a182ecdb90159add7aa1097b60247c6e7ca6bf49c6a" -dependencies = [ - "debugid", - "hex", - "rand 0.9.4", - "serde", - "serde_json", - "thiserror 2.0.17", - "time", - "url", - "uuid", -] - [[package]] name = "serde" version = "1.0.229" @@ -1633,6 +1853,12 @@ dependencies = [ "libc", ] +[[package]] +name = "simd-adler32" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a219298ac11a56ea9a6d2120044824d6f01aeb034955e7af7bc16858527deea" + [[package]] name = "slab" version = "0.4.9" @@ -1674,6 +1900,15 @@ version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +[[package]] +name = "spin" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8abadc99fd9c7bbb7d0ca2b31d72a067d0c0dcd7aad25ab8cac71ba91417694b" +dependencies = [ + "lock_api", +] + [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -1686,6 +1921,28 @@ version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" +[[package]] +name = "symbolic-common" +version = "13.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddfa0014ff4e423a1bb8881453c7a29181eb14fe1dbc8e0197ebfa081903f3ed" +dependencies = [ + "debugid", + "memmap2", + "stable_deref_trait", + "uuid", +] + +[[package]] +name = "symbolic-demangle" +version = "13.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a213276280a1a737ff5fb89ae2a70ba51d1d4608e74736beb92f257f125f1aa" +dependencies = [ + "rustc-demangle", + "symbolic-common", +] + [[package]] name = "syn" version = "2.0.98" @@ -1728,6 +1985,19 @@ dependencies = [ "syn 2.0.98", ] +[[package]] +name = "tempfile" +version = "3.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" +dependencies = [ + "fastrand", + "getrandom 0.3.4", + "once_cell", + "rustix", + "windows-sys 0.61.2", +] + [[package]] name = "thiserror" version = "1.0.69" @@ -1778,37 +2048,6 @@ dependencies = [ "once_cell", ] -[[package]] -name = "time" -version = "0.3.47" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" -dependencies = [ - "deranged", - "itoa", - "num-conv", - "powerfmt", - "serde_core", - "time-core", - "time-macros", -] - -[[package]] -name = "time-core" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" - -[[package]] -name = "time-macros" -version = "0.2.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" -dependencies = [ - "num-conv", - "time-core", -] - [[package]] name = "tinystr" version = "0.7.6" @@ -1873,19 +2112,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "tokio-util" -version = "0.7.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" -dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "pin-project-lite", - "tokio", -] - [[package]] name = "tower" version = "0.5.3" @@ -1920,6 +2146,25 @@ dependencies = [ "tower-service", ] +[[package]] +name = "tower-http" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b11f75e912b0c2be01b63d8cf8057b8c3f97cf34abb3d431a3a4c8675498e233" +dependencies = [ + "bitflags", + "bytes", + "futures-util", + "http", + "http-body", + "http-body-util", + "percent-encoding", + "pin-project-lite", + "tower-layer", + "tower-service", + "tracing", +] + [[package]] name = "tower-layer" version = "0.3.3" @@ -1976,6 +2221,45 @@ dependencies = [ "tracing-core", ] +[[package]] +name = "tracing-opentelemetry" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adbc64cba7137545b8044cb1fe9814f7aacf3c6b5f9b45be8bb5db538befdb26" +dependencies = [ + "js-sys", + "opentelemetry", + "smallvec", + "tracing", + "tracing-core", + "tracing-log", + "tracing-subscriber", + "web-time", +] + +[[package]] +name = "tracing-opentelemetry-instrumentation-sdk" +version = "0.38.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a10464b0f9cac62a3e26c08c7c9b93c5ae62f5165792b2e7e90c52940eaabef5" +dependencies = [ + "http", + "opentelemetry", + "opentelemetry-semantic-conventions", + "tracing", + "tracing-opentelemetry", +] + +[[package]] +name = "tracing-serde" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "704b1aeb7be0d0a84fc9828cae51dab5970fee5088f83d1dd7ee6f6246fc6ff1" +dependencies = [ + "serde", + "tracing-core", +] + [[package]] name = "tracing-subscriber" version = "0.3.23" @@ -2001,13 +2285,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] -name = "uname" -version = "0.1.1" +name = "twox-hash" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b72f89f0ca32e4db1c04e2a72f5345d59796d4866a1ee0609084569f73683dc8" -dependencies = [ - "libc", -] +checksum = "8464ec13c3691491391d9fce00f6416c9a48e46972f72d7865688be2080192c9" [[package]] name = "unicode-ident" @@ -2021,34 +2302,6 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" -[[package]] -name = "ureq" -version = "3.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d39cb1dbab692d82a977c0392ffac19e188bd9186a9f32806f0aaa859d75585a" -dependencies = [ - "base64", - "log", - "percent-encoding", - "rustls", - "rustls-pki-types", - "ureq-proto", - "utf-8", - "webpki-roots", -] - -[[package]] -name = "ureq-proto" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d81f9efa9df032be5934a46a068815a10a042b494b6a58cb0a1a97bb5467ed6f" -dependencies = [ - "base64", - "http", - "httparse", - "log", -] - [[package]] name = "url" version = "2.5.4" @@ -2058,15 +2311,8 @@ dependencies = [ "form_urlencoded", "idna", "percent-encoding", - "serde", ] -[[package]] -name = "utf-8" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" - [[package]] name = "utf16_iter" version = "1.0.5" @@ -2081,11 +2327,13 @@ checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" [[package]] name = "uuid" -version = "1.11.0" +version = "1.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" +checksum = "bf3923a6f5c4c6382e0b653c4117f48d631ea17f38ed86e2a828e6f7412f5239" dependencies = [ - "serde", + "getrandom 0.4.3", + "js-sys", + "wasm-bindgen", ] [[package]] @@ -2216,15 +2464,6 @@ dependencies = [ "rustls-pki-types", ] -[[package]] -name = "webpki-roots" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2878ef029c47c6e8cf779119f20fcf52bde7ad42a731b2a304bc221df17571e" -dependencies = [ - "rustls-pki-types", -] - [[package]] name = "winapi" version = "0.3.9" @@ -2256,25 +2495,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "windows" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" -dependencies = [ - "windows-core", - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-core" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" -dependencies = [ - "windows-targets 0.52.6", -] - [[package]] name = "windows-link" version = "0.2.1" @@ -2487,7 +2707,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ "byteorder", - "zerocopy-derive", + "zerocopy-derive 0.7.35", +] + +[[package]] +name = "zerocopy" +version = "0.8.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c" +dependencies = [ + "zerocopy-derive 0.8.27", ] [[package]] @@ -2501,6 +2730,17 @@ dependencies = [ "syn 2.0.98", ] +[[package]] +name = "zerocopy-derive" +version = "0.8.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.98", +] + [[package]] name = "zerofrom" version = "0.1.5" diff --git a/server/Cargo.toml b/server/Cargo.toml index ef4f739..8d2ec84 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -9,12 +9,23 @@ edition = "2024" anyhow = "=1.0.104" async-trait = "=0.1.91" axum = "=0.8.9" +axum-tracing-opentelemetry = "=0.38.0" bytes = "=1.12.1" envy = "=0.4.2" -# default featureは推移的にnative-tls featureを有効しているため、native-tls (LinuxではOpenSSL) を連れてくる。これをオプトアウトするためにrustlsを使う。 -sentry = { version = "=0.48.5", default-features = false, features = ["backtrace", "contexts", "panic", "anyhow", "reqwest", "tracing", "debug-images", "rustls", "tower", "tower-http"] } +# JSON ログに OTel trace_id を注入する (tracing-subscriber 標準の JSON では出せない) +json-subscriber = { version = "=0.3.0", features = ["tracing-opentelemetry-0-33"] } +opentelemetry = "=0.32.0" +opentelemetry-otlp = { version = "=0.32.0", default-features = false, features = ["http-proto", "trace", "reqwest-blocking-client"] } +opentelemetry_sdk = "=0.32.1" +# 継続プロファイリング (Grafana Pyroscope への push)。default の rustls-tls を使う +pyroscope = { version = "=2.1.1", features = ["backend-pprof-rs"] } serde = { version = "=1.0.229", features = ["derive"] } tokio = { version = "=1.53.1", features = ["full"] } tower = "=0.5.3" +tower-http = { version = "=0.7.0", features = ["catch-panic"] } tracing = "=0.1.44" +tracing-opentelemetry = "=0.33.0" tracing-subscriber = { version = "=0.3.23", features = ["std", "registry", "env-filter"] } + +[dev-dependencies] +serde_json = "=1.0.133" diff --git a/server/src/logging.rs b/server/src/logging.rs new file mode 100644 index 0000000..ee98a4d --- /dev/null +++ b/server/src/logging.rs @@ -0,0 +1,143 @@ +use tracing::Subscriber; +use tracing_subscriber::registry::LookupSpan; + +/// stdout ログを JSON にするかどうかを判定します。 +/// +/// `LOG_FORMAT` 環境変数 (`json` / `pretty`) が設定されていればそれに従い、 +/// 未設定なら `ENV_NAME=local` (ローカル開発) のときだけ人間向けフォーマットにします。 +/// `ENV_NAME` も未設定の場合は本番想定で JSON にします。 +pub fn json_logs_enabled(env_name: Option<&str>, log_format: Option<&str>) -> bool { + match log_format { + Some(format) => format.eq_ignore_ascii_case("json"), + None => env_name != Some("local"), + } +} + +/// stdout ログを 1 行 JSON で出力するレイヤーを作ります。 +/// +/// `tracing-subscriber` 標準の JSON フォーマッタは OTel の trace_id を出力できないため、 +/// [`json_subscriber`] を使う。 +/// +/// - OTel の span コンテキストが有効な場合、`openTelemetry.traceId` / `openTelemetry.spanId` +/// フィールドが付く (Tempo の tracesToLogsV2 でトレース→ログ相関に使う。 +/// このフィールド名は seichi_infra 側の Grafana/Loki 設定との契約であり、 +/// 変更する場合は両方直すこと) +/// - イベントのフィールドはトップレベルへフラットに出力される +/// (`panic=true` のような LogQL の `| json` パースを前提としたフィールドの契約を保つ) +/// - span のフィールドはスパン属性として Tempo 側へ送られるため、ログ行には出力しない +/// +/// (seichi-portal-backend の logging.rs と同じ構成) +pub fn json_log_layer() -> json_subscriber::fmt::Layer +where + S: Subscriber + for<'a> LookupSpan<'a>, +{ + json_subscriber::layer() + .flatten_event(true) + .with_current_span(false) + .with_span_list(false) + .with_opentelemetry_ids(true) +} + +#[cfg(test)] +mod tests { + use std::{ + io, + sync::{Arc, Mutex}, + }; + + use opentelemetry::trace::TracerProvider as _; + use tracing::info; + use tracing_subscriber::{fmt::MakeWriter, layer::SubscriberExt}; + + use super::{json_log_layer, json_logs_enabled}; + + #[test] + fn json_logs_are_enabled_outside_local_unless_overridden() { + assert!(json_logs_enabled(Some("production"), None)); + assert!(!json_logs_enabled(Some("local"), None)); + assert!(json_logs_enabled(None, None), "ENV_NAME 未設定は本番扱い"); + assert!(json_logs_enabled(Some("local"), Some("json"))); + assert!(!json_logs_enabled(Some("production"), Some("pretty"))); + } + + #[derive(Clone, Default)] + struct Capture(Arc>>); + + impl io::Write for Capture { + fn write(&mut self, buf: &[u8]) -> io::Result { + self.0.lock().unwrap().extend_from_slice(buf); + Ok(buf.len()) + } + + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } + } + + impl<'a> MakeWriter<'a> for Capture { + type Writer = Capture; + + fn make_writer(&'a self) -> Capture { + self.clone() + } + } + + fn captured_json(capture: &Capture) -> serde_json::Value { + let bytes = capture.0.lock().unwrap(); + let text = std::str::from_utf8(&bytes).expect("log output must be valid UTF-8"); + serde_json::from_str(text.lines().next().expect("a log line must be written")) + .expect("log line must be valid JSON") + } + + #[test] + fn formats_event_as_single_line_json() { + let capture = Capture::default(); + let subscriber = + tracing_subscriber::registry().with(json_log_layer().with_writer(capture.clone())); + + tracing::subscriber::with_default(subscriber, || { + info!(dump_age_secs = 42, "hello"); + }); + + let json = captured_json(&capture); + assert_eq!(json["message"], "hello"); + assert_eq!(json["level"], "INFO"); + assert_eq!( + json["dump_age_secs"], 42, + "イベントフィールドはトップレベルへフラットに出力される" + ); + assert!(json.get("timestamp").is_some()); + assert!( + json.get("openTelemetry").is_none(), + "OTel の span がなければ traceId は出力しない" + ); + } + + #[test] + fn injects_trace_and_span_id_inside_otel_span() { + let capture = Capture::default(); + let provider = opentelemetry_sdk::trace::SdkTracerProvider::builder().build(); + let subscriber = tracing_subscriber::registry() + .with(tracing_opentelemetry::layer().with_tracer(provider.tracer("test"))) + .with(json_log_layer().with_writer(capture.clone())); + + tracing::subscriber::with_default(subscriber, || { + let span = tracing::info_span!("request"); + let _guard = span.enter(); + info!("with trace"); + }); + + let json = captured_json(&capture); + let trace_id = json["openTelemetry"]["traceId"] + .as_str() + .expect("traceId must be present"); + assert_eq!(trace_id.len(), 32); + assert!(trace_id.chars().all(|c| c.is_ascii_hexdigit())); + assert_ne!(trace_id, "0".repeat(32), "traceId must be valid (non-zero)"); + + let span_id = json["openTelemetry"]["spanId"] + .as_str() + .expect("spanId must be present"); + assert_eq!(span_id.len(), 16); + } +} diff --git a/server/src/main.rs b/server/src/main.rs index 7c72778..536c92a 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -1,3 +1,7 @@ +mod logging; +mod panic_hook; +mod telemetry; + mod domain { use bytes::Bytes; use std::fmt::Debug; @@ -193,34 +197,76 @@ async fn main() { presentation::get_gachadata_handler, }; use axum::{Router, routing::get}; - use sentry::integrations::tower::{NewSentryLayer, SentryHttpLayer}; + use axum_tracing_opentelemetry::middleware::{OtelAxumLayer, OtelInResponseLayer}; + use opentelemetry::trace::TracerProvider as _; + use pyroscope::backend::{BackendConfig, PprofConfig, pprof_backend}; + use pyroscope::pyroscope::PyroscopeAgentBuilder; use std::sync::{Arc, Mutex}; use tokio::net::TcpListener; + use tower_http::catch_panic::CatchPanicLayer; use tracing_subscriber::{Layer, layer::SubscriberExt, util::SubscriberInitExt}; - tracing_subscriber::registry() - .with(sentry::integrations::tracing::layer()) - .with( - tracing_subscriber::fmt::layer().with_filter(tracing_subscriber::EnvFilter::new( - std::env::var("RUST_LOG").unwrap_or_else(|_| "info".into()), - )), - ) - .init(); - - let _guard = sentry::init(( - "https://d1672e23eefd4bc49b6081a051951f85@sentry.onp.admin.seichi.click/10", - sentry::ClientOptions { - release: sentry::release_name!(), - traces_sample_rate: 1.0, - ..Default::default() - }, - )); + // OTel トレーシング (OTLP http/protobuf)。 + // OTEL_EXPORTER_OTLP_ENDPOINT 未設定または OTEL_SDK_DISABLED=true なら無効 + let tracer_provider = telemetry::init_tracer_provider(); - sentry::configure_scope(|scope| scope.set_level(Some(sentry::Level::Warning))); + // stdout ログ: 本番は 1 行 JSON (trace_id 注入付き)、ローカル (ENV_NAME=local) は + // 人間向けフォーマット。LOG_FORMAT=json|pretty で明示上書き可 + let stdout_log_filter = || { + tracing_subscriber::EnvFilter::new( + std::env::var("RUST_LOG").unwrap_or_else(|_| "info".into()), + ) + }; + let json_logs_enabled = logging::json_logs_enabled( + std::env::var("ENV_NAME").ok().as_deref(), + std::env::var("LOG_FORMAT").ok().as_deref(), + ); + let (json_log_layer, pretty_log_layer) = if json_logs_enabled { + ( + Some(logging::json_log_layer().with_filter(stdout_log_filter())), + None, + ) + } else { + ( + None, + Some(tracing_subscriber::fmt::layer().with_filter(stdout_log_filter())), + ) + }; - let layer = tower::ServiceBuilder::new() - .layer(NewSentryLayer::new_from_top()) - .layer(SentryHttpLayer::new().enable_transaction()); + tracing_subscriber::registry() + .with(tracer_provider.as_ref().map(|provider| { + tracing_opentelemetry::layer().with_tracer(provider.tracer("gachadata-server")) + })) + .with(json_log_layer) + .with(pretty_log_layer) + .init(); + panic_hook::install(); + + // 継続プロファイリング (Grafana Pyroscope への push)。 + // PYROSCOPE_SERVER_ADDRESS 未設定なら無効。起動失敗はサーバー本体を止めない。 + // agent はプロセスの生存期間中動かし続けるため束縛だけ保持する + let _pyroscope_agent = std::env::var("PYROSCOPE_SERVER_ADDRESS") + .ok() + .and_then(|server_address| { + let started = PyroscopeAgentBuilder::new( + &server_address, + "gachadata-server", + 100, + "pyroscope-rs", + env!("CARGO_PKG_VERSION"), + pprof_backend(PprofConfig::default(), BackendConfig::default()), + ) + .build() + .and_then(pyroscope::PyroscopeAgent::start); + + match started { + Ok(agent) => Some(agent), + Err(error) => { + tracing::warn!(%error, "Pyroscope agent の起動に失敗したため、プロファイルなしで続行します"); + None + } + } + }); let config = Config::from_environment() .await @@ -234,7 +280,13 @@ async fn main() { let router = Router::new() .route("/", get(get_gachadata_handler)) .with_state(mysql_dump_connection) - .layer(layer); + // handler 内 panic で 500 を返し、コネクションを維持する + // (panic 自体は panic_hook が panic=true 付きでログに残す) + .layer(CatchPanicLayer::new()) + // レスポンスヘッダーへの trace context 挿入 (OtelAxumLayer より内側に置く) + .layer(OtelInResponseLayer) + // リクエストごとの OTel サーバースパン開始 + .layer(OtelAxumLayer::default()); let addr = std::net::SocketAddr::from(([0, 0, 0, 0], config.http_port.port)); @@ -242,5 +294,10 @@ async fn main() { let listener = TcpListener::bind(addr).await.unwrap(); - axum::serve(listener, router).await.unwrap() + axum::serve(listener, router).await.unwrap(); + + // serve が戻るのはシャットダウン時のみ。バッファ済みスパンを flush する + if let Some(provider) = tracer_provider { + let _ = provider.shutdown(); + } } diff --git a/server/src/panic_hook.rs b/server/src/panic_hook.rs new file mode 100644 index 0000000..00690bf --- /dev/null +++ b/server/src/panic_hook.rs @@ -0,0 +1,99 @@ +use std::backtrace::Backtrace; + +/// panic を tracing の ERROR イベントとして記録する panic hook を登録します。 +/// +/// `panic = true` フィールドは seichi_infra 側の LogQL ルール +/// (`| json | panic="true"`) とアプリ間の契約であり、 +/// 変更する場合は LogQL ルール側も直すこと。 +/// +/// 既存の hook (stderr への出力) はチェーンして維持する。 +/// (seichi-portal-backend の panic_hook.rs と同じ構成) +pub fn install() { + let previous_hook = std::panic::take_hook(); + std::panic::set_hook(Box::new(move |panic_info| { + let payload = panic_info.payload(); + let message = payload + .downcast_ref::<&str>() + .copied() + .or_else(|| payload.downcast_ref::().map(String::as_str)) + .unwrap_or(""); + let location = panic_info + .location() + .map(ToString::to_string) + .unwrap_or_else(|| "".to_owned()); + let backtrace = Backtrace::force_capture(); + + tracing::error!( + panic = true, + panic.location = %location, + backtrace = %backtrace, + "panicked: {message}" + ); + + previous_hook(panic_info); + })); +} + +#[cfg(test)] +mod tests { + use std::{ + io, + panic::catch_unwind, + sync::{Arc, Mutex}, + }; + + use tracing_subscriber::{fmt::MakeWriter, layer::SubscriberExt}; + + #[derive(Clone, Default)] + struct Capture(Arc>>); + + impl io::Write for Capture { + fn write(&mut self, buf: &[u8]) -> io::Result { + self.0.lock().unwrap().extend_from_slice(buf); + Ok(buf.len()) + } + + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } + } + + impl<'a> MakeWriter<'a> for Capture { + type Writer = Capture; + + fn make_writer(&'a self) -> Capture { + self.clone() + } + } + + #[test] + fn panic_is_logged_with_panic_field_and_backtrace() { + let capture = Capture::default(); + let subscriber = tracing_subscriber::registry() + .with(crate::logging::json_log_layer().with_writer(capture.clone())); + + super::install(); + tracing::subscriber::with_default(subscriber, || { + let _ = catch_unwind(|| panic!("boom for test")); + }); + + let bytes = capture.0.lock().unwrap(); + let text = std::str::from_utf8(&bytes).expect("log output must be valid UTF-8"); + let json: serde_json::Value = + serde_json::from_str(text.lines().next().expect("a log line must be written")) + .expect("log line must be valid JSON"); + + assert_eq!(json["panic"], true, "LogQL ルールとの契約フィールド"); + assert_eq!(json["level"], "ERROR"); + assert!( + json["message"] + .as_str() + .is_some_and(|message| message.contains("boom for test")) + ); + assert!( + json["backtrace"] + .as_str() + .is_some_and(|backtrace| !backtrace.is_empty()) + ); + } +} diff --git a/server/src/telemetry.rs b/server/src/telemetry.rs new file mode 100644 index 0000000..30a8c1a --- /dev/null +++ b/server/src/telemetry.rs @@ -0,0 +1,97 @@ +use opentelemetry::global; +use opentelemetry_otlp::{Protocol, SpanExporter, WithExportConfig}; +use opentelemetry_sdk::{Resource, propagation::TraceContextPropagator, trace::SdkTracerProvider}; + +const SERVICE_NAME: &str = "gachadata-server"; + +/// OpenTelemetry のトレーシングを初期化します。 +/// +/// `OTEL_SDK_DISABLED=true` または `OTEL_EXPORTER_OTLP_ENDPOINT` 未設定の場合は +/// 初期化をスキップして `None` を返します +/// (`OTEL_SDK_DISABLED` は Rust SDK 未実装のため自前でゲートしています)。 +/// +/// エクスポートは OTLP http/protobuf で、endpoint やその他の設定は +/// `OTEL_*` 環境変数から自動で読み込まれます。 +/// (seichi-portal-backend の telemetry.rs と同じ構成) +pub fn init_tracer_provider() -> Option { + let sdk_disabled = + std::env::var("OTEL_SDK_DISABLED").is_ok_and(|value| value.eq_ignore_ascii_case("true")); + let endpoint_configured = + std::env::var("OTEL_EXPORTER_OTLP_ENDPOINT").is_ok_and(|value| !value.is_empty()); + + if sdk_disabled || !endpoint_configured { + return None; + } + + global::set_text_map_propagator(TraceContextPropagator::new()); + + let exporter = SpanExporter::builder() + .with_http() + .with_protocol(Protocol::HttpBinary) + .build() + .expect("failed to build OTLP span exporter"); + + // Resource::builder() は OTEL_SERVICE_NAME / OTEL_RESOURCE_ATTRIBUTES を + // 自動で読むため、service.name は環境変数未設定時のみデフォルト値を与える + let resource = if std::env::var("OTEL_SERVICE_NAME").is_ok() { + Resource::builder().build() + } else { + Resource::builder().with_service_name(SERVICE_NAME).build() + }; + + let provider = SdkTracerProvider::builder() + .with_batch_exporter(exporter) + .with_resource(resource) + .build(); + + global::set_tracer_provider(provider.clone()); + + Some(provider) +} + +#[cfg(test)] +mod tests { + use super::init_tracer_provider; + + /// 環境変数の設定はプロセス全体に影響するため、 + /// 競合しないよう 1 つのテストで順に検証する。 + #[test] + fn tracer_provider_is_gated_by_environment_variables() { + // SAFETY: このテストバイナリ内で環境変数を読み書きするのはこのテストだけ + unsafe { + std::env::remove_var("OTEL_EXPORTER_OTLP_ENDPOINT"); + std::env::remove_var("OTEL_SDK_DISABLED"); + } + assert!( + init_tracer_provider().is_none(), + "OTEL_EXPORTER_OTLP_ENDPOINT 未設定なら初期化をスキップする" + ); + + unsafe { + std::env::set_var("OTEL_EXPORTER_OTLP_ENDPOINT", "http://localhost:4318"); + std::env::set_var("OTEL_SDK_DISABLED", "true"); + } + assert!( + init_tracer_provider().is_none(), + "OTEL_SDK_DISABLED=true なら endpoint が設定されていてもスキップする" + ); + + unsafe { + std::env::remove_var("OTEL_SDK_DISABLED"); + } + let provider = init_tracer_provider(); + assert!( + provider.is_some(), + "endpoint 設定時は tracer provider が初期化される" + ); + + if let Some(provider) = provider { + provider + .shutdown() + .expect("tracer provider must shut down cleanly"); + } + unsafe { + std::env::remove_var("OTEL_EXPORTER_OTLP_ENDPOINT"); + } + } +}