diff --git a/Cargo.lock b/Cargo.lock index 02805bb55..ff0186a29 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -140,9 +140,9 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anstream" -version = "0.6.21" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" +checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" dependencies = [ "anstyle", "anstyle-parse", @@ -155,15 +155,15 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" [[package]] name = "anstyle-parse" -version = "0.2.7" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" dependencies = [ "utf8parse", ] @@ -190,9 +190,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.101" +version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e0fee31ef5ed1ba1316088939cea399010ed7731dba877ed44aeb407a75ea" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" [[package]] name = "append-only-vec" @@ -202,9 +202,9 @@ checksum = "2114736faba96bcd79595c700d03183f61357b9fbce14852515e59f3bee4ed4a" [[package]] name = "arc-swap" -version = "1.8.2" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9f3647c145568cec02c42054e07bdf9a5a698e15b466fb2341bfc393cd24aa5" +checksum = "a07d1f37ff60921c83bdfc7407723bdefe89b44b98a9b772f225c8f9d67141a6" dependencies = [ "rustversion", ] @@ -299,7 +299,7 @@ checksum = "3109e49b1e4909e9db6515a30c633684d68cdeaa252f215214cb4fa1a5bfee2c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", "synstructure", ] @@ -311,7 +311,7 @@ checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -322,9 +322,9 @@ checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" [[package]] name = "async-compression" -version = "0.4.39" +version = "0.4.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68650b7df54f0293fd061972a0fb05aaf4fc0879d3b3d21a638a182c5c543b9f" +checksum = "d0f9ee0f6e02ffd7ad5816e9464499fba7b3effd01123b515c41d1697c43dad1" dependencies = [ "compression-codecs", "compression-core", @@ -340,7 +340,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -392,6 +392,17 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi 0.1.19", + "libc", + "winapi", +] + [[package]] name = "autocfg" version = "1.5.0" @@ -400,9 +411,9 @@ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "aws-lc-rs" -version = "1.15.4" +version = "1.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b7b6141e96a8c160799cc2d5adecd5cbbe5054cb8c7c4af53da0f83bb7ad256" +checksum = "a054912289d18629dc78375ba2c3726a3afe3ff71b4edba9dedfca0e3446d1fc" dependencies = [ "aws-lc-sys", "zeroize", @@ -410,9 +421,9 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.37.1" +version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b092fe214090261288111db7a2b2c2118e5a7f30dc2569f1732c4069a6840549" +checksum = "1fa7e52a4c5c547c741610a2c6f123f3881e409b714cd27e6798ef020c514f0a" dependencies = [ "cc", "cmake", @@ -559,7 +570,7 @@ dependencies = [ "regex", "rustc-hash 1.1.0", "shlex", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -577,7 +588,7 @@ dependencies = [ "regex", "rustc-hash 2.1.1", "shlex", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -731,7 +742,7 @@ checksum = "e0b121a9fe0df916e362fb3271088d071159cdf11db0e4182d02152850756eff" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -767,25 +778,26 @@ dependencies = [ [[package]] name = "borsh" -version = "1.6.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1da5ab77c1437701eeff7c88d968729e7766172279eab0676857b3d63af7a6f" +checksum = "cfd1e3f8955a5d7de9fab72fc8373fade9fb8a703968cb200ae3dc6cf08e185a" dependencies = [ "borsh-derive", + "bytes", "cfg_aliases", ] [[package]] name = "borsh-derive" -version = "1.6.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0686c856aa6aac0c4498f936d7d6a02df690f614c03e4d906d1018062b5c5e2c" +checksum = "bfcfdc083699101d5a7965e49925975f2f55060f94f9a05e7187be95d530ca59" dependencies = [ "once_cell", "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -821,9 +833,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.19.1" +version = "3.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510" +checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" [[package]] name = "by_address" @@ -922,9 +934,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.56" +version = "1.2.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aebf35691d1bfb0ac386a69bac2fde4dd276fb618cf8bf4f5318fe285e821bb2" +checksum = "7a0dd1ca384932ff3641c8718a02769f1698e7563dc6974ffd03346116310423" dependencies = [ "find-msvc-tools", "jobserver", @@ -990,9 +1002,9 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.43" +version = "0.4.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fac4744fb15ae8337dc853fee7fb3f4e48c0fbaa23d0afe49c447b4fab126118" +checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" dependencies = [ "iana-time-zone", "js-sys", @@ -1053,9 +1065,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.59" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5caf74d17c3aec5495110c34cc3f78644bfa89af6c8993ed4de2790e49b6499" +checksum = "b193af5b67834b676abd72466a96c1024e6a6ad978a1f484bd90b85c94041351" dependencies = [ "clap_builder", "clap_derive", @@ -1063,9 +1075,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.59" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "370daa45065b80218950227371916a1633217ae42b2715b2287b606dcd618e24" +checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" dependencies = [ "anstream", "anstyle", @@ -1075,21 +1087,21 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.55" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a92793da1a46a5f2a02a6f4c46c6496b28c43638adea8306fcb0caa1634f24e5" +checksum = "1110bd8a634a1ab8cb04345d8d878267d57c3cf1b38d91b71af6686408bbca6a" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] name = "clap_lex" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a822ea5bc7590f9d40f1ba12c0dc3c2760f3482c6984db1573ad11031420831" +checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" [[package]] name = "cmake" @@ -1126,15 +1138,15 @@ dependencies = [ [[package]] name = "colorchoice" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" +checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" [[package]] name = "compression-codecs" -version = "0.4.36" +version = "0.4.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00828ba6fd27b45a448e57dbfe84f1029d4c9f26b368157e9a448a5f49a2ec2a" +checksum = "eb7b51a7d9c967fc26773061ba86150f19c50c0d65c887cb1fbe295fd16619b7" dependencies = [ "compression-core", "flate2", @@ -1160,14 +1172,14 @@ dependencies = [ [[package]] name = "config" -version = "0.15.19" +version = "0.15.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b30fa8254caad766fc03cb0ccae691e14bf3bd72bfff27f72802ce729551b3d6" +checksum = "8e68cfe19cd7d23ffde002c24ffa5cda73931913ef394d5eaaa32037dc940c0c" dependencies = [ "pathdiff", "serde_core", - "toml 0.9.12+spec-1.1.0", - "winnow", + "toml 1.1.0+spec-1.1.0", + "winnow 1.0.0", ] [[package]] @@ -1488,7 +1500,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -1536,7 +1548,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.11.1", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -1558,7 +1570,7 @@ checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" dependencies = [ "darling_core 0.21.3", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -1640,7 +1652,7 @@ dependencies = [ "quote", "sha3", "strum", - "syn 2.0.116", + "syn 2.0.117", "void", ] @@ -1652,7 +1664,7 @@ checksum = "74ef43543e701c01ad77d3a5922755c6a1d71b22d942cb8042be4994b380caff" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -1716,7 +1728,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.116", + "syn 2.0.117", "unicode-xid", ] @@ -1770,7 +1782,7 @@ dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -1781,7 +1793,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -1816,7 +1828,7 @@ dependencies = [ "proc-macro2", "quote", "strum", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -1854,7 +1866,7 @@ checksum = "0b0713d5c1d52e774c5cd7bb8b043d7c0fc4f921abfb678556140bfbe6ab2364" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -1900,13 +1912,13 @@ dependencies = [ [[package]] name = "ed25519-zebra" -version = "4.1.0" +version = "4.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0017d969298eec91e3db7a2985a8cab4df6341d86e6f3a6f5878b13fb7846bc9" +checksum = "775765289f7c6336c18d3d66127527820dd45ffd9eb3b6b8ee4708590e6c20f5" dependencies = [ "curve25519-dalek", "ed25519", - "hashbrown 0.15.5", + "hashbrown 0.16.1", "pkcs8", "rand_core 0.6.4", "serde", @@ -1968,7 +1980,7 @@ dependencies = [ "num-traits", "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -1980,15 +1992,9 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] -[[package]] -name = "env_home" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7f84e12ccf0a7ddc17a6c41c93326024c42920d7ee630d04950e6926645c0fe" - [[package]] name = "env_logger" version = "0.7.1" @@ -2023,7 +2029,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -2167,6 +2173,12 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" +[[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.2" @@ -2283,7 +2295,7 @@ checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -2370,20 +2382,20 @@ dependencies = [ "cfg-if", "js-sys", "libc", - "r-efi", + "r-efi 5.3.0", "wasip2", "wasm-bindgen", ] [[package]] name = "getrandom" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "139ef39800118c7683f2fd3c98c1b23c09ae076556b435f8e9064ae108aaeeec" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" dependencies = [ "cfg-if", "libc", - "r-efi", + "r-efi 6.0.0", "rand_core 0.10.0", "wasip2", "wasip3", @@ -2398,7 +2410,7 @@ dependencies = [ "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -2537,9 +2549,7 @@ version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ - "allocator-api2", - "equivalent", - "foldhash", + "foldhash 0.1.5", ] [[package]] @@ -2547,6 +2557,11 @@ name = "hashbrown" version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash 0.2.0", +] [[package]] name = "hashlink" @@ -2563,6 +2578,15 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + [[package]] name = "hermit-abi" version = "0.5.2" @@ -2953,7 +2977,7 @@ checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -2996,9 +3020,9 @@ dependencies = [ [[package]] name = "inotify" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f37dccff2791ab604f9babef0ba14fbe0be30bd368dc541e2b08d07c8aa908f3" +checksum = "bd5b3eaf1a28b758ac0faa5a4254e8ab2705605496f1b1f3fbbc3988ad73d199" dependencies = [ "bitflags 2.11.0", "inotify-sys", @@ -3064,24 +3088,24 @@ dependencies = [ [[package]] name = "inventory" -version = "0.3.21" +version = "0.3.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc61209c082fbeb19919bee74b176221b27223e27b65d781eb91af24eb1fb46e" +checksum = "009ae045c87e7082cb72dab0ccd01ae075dd00141ddc108f43a0ea150a9e7227" dependencies = [ "rustversion", ] [[package]] name = "ipnet" -version = "2.11.0" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" +checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" [[package]] name = "iri-string" -version = "0.7.10" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c91338f0783edbd6195decb37bae672fd3b165faffb89bf7b9e6942f8b1a731a" +checksum = "d8e7418f59cc01c88316161279a7f665217ae316b388e58a0d10e29f54f1e5eb" dependencies = [ "memchr", "serde", @@ -3122,9 +3146,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "jobserver" @@ -3138,9 +3162,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.85" +version = "0.3.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c942ebf8e95485ca0d52d97da7c5a2c387d0e7f0ba4c35e93bfcaee045955b3" +checksum = "b49715b7073f385ba4bc528e5747d02e66cb39c6146efb66b781f131f0fb399c" dependencies = [ "once_cell", "wasm-bindgen", @@ -3199,7 +3223,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -3266,11 +3290,11 @@ dependencies = [ [[package]] name = "known-folders" -version = "1.4.0" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d463f34ca3c400fde3a054da0e0b8c6ffa21e4590922f3e18281bb5eeef4cbdc" +checksum = "7a1886916523694cd6ea3d175f03a1e5010699a2a4cc13696d83d7bea1d80638" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -3316,9 +3340,9 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" [[package]] name = "libc" -version = "0.2.182" +version = "0.2.183" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112" +checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d" [[package]] name = "libloading" @@ -3332,9 +3356,9 @@ dependencies = [ [[package]] name = "liblzma" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73c36d08cad03a3fbe2c4e7bb3a9e84c57e4ee4135ed0b065cade3d98480c648" +checksum = "b6033b77c21d1f56deeae8014eb9fbe7bdf1765185a6c508b5ca82eeaed7f899" dependencies = [ "liblzma-sys", ] @@ -3358,13 +3382,14 @@ checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" [[package]] name = "libredox" -version = "0.1.12" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d0b95e02c851351f877147b7deea7b1afb1df71b63aa5f8270716e0c5720616" +checksum = "1744e39d1d6a9948f4f388969627434e31128196de472883b39f148769bfe30a" dependencies = [ "bitflags 2.11.0", "libc", - "redox_syscall 0.7.1", + "plain", + "redox_syscall 0.7.3", ] [[package]] @@ -3395,9 +3420,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.23" +version = "1.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15d118bbf3771060e7311cc7bb0545b01d08a8b4a7de949198dec1fa0ca1c0f7" +checksum = "d52f4c29e2a68ac30c9087e1b772dc9f44a2b66ed44edf2266cf2be9b03dafc1" dependencies = [ "cc", "pkg-config", @@ -3425,9 +3450,9 @@ checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "linux-raw-sys" -version = "0.11.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" [[package]] name = "litemap" @@ -3694,7 +3719,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -3765,15 +3790,15 @@ version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" dependencies = [ - "hermit-abi", + "hermit-abi 0.5.2", "libc", ] [[package]] name = "num_enum" -version = "0.7.5" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1207a7e20ad57b847bbddc6776b968420d38292bbfe2089accff5e19e82454c" +checksum = "5d0bca838442ec211fa11de3a8b0e0e8f3a4522575b5c4c06ed722e005036f26" dependencies = [ "num_enum_derive", "rustversion", @@ -3781,14 +3806,14 @@ dependencies = [ [[package]] name = "num_enum_derive" -version = "0.7.5" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff32365de1b6743cb203b710788263c44a03de03802daf96092f2da4fe6ba4d7" +checksum = "680998035259dcfcafe653688bf2aa6d3e2dc05e98be6ab46afb089dc84f1df8" dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -3821,9 +3846,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.21.3" +version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "once_cell_polyfill" @@ -3864,7 +3889,7 @@ dependencies = [ "schemars 1.2.1", "serde", "serde_json", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -3881,7 +3906,7 @@ checksum = "969ccca8ffc4fb105bd131a228107d5c9dd89d9d627edf3295cbe979156f9712" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -3955,9 +3980,9 @@ dependencies = [ [[package]] name = "owo-colors" -version = "4.2.3" +version = "4.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c6901729fa79e91a0913333229e9ca5dc725089d1c363b2f4b4760709dc4a52" +checksum = "d211803b9b6b570f68772237e415a029d5a50c65d382910b879fb19d3271f94d" [[package]] name = "p256" @@ -4031,7 +4056,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -4236,7 +4261,7 @@ dependencies = [ "phf_shared 0.12.1", "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -4249,7 +4274,7 @@ dependencies = [ "phf_shared 0.13.1", "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -4272,29 +4297,29 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.1.10" +version = "1.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" +checksum = "f1749c7ed4bcaf4c3d0a3efc28538844fb29bcdd7d2b67b2be7e20ba861ff517" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.10" +version = "1.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" +checksum = "d9b20ed30f105399776b9c883e68e536ef602a16ae6f596d2c473591d6ad64c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] name = "pin-project-lite" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" [[package]] name = "pin-utils" @@ -4329,6 +4354,12 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +[[package]] +name = "plain" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" + [[package]] name = "plotters" version = "0.3.7" @@ -4429,7 +4460,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -4476,11 +4507,11 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "3.4.0" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" +checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" dependencies = [ - "toml_edit 0.23.10+spec-1.0.0", + "toml_edit 0.25.8+spec-1.1.0", ] [[package]] @@ -4502,7 +4533,7 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -4542,7 +4573,7 @@ checksum = "4ee1c9ac207483d5e7db4940700de86a9aae46ef90c48b57f99fe7edb8345e49" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -4572,7 +4603,7 @@ dependencies = [ "pulldown-cmark", "pulldown-cmark-to-cmark", "regex", - "syn 2.0.116", + "syn 2.0.117", "tempfile", ] @@ -4586,7 +4617,7 @@ dependencies = [ "itertools 0.14.0", "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -4636,9 +4667,9 @@ dependencies = [ [[package]] name = "pulldown-cmark" -version = "0.13.0" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e8bbe1a966bd2f362681a44f6edce3c2310ac21e4d5067a6e7ec396297a6ea0" +checksum = "7c3a14896dfa883796f1cb410461aef38810ea05f2b2c33c5aded3649095fdad" dependencies = [ "bitflags 2.11.0", "memchr", @@ -4717,9 +4748,9 @@ dependencies = [ [[package]] name = "quinn-proto" -version = "0.11.13" +version = "0.11.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" +checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098" dependencies = [ "bytes", "getrandom 0.3.4", @@ -4747,14 +4778,14 @@ dependencies = [ "once_cell", "socket2", "tracing", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] name = "quote" -version = "1.0.44" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" dependencies = [ "proc-macro2", ] @@ -4765,6 +4796,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 = "radium" version = "0.7.0" @@ -4812,7 +4849,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc266eb313df6c5c09c1c7b1fbe2510961e5bcd3add930c1e31f7ed9da0feff8" dependencies = [ "chacha20 0.10.0", - "getrandom 0.4.1", + "getrandom 0.4.2", "rand_core 0.10.0", ] @@ -4979,9 +5016,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.7.1" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35985aa610addc02e24fc232012c86fd11f14111180f902b67e2d5331f8ebf2b" +checksum = "6ce70a74e890531977d37e532c34d45e9055d2409ed08ddba14529471ed0be16" dependencies = [ "bitflags 2.11.0", ] @@ -5014,7 +5051,7 @@ checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -5042,9 +5079,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.9" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a96887878f22d7bad8a3b6dc5b7440e0ada9a245242924394987b21cf2210a4c" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" [[package]] name = "rend" @@ -5253,7 +5290,7 @@ dependencies = [ "proc-macro2", "quote", "rust-embed-utils", - "syn 2.0.116", + "syn 2.0.117", "walkdir", ] @@ -5340,15 +5377,15 @@ dependencies = [ [[package]] name = "rustix" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ "bitflags 2.11.0", "errno", "libc", - "linux-raw-sys 0.11.0", - "windows-sys 0.59.0", + "linux-raw-sys 0.12.1", + "windows-sys 0.61.2", ] [[package]] @@ -5374,7 +5411,7 @@ dependencies = [ "once_cell", "ring", "rustls-pki-types", - "rustls-webpki 0.103.9", + "rustls-webpki 0.103.10", "subtle", "zeroize", ] @@ -5413,9 +5450,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.103.9" +version = "0.103.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7df23109aa6c1567d1c575b9952556388da57401e4ace1d15f79eedad0d8f53" +checksum = "df33b2b81ac578cabaf06b89b0631153a3f416b0a886e8a7a1707fb51abbd1ef" dependencies = [ "aws-lc-rs", "ring", @@ -5513,9 +5550,9 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.28" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" +checksum = "91c1b7e4904c873ef0710c1f407dde2e6287de2bebc1bbbf7d430bb7cbffd939" dependencies = [ "windows-sys 0.61.2", ] @@ -5554,7 +5591,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -5643,9 +5680,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "3.6.0" +version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d17b898a6d6948c3a8ee4372c17cb384f90d2e6e912ef00895b14fd7ab54ec38" +checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" dependencies = [ "bitflags 2.11.0", "core-foundation", @@ -5656,9 +5693,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.16.0" +version = "2.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "321c8673b092a9a42605034a9879d73cb79101ed5fd117bc9a597b89b4e9e61a" +checksum = "6ce2691df843ecc5d231c0b14ece2acc3efb62c0a398c7e1d875f3983ce020e3" dependencies = [ "core-foundation-sys", "libc", @@ -5720,7 +5757,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -5731,7 +5768,7 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -5769,9 +5806,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "1.0.4" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8bbf91e5a4d6315eee45e704372590b30e260ee83af6639d64557f51b067776" +checksum = "876ac351060d4f882bb1032b6369eb0aef79ad9df1ea8bc404874d8cc3d0cd98" dependencies = [ "serde_core", ] @@ -5790,9 +5827,9 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.16.1" +version = "3.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fa237f2807440d238e0364a218270b98f767a00d3dada77b1c53ae88940e2e7" +checksum = "381b283ce7bc6b476d903296fb59d0d36633652b633b27f64db4fb46dcbfc3b9" dependencies = [ "base64", "chrono", @@ -5809,14 +5846,14 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.16.1" +version = "3.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52a8e3ca0ca629121f70ab50f95249e5a6f925cc0f6ffe8256c45b728875706c" +checksum = "a6d4e30573c8cb306ed6ab1dca8423eec9a463ea0e155f45399455e0368b27e0" dependencies = [ "darling 0.21.3", "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -5873,9 +5910,9 @@ dependencies = [ [[package]] name = "shardtree" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "637e95dcd06bc1bb3f86ed9db1e1832a70125f32daae071ef37dcb7701b7d4fe" +checksum = "359e552886ae54d1642091645980d83f7db465fd9b5b0248e3680713c1773388" dependencies = [ "bitflags 2.11.0", "either", @@ -5885,9 +5922,9 @@ dependencies = [ [[package]] name = "shellexpand" -version = "3.1.1" +version = "3.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b1fdf65dd6331831494dd616b30351c38e96e45921a27745cf98490458b90bb" +checksum = "32824fab5e16e6c4d86dc1ba84489390419a39f97699852b66480bb87d297ed8" dependencies = [ "bstr", "dirs", @@ -5998,12 +6035,12 @@ checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "socket2" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86f4aa3ad99f2088c990dfa82d367e19cb29268ed67c574d10d0a4bfe71f07e0" +checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -6144,7 +6181,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -6166,9 +6203,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.116" +version = "2.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3df424c70518695237746f84cede799c9c58fcb37450d7b23716568cc8bc69cb" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" dependencies = [ "proc-macro2", "quote", @@ -6192,7 +6229,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -6217,15 +6254,15 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" -version = "3.25.0" +version = "3.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0136791f7c95b1f6dd99f9cc786b91bb81c3800b639b3478e561ddb7be95e5f1" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom 0.4.1", + "getrandom 0.4.2", "once_cell", - "rustix 1.1.3", - "windows-sys 0.59.0", + "rustix 1.1.4", + "windows-sys 0.61.2", ] [[package]] @@ -6254,7 +6291,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -6265,7 +6302,7 @@ checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -6331,9 +6368,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" +checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" dependencies = [ "tinyvec_macros", ] @@ -6346,9 +6383,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.49.0" +version = "1.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86" +checksum = "27ad5e34374e03cfffefc301becb44e9dc3c17584f414349ebe29ed26661822d" dependencies = [ "bytes", "libc", @@ -6364,13 +6401,13 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.6.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" +checksum = "5c55a2eff8b69ce66c84f85e1da1c233edc36ceb85a2058d11b0d6a3c7e7569c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -6438,11 +6475,24 @@ checksum = "cf92845e79fc2e2def6a5d828f0801e29a2f8acc037becc5ab08595c7d5e9863" dependencies = [ "indexmap 2.13.0", "serde_core", - "serde_spanned 1.0.4", + "serde_spanned 1.1.0", "toml_datetime 0.7.5+spec-1.1.0", "toml_parser", "toml_writer", - "winnow", + "winnow 0.7.15", +] + +[[package]] +name = "toml" +version = "1.1.0+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8195ca05e4eb728f4ba94f3e3291661320af739c4e43779cbdfae82ab239fcc" +dependencies = [ + "serde_core", + "serde_spanned 1.1.0", + "toml_datetime 1.1.0+spec-1.1.0", + "toml_parser", + "winnow 1.0.0", ] [[package]] @@ -6463,6 +6513,15 @@ dependencies = [ "serde_core", ] +[[package]] +name = "toml_datetime" +version = "1.1.0+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97251a7c317e03ad83774a8752a7e81fb6067740609f75ea2b585b569a59198f" +dependencies = [ + "serde_core", +] + [[package]] name = "toml_edit" version = "0.22.27" @@ -6474,28 +6533,28 @@ dependencies = [ "serde_spanned 0.6.9", "toml_datetime 0.6.11", "toml_write", - "winnow", + "winnow 0.7.15", ] [[package]] name = "toml_edit" -version = "0.23.10+spec-1.0.0" +version = "0.25.8+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84c8b9f757e028cee9fa244aea147aab2a9ec09d5325a9b01e0a49730c2b5269" +checksum = "16bff38f1d86c47f9ff0647e6838d7bb362522bdf44006c7068c2b1e606f1f3c" dependencies = [ "indexmap 2.13.0", - "toml_datetime 0.7.5+spec-1.1.0", + "toml_datetime 1.1.0+spec-1.1.0", "toml_parser", - "winnow", + "winnow 1.0.0", ] [[package]] name = "toml_parser" -version = "1.0.9+spec-1.1.0" +version = "1.1.0+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "702d4415e08923e7e1ef96cd5727c0dfed80b4d2fa25db9647fe5eb6f7c5a4c4" +checksum = "2334f11ee363607eb04df9b8fc8a13ca1715a72ba8662a26ac285c98aabb4011" dependencies = [ - "winnow", + "winnow 1.0.0", ] [[package]] @@ -6506,15 +6565,15 @@ checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" [[package]] name = "toml_writer" -version = "1.0.6+spec-1.1.0" +version = "1.1.0+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab16f14aed21ee8bfd8ec22513f7287cd4a91aa92e44edfe2c17ddd004e92607" +checksum = "d282ade6016312faf3e41e57ebbba0c073e4056dab1232ab1cb624199648f8ed" [[package]] name = "tonic" -version = "0.14.4" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f32a6f80051a4111560201420c7885d0082ba9efe2ab61875c587bb6b18b9a0" +checksum = "fec7c61a0695dc1887c1b53952990f3ad2e3a31453e1f49f10e75424943a93ec" dependencies = [ "async-trait", "axum", @@ -6544,21 +6603,21 @@ dependencies = [ [[package]] name = "tonic-build" -version = "0.14.4" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6d8958ed3be404120ca43ffa0fb1e1fc7be214e96c8d33bd43a131b6eebc9e" +checksum = "1882ac3bf5ef12877d7ed57aad87e75154c11931c2ba7e6cde5e22d63522c734" dependencies = [ "prettyplease", "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] name = "tonic-prost" -version = "0.14.4" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f86539c0089bfd09b1f8c0ab0239d80392af74c21bc9e0f15e1b4aca4c1647f" +checksum = "a55376a0bbaa4975a3f10d009ad763d8f4108f067c7c2e74f3001fb49778d309" dependencies = [ "bytes", "prost", @@ -6567,25 +6626,25 @@ dependencies = [ [[package]] name = "tonic-prost-build" -version = "0.14.4" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65873ace111e90344b8973e94a1fc817c924473affff24629281f90daed1cd2e" +checksum = "f3144df636917574672e93d0f56d7edec49f90305749c668df5101751bb8f95a" dependencies = [ "prettyplease", "proc-macro2", "prost-build", "prost-types", "quote", - "syn 2.0.116", + "syn 2.0.117", "tempfile", "tonic-build", ] [[package]] name = "tonic-reflection" -version = "0.14.4" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e5f75c058c397bf4ecada0fe0a2299c49c252fcf484f4a2f47279b6fa7026b" +checksum = "aaf0685a51e6d02b502ba0764002e766b7f3042aed13d9234925b6ffbfa3fca7" dependencies = [ "prost", "prost-types", @@ -7436,7 +7495,7 @@ dependencies = [ "paste", "pin-project", "rustls-pki-types", - "rustls-webpki 0.103.9", + "rustls-webpki 0.103.10", "thiserror 2.0.18", "tokio", "tokio-util", @@ -7620,7 +7679,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -7664,16 +7723,28 @@ dependencies = [ "tracing-core", ] +[[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.22" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f30143827ddab0d256fd843b7a66d164e9f271cfa0dde49142c5ca0ca291f1e" +checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" dependencies = [ "matchers", "nu-ansi-term", "once_cell", "regex-automata", + "serde", + "serde_json", "sharded-slab", "smallvec", "thread_local", @@ -7681,6 +7752,7 @@ dependencies = [ "tracing", "tracing-core", "tracing-log", + "tracing-serde", ] [[package]] @@ -7701,7 +7773,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad06847b7afb65c7866a36664b75c40b895e318cea4f71299f013fb22965329d" dependencies = [ "quote", - "syn 2.0.116", + "syn 2.0.117", +] + +[[package]] +name = "tracing-tree" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac87aa03b6a4d5a7e4810d1a80c19601dbe0f8a837e9177f23af721c7ba7beec" +dependencies = [ + "nu-ansi-term", + "tracing-core", + "tracing-log", + "tracing-subscriber", ] [[package]] @@ -7712,7 +7796,7 @@ checksum = "70977707304198400eb4835a78f6a9f928bf41bba420deb8fdb175cd965d77a7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -7857,9 +7941,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.21.0" +version = "1.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b672338555252d43fd2240c714dc444b8c6fb0a5c5335e65a07bba7742735ddb" +checksum = "a68d3c8f01c0cfa54a75291d83601161799e4a89a39e0929f4b0354d88757a37" dependencies = [ "js-sys", "wasm-bindgen", @@ -7891,7 +7975,7 @@ checksum = "d674d135b4a8c1d7e813e2f8d1c9a58308aee4a680323066025e53132218bd91" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -8025,9 +8109,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.108" +version = "0.2.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64024a30ec1e37399cf85a7ffefebdb72205ca1c972291c51512360d90bd8566" +checksum = "6532f9a5c1ece3798cb1c2cfdba640b9b3ba884f5db45973a6f442510a87d38e" dependencies = [ "cfg-if", "once_cell", @@ -8038,9 +8122,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.58" +version = "0.4.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70a6e77fd0ae8029c9ea0063f87c46fde723e7d887703d74ad2616d792e51e6f" +checksum = "e9c5522b3a28661442748e09d40924dfb9ca614b21c00d3fd135720e48b67db8" dependencies = [ "cfg-if", "futures-util", @@ -8052,9 +8136,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.108" +version = "0.2.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "008b239d9c740232e71bd39e8ef6429d27097518b6b30bdf9086833bd5b6d608" +checksum = "18a2d50fcf105fb33bb15f00e7a77b772945a2ee45dcf454961fd843e74c18e6" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -8062,22 +8146,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.108" +version = "0.2.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5256bae2d58f54820e6490f9839c49780dff84c65aeab9e772f15d5f0e913a55" +checksum = "03ce4caeaac547cdf713d280eda22a730824dd11e6b8c3ca9e42247b25c631e3" dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.108" +version = "0.2.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f01b580c9ac74c8d8f0c0e4afb04eeef2acf145458e52c03845ee9cd23e3d12" +checksum = "75a326b8c223ee17883a4251907455a2431acc2791c98c26279376490c378c16" dependencies = [ "unicode-ident", ] @@ -8124,9 +8208,9 @@ checksum = "323f4da9523e9a669e1eaf9c6e763892769b1d38c623913647bfdc1532fe4549" [[package]] name = "web-sys" -version = "0.3.85" +version = "0.3.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "312e32e551d92129218ea9a2452120f4aabc03529ef03e4d0d82fb2780608598" +checksum = "854ba17bb104abfb26ba36da9729addc7ce7f06f5c0f90f3c391f8461cca21f9" dependencies = [ "js-sys", "wasm-bindgen", @@ -8171,13 +8255,11 @@ dependencies = [ [[package]] name = "which" -version = "8.0.0" +version = "8.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3fabb953106c3c8eea8306e4393700d7657561cb43122571b172bbfb7c7ba1d" +checksum = "81995fafaaaf6ae47a7d0cc83c67caf92aeb7e5331650ae6ff856f7c0c60c459" dependencies = [ - "env_home", - "rustix 1.1.3", - "winsafe", + "libc", ] [[package]] @@ -8213,7 +8295,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -8289,7 +8371,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -8300,7 +8382,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -8537,18 +8619,21 @@ checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" [[package]] name = "winnow" -version = "0.7.14" +version = "0.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" +checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" dependencies = [ "memchr", ] [[package]] -name = "winsafe" -version = "0.0.19" +name = "winnow" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904" +checksum = "a90e88e4667264a994d34e6d1ab2d26d398dcdca8b7f52bec8668957517fc7d8" +dependencies = [ + "memchr", +] [[package]] name = "wit-bindgen" @@ -8580,7 +8665,7 @@ dependencies = [ "heck", "indexmap 2.13.0", "prettyplease", - "syn 2.0.116", + "syn 2.0.117", "wasm-metadata", "wit-bindgen-core", "wit-component", @@ -8596,7 +8681,7 @@ dependencies = [ "prettyplease", "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", "wit-bindgen-core", "wit-bindgen-rust", ] @@ -8690,7 +8775,7 @@ checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", "synstructure", ] @@ -8698,9 +8783,15 @@ dependencies = [ name = "zaino-common" version = "0.2.0" dependencies = [ + "atty", + "hex", + "nu-ansi-term", "serde", "thiserror 1.0.69", - "zcash_local_net", + "time", + "tracing", + "tracing-subscriber", + "tracing-tree", "zebra-chain", "zingo_common_components", ] @@ -8900,9 +8991,9 @@ dependencies = [ [[package]] name = "zcash_client_backend" -version = "0.21.0" +version = "0.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5493217c813ba1f7ef4e6b6bf846f4e4cd57b6a070d679c9f15d2477e12d1464" +checksum = "d2b5eca509a516dbd9e4d13c1f5befd6d9fa25c7e62460444ef1b3f62122f323" dependencies = [ "arti-client", "base64", @@ -8952,7 +9043,7 @@ dependencies = [ "tracing", "trait-variant", "webpki-roots 1.0.6", - "which 8.0.0", + "which 8.0.2", "zcash_address", "zcash_encoding", "zcash_keys", @@ -9384,7 +9475,7 @@ dependencies = [ "tonic-reflection", "tower 0.4.13", "tracing", - "which 8.0.0", + "which 8.0.2", "zcash_address", "zcash_keys", "zcash_primitives", @@ -9480,22 +9571,22 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.39" +version = "0.8.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db6d35d663eadb6c932438e763b262fe1a70987f9ae936e60158176d710cae4a" +checksum = "efbb2a062be311f2ba113ce66f697a4dc589f85e78a4aea276200804cea0ed87" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.39" +version = "0.8.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4122cd3169e94605190e77839c9a40d40ed048d305bfdc146e7df40ab0f3e517" +checksum = "0e8bc7269b54418e7aeeef514aa68f8690b8c0489a06b0136e5f57c4c5ccab89" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -9515,7 +9606,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", "synstructure", ] @@ -9536,7 +9627,7 @@ checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -9570,7 +9661,7 @@ checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index b5fdb59bd..4bc256c28 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -64,8 +64,13 @@ tracing-subscriber = { version = "0.3.20", features = [ "fmt", "env-filter", "time", + "json", ] } tracing-futures = "0.2" +tracing-tree = "0.4" +nu-ansi-term = "0.50" +atty = "0.2" +time = { version = "0.3", features = ["macros", "formatting"] } # Network / RPC http = "1.1" diff --git a/Makefile.toml b/Makefile.toml index e76055a94..9ac9729a5 100644 --- a/Makefile.toml +++ b/Makefile.toml @@ -266,6 +266,8 @@ docker run --rm \ -e "TEST_BINARIES_DIR=${TEST_BINARIES_DIR}" \ -e "NEXTEST_EXPERIMENTAL_LIBTEST_JSON=1" \ -e "CARGO_TARGET_DIR=/home/container_user/zaino/target" \ + -e "ZAINOLOG_FORMAT=${ZAINOLOG_FORMAT:-stream}" \ + -e "RUST_LOG=${RUST_LOG:-}" \ -w /home/container_user/zaino \ -u container_user \ "${IMAGE_NAME}:$TAG" \ diff --git a/docs/logging.md b/docs/logging.md new file mode 100644 index 000000000..0499ef1bb --- /dev/null +++ b/docs/logging.md @@ -0,0 +1,90 @@ +# Logging Configuration + +Zaino provides flexible logging with three output formats and configurable verbosity levels. + +## Environment Variables + +| Variable | Values | Default | Description | +|----------|--------|---------|-------------| +| `RUST_LOG` | Filter string | `zaino=info,zainod=info` | Log level filter | +| `ZAINOLOG_FORMAT` | `stream`, `tree`, `json` | `stream` | Output format | +| `ZAINOLOG_COLOR` | `true`, `false`, `auto` | `true` | ANSI color output | + +## Log Formats + +### Stream (default) +Flat chronological output with timestamps. Best for general use and piping to files. +``` +14:32:01.234 INFO zaino_state::indexer: Starting indexer +14:32:01.456 INFO zaino_state::indexer: Connected to validator +``` + +### Tree +Hierarchical span-based output showing call structure. Best for debugging complex flows. +``` +indexer +├─ INFO Starting indexer +└─ validator_connection + └─ INFO Connected to validator +``` + +### JSON +Machine-parseable output. Best for log aggregation systems (ELK, Loki, etc). +```json +{"timestamp":"2024-01-15T14:32:01.234Z","level":"INFO","target":"zaino_state::indexer","message":"Starting indexer"} +``` + +## Usage Examples + +### Local Development + +```bash +# Default logging (stream format, zaino crates only at INFO level) +zainod start + +# Tree format for debugging span hierarchies +ZAINOLOG_FORMAT=tree zainod start + +# Debug level for zaino crates +RUST_LOG=zaino=debug,zainod=debug zainod start + +# Include zebra logs +RUST_LOG=info zainod start + +# Fine-grained control +RUST_LOG="zaino_state=debug,zaino_serve=info,zebra_state=warn" zainod start + +# Disable colors (for file output) +ZAINOLOG_COLOR=false zainod start 2>&1 | tee zainod.log +``` + +### Makefile / Container Tests + +The test environment passes logging variables through to containers: + +```bash +# Default (stream format) +makers container-test + +# Tree format in tests +ZAINOLOG_FORMAT=tree makers container-test + +# Debug logging in tests +RUST_LOG=debug ZAINOLOG_FORMAT=tree makers container-test + +# JSON output for parsing test logs +ZAINOLOG_FORMAT=json makers container-test 2>&1 | jq . +``` + +### Production + +```bash +# JSON for log aggregation +ZAINOLOG_FORMAT=json ZAINOLOG_COLOR=false zainod start + +# Structured logging to file +ZAINOLOG_FORMAT=json ZAINOLOG_COLOR=false zainod start 2>> /var/log/zainod.json + +# Minimal logging +RUST_LOG=warn zainod start +``` diff --git a/zaino-common/Cargo.toml b/zaino-common/Cargo.toml index b485b8e7b..3c6ca2494 100644 --- a/zaino-common/Cargo.toml +++ b/zaino-common/Cargo.toml @@ -18,5 +18,14 @@ serde = { workspace = true, features = ["derive"] } # Error handling thiserror = { workspace = true } +# Logging +tracing = { workspace = true } +tracing-subscriber = { workspace = true } +tracing-tree = { workspace = true } +nu-ansi-term = { workspace = true } +atty = { workspace = true } +hex = { workspace = true } +time = { workspace = true } + # Zingo zingo_common_components = { workspace = true } diff --git a/zaino-common/src/config/network.rs b/zaino-common/src/config/network.rs index a935eabe9..1c2e7f14b 100644 --- a/zaino-common/src/config/network.rs +++ b/zaino-common/src/config/network.rs @@ -1,5 +1,7 @@ //! Network type for Zaino configuration. +use std::fmt; + use serde::{Deserialize, Serialize}; use zebra_chain::parameters::testnet::ConfiguredActivationHeights; @@ -28,6 +30,16 @@ pub enum Network { Regtest(ActivationHeights), } +impl fmt::Display for Network { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Network::Mainnet => write!(f, "Mainnet"), + Network::Testnet => write!(f, "Testnet"), + Network::Regtest(_) => write!(f, "Regtest"), + } + } +} + /// Helper type for Network serialization/deserialization. /// /// This allows Network to serialize as simple strings ("Mainnet", "Testnet", "Regtest") diff --git a/zaino-common/src/lib.rs b/zaino-common/src/lib.rs index 934ef27d5..7669197b1 100644 --- a/zaino-common/src/lib.rs +++ b/zaino-common/src/lib.rs @@ -4,6 +4,7 @@ //! and common utilities used across the Zaino blockchain indexer ecosystem. pub mod config; +pub mod logging; pub mod net; pub mod probing; pub mod status; diff --git a/zaino-common/src/logging.rs b/zaino-common/src/logging.rs new file mode 100644 index 000000000..331683671 --- /dev/null +++ b/zaino-common/src/logging.rs @@ -0,0 +1,385 @@ +//! Logging infrastructure for Zaino. +//! +//! This module provides centralized logging configuration with support for: +//! - Stream view (flat chronological output) - DEFAULT +//! - Tree view (hierarchical span-based output) +//! - JSON output (machine-parseable) +//! +//! # Environment Variables +//! +//! - `RUST_LOG`: Standard tracing filter. By default only zaino crates are logged. +//! Set `RUST_LOG=info` to include all crates (zebra, etc.), or use specific +//! filters like `RUST_LOG=zaino=debug,zebra_state=info`. +//! - `ZAINOLOG_FORMAT`: Output format ("stream", "tree", or "json") +//! - `ZAINOLOG_COLOR`: Color mode ("true"/"false"/"auto"). Defaults to color enabled. +//! +//! # Example +//! +//! ```no_run +//! use zaino_common::logging; +//! +//! // Initialize with defaults (tree format, info level) +//! logging::init(); +//! +//! // Or with custom configuration +//! logging::init_with_config(logging::LogConfig::default().format(logging::LogFormat::Json)); +//! ``` + +use std::env; +use std::fmt; + +use time::macros::format_description; +use tracing::Level; +use tracing_subscriber::{ + fmt::{format::FmtSpan, time::UtcTime}, + layer::SubscriberExt, + util::SubscriberInitExt, + EnvFilter, +}; +use tracing_tree::HierarchicalLayer; + +/// Time format for logs: HH:MM:SS.subsec (compact, no date) +const TIME_FORMAT: &[time::format_description::FormatItem<'static>] = + format_description!("[hour]:[minute]:[second].[subsecond digits:3]"); + +/// Log output format. +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)] +pub enum LogFormat { + /// Hierarchical tree view showing span nesting. + Tree, + /// Flat chronological stream (default). + #[default] + Stream, + /// Machine-parseable JSON. + Json, +} + +impl LogFormat { + /// Parse from string (case-insensitive). + pub fn from_str(s: &str) -> Option { + match s.to_lowercase().as_str() { + "tree" => Some(LogFormat::Tree), + "stream" => Some(LogFormat::Stream), + "json" => Some(LogFormat::Json), + _ => None, + } + } + + /// Get from ZAINOLOG_FORMAT environment variable. + pub fn from_env() -> Self { + env::var("ZAINOLOG_FORMAT") + .ok() + .and_then(|s| Self::from_str(&s)) + .unwrap_or_default() + } +} + +impl fmt::Display for LogFormat { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + LogFormat::Tree => write!(f, "tree"), + LogFormat::Stream => write!(f, "stream"), + LogFormat::Json => write!(f, "json"), + } + } +} + +/// Logging configuration. +#[derive(Debug, Clone)] +pub struct LogConfig { + /// Output format (tree, stream, or json). + pub format: LogFormat, + /// Enable ANSI colors. + pub color: bool, + /// Default log level. + pub level: Level, + /// Show span events (enter/exit). + pub show_span_events: bool, +} + +impl Default for LogConfig { + fn default() -> Self { + // Check ZAINOLOG_COLOR env var: + // - "true"/"1"/etc: force color on + // - "false"/"0"/etc: force color off + // - "auto": auto-detect TTY (default behavior) + // If not set, default to color enabled (better dev experience) + let color = env::var("ZAINOLOG_COLOR") + .ok() + .and_then(|s| match s.to_lowercase().as_str() { + "1" | "true" | "yes" | "on" => Some(true), + "0" | "false" | "no" | "off" => Some(false), + "auto" => Some(atty::is(atty::Stream::Stderr)), + _ => None, + }) + .unwrap_or(true); // Default to color enabled + + Self { + format: LogFormat::from_env(), + color, + level: Level::INFO, + show_span_events: false, + } + } +} + +impl LogConfig { + /// Create a new config with defaults. + pub fn new() -> Self { + Self::default() + } + + /// Set the log format. + pub fn format(mut self, format: LogFormat) -> Self { + self.format = format; + self + } + + /// Enable or disable colors. + pub fn color(mut self, color: bool) -> Self { + self.color = color; + self + } + + /// Set the default log level. + pub fn level(mut self, level: Level) -> Self { + self.level = level; + self + } + + /// Show span enter/exit events. + pub fn show_span_events(mut self, show: bool) -> Self { + self.show_span_events = show; + self + } +} + +/// Initialize logging with default configuration. +/// +/// Reads `ZAINOLOG_FORMAT` environment variable to determine format: +/// - "stream" (default): Flat chronological output with timestamps +/// - "tree": Hierarchical span-based output +/// - "json": Machine-parseable JSON +pub fn init() { + init_with_config(LogConfig::default()); +} + +/// Initialize logging with custom configuration. +pub fn init_with_config(config: LogConfig) { + // If RUST_LOG is set, use it directly. Otherwise, default to zaino crates only. + // Users can set RUST_LOG=info to see all crates including zebra. + let env_filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| { + EnvFilter::new(format!( + "zaino={level},zainod={level},zainodlib={level}", + level = config.level.as_str() + )) + }); + + match config.format { + LogFormat::Tree => init_tree(env_filter, config), + LogFormat::Stream => init_stream(env_filter, config), + LogFormat::Json => init_json(env_filter), + } +} + +/// Try to initialize logging (won't fail if already initialized). +/// +/// Useful for tests where multiple test functions may try to initialize logging. +pub fn try_init() { + try_init_with_config(LogConfig::default()); +} + +/// Try to initialize logging with custom configuration. +pub fn try_init_with_config(config: LogConfig) { + let env_filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| { + EnvFilter::new(format!( + "zaino={level},zainod={level},zainodlib={level}", + level = config.level.as_str() + )) + }); + + match config.format { + LogFormat::Tree => { + let _ = try_init_tree(env_filter, config); + } + LogFormat::Stream => { + let _ = try_init_stream(env_filter, config); + } + LogFormat::Json => { + let _ = try_init_json(env_filter); + } + } +} + +fn init_tree(env_filter: EnvFilter, config: LogConfig) { + let layer = HierarchicalLayer::new(2) + .with_ansi(config.color) + .with_targets(true) + .with_bracketed_fields(true) + .with_indent_lines(true) + .with_thread_ids(false) + .with_thread_names(false) + .with_deferred_spans(true) // Only show spans when they have events + .with_verbose_entry(false) // Don't repeat span info on entry + .with_verbose_exit(false); // Don't repeat span info on exit + + tracing_subscriber::registry() + .with(env_filter) + .with(layer) + .init(); +} + +fn try_init_tree( + env_filter: EnvFilter, + config: LogConfig, +) -> Result<(), tracing_subscriber::util::TryInitError> { + let layer = HierarchicalLayer::new(2) + .with_ansi(config.color) + .with_targets(true) + .with_bracketed_fields(true) + .with_indent_lines(true) + .with_thread_ids(false) + .with_thread_names(false) + .with_deferred_spans(true) // Only show spans when they have events + .with_verbose_entry(false) // Don't repeat span info on entry + .with_verbose_exit(false); // Don't repeat span info on exit + + tracing_subscriber::registry() + .with(env_filter) + .with(layer) + .try_init() +} + +fn init_stream(env_filter: EnvFilter, config: LogConfig) { + let span_events = if config.show_span_events { + FmtSpan::ENTER | FmtSpan::EXIT + } else { + FmtSpan::NONE + }; + + tracing_subscriber::fmt() + .with_env_filter(env_filter) + .with_timer(UtcTime::new(TIME_FORMAT)) + .with_target(true) + .with_ansi(config.color) + .with_span_events(span_events) + .pretty() + .init(); +} + +fn try_init_stream( + env_filter: EnvFilter, + config: LogConfig, +) -> Result<(), tracing_subscriber::util::TryInitError> { + let span_events = if config.show_span_events { + FmtSpan::ENTER | FmtSpan::EXIT + } else { + FmtSpan::NONE + }; + + let fmt_layer = tracing_subscriber::fmt::layer() + .with_timer(UtcTime::new(TIME_FORMAT)) + .with_target(true) + .with_ansi(config.color) + .with_span_events(span_events) + .pretty(); + + tracing_subscriber::registry() + .with(env_filter) + .with(fmt_layer) + .try_init() +} + +fn init_json(env_filter: EnvFilter) { + // JSON format keeps full RFC3339 timestamps for machine parsing + tracing_subscriber::fmt() + .with_env_filter(env_filter) + .json() + .with_timer(UtcTime::rfc_3339()) + .with_target(true) + .init(); +} + +fn try_init_json(env_filter: EnvFilter) -> Result<(), tracing_subscriber::util::TryInitError> { + // JSON format keeps full RFC3339 timestamps for machine parsing + let fmt_layer = tracing_subscriber::fmt::layer() + .json() + .with_timer(UtcTime::rfc_3339()) + .with_target(true); + + tracing_subscriber::registry() + .with(env_filter) + .with(fmt_layer) + .try_init() +} + +/// Wrapper for displaying hashes in a compact format. +/// +/// Shows the first 4 bytes (8 hex chars) followed by "..". +pub struct DisplayHash<'a>(pub &'a [u8]); + +impl fmt::Display for DisplayHash<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + if self.0.len() >= 4 { + write!(f, "{}..", hex::encode(&self.0[..4])) + } else { + write!(f, "{}", hex::encode(self.0)) + } + } +} + +/// Wrapper for displaying hex strings in a compact format. +/// +/// Shows the first 8 chars followed by "..". +pub struct DisplayHexStr<'a>(pub &'a str); + +impl fmt::Display for DisplayHexStr<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + if self.0.len() > 8 { + write!(f, "{}..", &self.0[..8]) + } else { + write!(f, "{}", self.0) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_log_format_from_str() { + assert_eq!(LogFormat::from_str("tree"), Some(LogFormat::Tree)); + assert_eq!(LogFormat::from_str("TREE"), Some(LogFormat::Tree)); + assert_eq!(LogFormat::from_str("stream"), Some(LogFormat::Stream)); + assert_eq!(LogFormat::from_str("json"), Some(LogFormat::Json)); + assert_eq!(LogFormat::from_str("unknown"), None); + } + + #[test] + fn test_display_hash() { + let hash = [0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0]; + assert_eq!(format!("{}", DisplayHash(&hash)), "12345678.."); + } + + #[test] + fn test_display_hex_str() { + let hex_str = "1234567890abcdef"; + assert_eq!(format!("{}", DisplayHexStr(hex_str)), "12345678.."); + + let short_hex = "1234"; + assert_eq!(format!("{}", DisplayHexStr(short_hex)), "1234"); + } + + #[test] + fn test_config_builder() { + let config = LogConfig::new() + .format(LogFormat::Json) + .color(false) + .level(Level::DEBUG); + + assert_eq!(config.format, LogFormat::Json); + assert!(!config.color); + assert_eq!(config.level, Level::DEBUG); + } +} diff --git a/zaino-serve/src/server/grpc.rs b/zaino-serve/src/server/grpc.rs index fb6ec0559..4e8e806da 100644 --- a/zaino-serve/src/server/grpc.rs +++ b/zaino-serve/src/server/grpc.rs @@ -6,7 +6,7 @@ use tokio::time::interval; use tonic::transport::Server; use tracing::warn; use zaino_proto::proto::service::compact_tx_streamer_server::CompactTxStreamerServer; -use zaino_state::{AtomicStatus, IndexerSubscriber, LightWalletIndexer, StatusType, ZcashIndexer}; +use zaino_state::{IndexerSubscriber, LightWalletIndexer, NamedAtomicStatus, StatusType, ZcashIndexer}; use crate::{ rpc::GrpcClient, @@ -16,7 +16,7 @@ use crate::{ /// LightWallet gRPC server capable of servicing clients over TCP. pub struct TonicServer { /// Current status of the server. - pub status: AtomicStatus, + pub status: NamedAtomicStatus, /// JoinHandle for the servers `serve` task. pub server_handle: Option>>, } @@ -31,7 +31,7 @@ impl TonicServer { service_subscriber: IndexerSubscriber, server_config: GrpcServerConfig, ) -> Result { - let status = AtomicStatus::new(StatusType::Spawning); + let status = NamedAtomicStatus::new("gRPC", StatusType::Spawning); let svc = CompactTxStreamerServer::new(GrpcClient { service_subscriber: service_subscriber.clone(), diff --git a/zaino-serve/src/server/jsonrpc.rs b/zaino-serve/src/server/jsonrpc.rs index 5ae65d076..76294cd9c 100644 --- a/zaino-serve/src/server/jsonrpc.rs +++ b/zaino-serve/src/server/jsonrpc.rs @@ -5,7 +5,7 @@ use crate::{ server::{config::JsonRpcServerConfig, error::ServerError}, }; -use zaino_state::{AtomicStatus, IndexerSubscriber, LightWalletIndexer, StatusType, ZcashIndexer}; +use zaino_state::{IndexerSubscriber, LightWalletIndexer, NamedAtomicStatus, StatusType, ZcashIndexer}; use zebra_rpc::server::{ cookie::{remove_from_disk, write_to_disk, Cookie}, @@ -21,7 +21,7 @@ use tracing::warn; /// JSON-RPC server capable of servicing clients over TCP. pub struct JsonRpcServer { /// Current status of the server. - pub status: AtomicStatus, + pub status: NamedAtomicStatus, /// JoinHandle for the servers `serve` task. pub server_handle: Option>>, /// Cookie dir. @@ -38,7 +38,7 @@ impl JsonRpcServer { service_subscriber: IndexerSubscriber, server_config: JsonRpcServerConfig, ) -> Result { - let status = AtomicStatus::new(StatusType::Spawning); + let status = NamedAtomicStatus::new("JSON-RPC", StatusType::Spawning); let rpc_impl = JsonRpcClient { service_subscriber: service_subscriber.clone(), diff --git a/zaino-state/src/backends/fetch.rs b/zaino-state/src/backends/fetch.rs index 95c186546..024d2c88b 100644 --- a/zaino-state/src/backends/fetch.rs +++ b/zaino-state/src/backends/fetch.rs @@ -5,7 +5,7 @@ use hex::FromHex; use std::{io::Cursor, time}; use tokio::{sync::mpsc, time::timeout}; use tonic::async_trait; -use tracing::{info, warn}; +use tracing::{info, instrument, warn}; use zebra_state::HashOrHeight; use zebra_chain::{ @@ -113,8 +113,13 @@ impl ZcashService for FetchService { type Config = FetchServiceConfig; /// Initializes a new FetchService instance and starts sync process. + #[instrument(name = "FetchService::spawn", skip(config), fields(network = %config.network))] async fn spawn(config: FetchServiceConfig) -> Result { - info!("Launching Chain Fetch Service.."); + info!( + rpc_address = %config.validator_rpc_address, + network = %config.network, + "Launching Fetch Service" + ); let fetcher = JsonRpSeeConnector::new_from_config_parts( &config.validator_rpc_address, @@ -131,7 +136,7 @@ impl ZcashService for FetchService { zebra_build_data.build, zebra_build_data.subversion, ); - info!("Using Zcash build: {}", data); + info!(build = %data.zebra_build(), subversion = %data.zebra_subversion(), "Connected to Zcash node"); let source = ValidatorConnector::Fetch(fetcher.clone()); let indexer = NodeBackedChainIndex::new(source, config.clone().into()) @@ -518,7 +523,7 @@ impl ZcashIndexer for FetchServiceSubscriber { .get_mempool_txids() .await? .iter() - .map(|txid| txid.to_string()) + .map(|txid| txid.to_rpc_hex()) .collect()) } diff --git a/zaino-state/src/backends/state.rs b/zaino-state/src/backends/state.rs index b1b4423a8..561658628 100644 --- a/zaino-state/src/backends/state.rs +++ b/zaino-state/src/backends/state.rs @@ -13,7 +13,7 @@ use crate::{ indexer::{ handle_raw_transaction, IndexerSubscriber, LightWalletIndexer, ZcashIndexer, ZcashService, }, - status::{AtomicStatus, Status, StatusType}, + status::{NamedAtomicStatus, Status, StatusType}, stream::{ AddressStream, CompactBlockStream, CompactTransactionStream, RawTransactionStream, UtxoReplyStream, @@ -91,7 +91,7 @@ use tokio::{ }; use tonic::async_trait; use tower::{Service, ServiceExt}; -use tracing::{info, warn}; +use tracing::{info, instrument, warn}; macro_rules! expected_read_response { ($response:ident, $expected_variant:ident) => { @@ -141,7 +141,7 @@ pub struct StateService { data: ServiceMetadata, /// Thread-safe status indicator. - status: AtomicStatus, + status: NamedAtomicStatus, } impl StateService { @@ -172,8 +172,13 @@ impl ZcashService for StateService { type Config = StateServiceConfig; /// Initializes a new StateService instance and starts sync process. + #[instrument(name = "StateService::spawn", skip(config), fields(network = %config.network))] async fn spawn(config: StateServiceConfig) -> Result { - info!("Spawning State Service.."); + info!( + rpc_address = %config.validator_rpc_address, + network = %config.network, + "Spawning State Service" + ); let rpc_client = JsonRpSeeConnector::new_from_config_parts( &config.validator_rpc_address, @@ -218,10 +223,12 @@ impl ZcashService for StateService { zebra_build_data.build, zebra_build_data.subversion, ); - info!("Using Zcash build: {}", data); + info!(build = %data.zebra_build(), subversion = %data.zebra_subversion(), "Connected to Zcash node"); - info!("Launching Chain Syncer.."); - info!("{}", config.validator_rpc_address); + info!( + grpc_address = %config.validator_grpc_address, + "Launching Chain Syncer" + ); let (mut read_state_service, _latest_chain_tip, chain_tip_change, sync_task_handle) = init_read_state_with_syncer( config.validator_state_config.clone(), @@ -230,29 +237,29 @@ impl ZcashService for StateService { ) .await??; - info!("chain syncer launched!"); + info!("Chain syncer launched"); // Wait for ReadStateService to catch up to primary database: loop { let server_height = rpc_client.get_blockchain_info().await?.blocks; - info!("got blockchain info!"); let syncer_response = read_state_service .ready() .and_then(|service| service.call(ReadRequest::Tip)) .await?; - info!("got tip!"); let (syncer_height, _) = expected_read_response!(syncer_response, Tip).ok_or( RpcError::new_from_legacycode(LegacyCode::Misc, "no blocks in chain"), )?; if server_height.0 == syncer_height.0 { + info!(height = syncer_height.0, "ReadStateService synced with Zebra"); break; } else { - info!(" - ReadStateService syncing with Zebra. Syncer chain height: {}, Validator chain height: {}", - &syncer_height.0, - &server_height.0 - ); + info!( + syncer_height = syncer_height.0, + validator_height = server_height.0, + "ReadStateService syncing with Zebra" + ); tokio::time::sleep(std::time::Duration::from_millis(1000)).await; continue; } @@ -286,7 +293,7 @@ impl ZcashService for StateService { indexer: chain_index, data, config, - status: AtomicStatus::new(StatusType::Spawning), + status: NamedAtomicStatus::new("StateService", StatusType::Spawning), }; // wait for sync to complete, return error on sync fail. @@ -1460,7 +1467,7 @@ impl ZcashIndexer for StateServiceSubscriber { .get_mempool_txids() .await? .into_iter() - .map(|txid| txid.to_string()) + .map(|txid| txid.to_rpc_hex()) .collect()) } diff --git a/zaino-state/src/chain_index.rs b/zaino-state/src/chain_index.rs index cba7ac69f..c69794a33 100644 --- a/zaino-state/src/chain_index.rs +++ b/zaino-state/src/chain_index.rs @@ -17,7 +17,7 @@ use crate::chain_index::types::db::metadata::MempoolInfo; use crate::chain_index::types::{BestChainLocation, NonBestChainLocation}; use crate::error::{ChainIndexError, ChainIndexErrorKind, FinalisedStateError}; use crate::status::Status; -use crate::{AtomicStatus, CompactBlockStream, NodeConnectionError, StatusType, SyncError}; +use crate::{NamedAtomicStatus, CompactBlockStream, NodeConnectionError, StatusType, SyncError}; use crate::{IndexedBlock, TransactionHash}; use std::collections::HashSet; use std::{sync::Arc, time::Duration}; @@ -27,7 +27,7 @@ use hex::FromHex as _; use non_finalised_state::NonfinalizedBlockCacheSnapshot; use source::{BlockchainSource, ValidatorConnector}; use tokio_stream::StreamExt; -use tracing::info; +use tracing::{info, instrument}; use zaino_proto::proto::utils::{compact_block_with_pool_types, PoolTypeFilter}; use zebra_chain::parameters::ConsensusBranchId; pub use zebra_chain::parameters::Network as ZebraNetwork; @@ -457,7 +457,7 @@ pub struct NodeBackedChainIndex { non_finalized_state: std::sync::Arc>, finalized_db: std::sync::Arc, sync_loop_handle: Option>>, - status: AtomicStatus, + status: NamedAtomicStatus, } impl NodeBackedChainIndex { @@ -494,7 +494,7 @@ impl NodeBackedChainIndex { non_finalized_state: std::sync::Arc::new(non_finalized_state), finalized_db, sync_loop_handle: None, - status: AtomicStatus::new(StatusType::Spawning), + status: NamedAtomicStatus::new("ChainIndex", StatusType::Spawning), }; chain_index.sync_loop_handle = Some(chain_index.start_sync_loop()); @@ -535,8 +535,9 @@ impl NodeBackedChainIndex { combined_status } + #[instrument(name = "ChainIndex::start_sync_loop", skip(self))] pub(super) fn start_sync_loop(&self) -> tokio::task::JoinHandle> { - info!("Starting ChainIndex sync."); + info!("Starting ChainIndex sync loop"); let nfs = self.non_finalized_state.clone(); let fs = self.finalized_db.clone(); let status = self.status.clone(); @@ -615,7 +616,7 @@ pub struct NodeBackedChainIndexSubscriber>, finalized_state: finalised_state::reader::DbReader, - status: AtomicStatus, + status: NamedAtomicStatus, } impl NodeBackedChainIndexSubscriber { @@ -1217,7 +1218,7 @@ impl ChainIndex for NodeBackedChainIndexSubscriber ChainIndex for NodeBackedChainIndexSubscriber( cfg: BlockCacheConfig, source: T, @@ -305,7 +306,7 @@ impl ZainoDB { let backend = match version_opt { Some(version) => { - info!("Opening ZainoDBv{} from file.", version); + info!(version, "Opening ZainoDB from file"); match version { 0 => DbBackend::spawn_v0(&cfg).await?, 1 => DbBackend::spawn_v1(&cfg).await?, @@ -317,7 +318,7 @@ impl ZainoDB { } } None => { - info!("Creating new ZainoDBv{}.", target_version); + info!(version = %target_version, "Creating new ZainoDB"); match target_version.major() { 0 => DbBackend::spawn_v0(&cfg).await?, 1 => DbBackend::spawn_v1(&cfg).await?, @@ -335,8 +336,9 @@ impl ZainoDB { if version_opt.is_some() && current_version < target_version { info!( - "Starting ZainoDB migration manager, migratiing database from v{} to v{}.", - current_version, target_version + from_version = %current_version, + to_version = %target_version, + "Starting ZainoDB migration" ); let mut migration_manager = MigrationManager { router: Arc::clone(&router), diff --git a/zaino-state/src/chain_index/finalised_state/db/v0.rs b/zaino-state/src/chain_index/finalised_state/db/v0.rs index 525b0c9ee..5d9efcc80 100644 --- a/zaino-state/src/chain_index/finalised_state/db/v0.rs +++ b/zaino-state/src/chain_index/finalised_state/db/v0.rs @@ -49,7 +49,7 @@ use crate::{ }, config::BlockCacheConfig, error::FinalisedStateError, - status::{AtomicStatus, StatusType}, + status::{NamedAtomicStatus, StatusType}, CompactBlockStream, Height, IndexedBlock, }; @@ -255,7 +255,7 @@ pub struct DbV0 { db_handler: Option>, /// Backend lifecycle status. - status: AtomicStatus, + status: NamedAtomicStatus, /// Configuration snapshot used for path/network selection and sizing parameters. config: BlockCacheConfig, @@ -319,7 +319,7 @@ impl DbV0 { heights_to_hashes, hashes_to_blocks, db_handler: None, - status: AtomicStatus::new(StatusType::Spawning), + status: NamedAtomicStatus::new("ZainoDB", StatusType::Spawning), config: config.clone(), }; diff --git a/zaino-state/src/chain_index/finalised_state/db/v1.rs b/zaino-state/src/chain_index/finalised_state/db/v1.rs index 25abad116..db36cfcad 100644 --- a/zaino-state/src/chain_index/finalised_state/db/v1.rs +++ b/zaino-state/src/chain_index/finalised_state/db/v1.rs @@ -37,9 +37,9 @@ use crate::{ }, config::BlockCacheConfig, error::FinalisedStateError, - AtomicStatus, BlockHash, BlockHeaderData, CommitmentTreeData, CompactBlockStream, - CompactOrchardAction, CompactSaplingOutput, CompactSaplingSpend, CompactSize, CompactTxData, - FixedEncodedLen as _, Height, IndexedBlock, OrchardCompactTx, OrchardTxList, SaplingCompactTx, + BlockHash, BlockHeaderData, CommitmentTreeData, CompactBlockStream, CompactOrchardAction, + CompactSaplingOutput, CompactSaplingSpend, CompactSize, CompactTxData, FixedEncodedLen as _, + Height, IndexedBlock, NamedAtomicStatus, OrchardCompactTx, OrchardTxList, SaplingCompactTx, SaplingTxList, StatusType, TransparentCompactTx, TransparentTxList, TxInCompact, TxLocation, TxOutCompact, TxidList, ZainoVersionedSerde as _, }; @@ -248,7 +248,7 @@ pub(crate) struct DbV1 { db_handler: Option>, /// ZainoDB status. - status: AtomicStatus, + status: NamedAtomicStatus, /// BlockCache config data. config: BlockCacheConfig, @@ -353,7 +353,7 @@ impl DbV1 { validated_tip: Arc::new(AtomicU32::new(0)), validated_set: DashSet::new(), db_handler: None, - status: AtomicStatus::new(StatusType::Spawning), + status: NamedAtomicStatus::new("ZainoDB", StatusType::Spawning), config: config.clone(), }; } @@ -373,7 +373,7 @@ impl DbV1 { validated_tip: Arc::new(AtomicU32::new(0)), validated_set: DashSet::new(), db_handler: None, - status: AtomicStatus::new(StatusType::Spawning), + status: NamedAtomicStatus::new("ZainoDB", StatusType::Spawning), config: config.clone(), }; } diff --git a/zaino-state/src/chain_index/mempool.rs b/zaino-state/src/chain_index/mempool.rs index 2a8bdc6f5..235706ce9 100644 --- a/zaino-state/src/chain_index/mempool.rs +++ b/zaino-state/src/chain_index/mempool.rs @@ -9,10 +9,10 @@ use crate::{ types::db::metadata::MempoolInfo, }, error::{MempoolError, StatusError}, - status::{AtomicStatus, StatusType}, + status::{NamedAtomicStatus, StatusType}, BlockHash, }; -use tracing::{info, warn}; +use tracing::{info, instrument, warn}; use zaino_fetch::jsonrpsee::response::GetMempoolInfoResponse; use zebra_chain::{block::Hash, transaction::SerializedTransaction}; @@ -50,11 +50,12 @@ pub struct Mempool { /// Mempool sync handle. sync_task_handle: Option>>, /// mempool status. - status: AtomicStatus, + status: NamedAtomicStatus, } impl Mempool { /// Spawns a new [`Mempool`]. + #[instrument(name = "Mempool::spawn", skip(fetcher, capacity_and_shard_amount))] pub async fn spawn( fetcher: T, capacity_and_shard_amount: Option<(usize, usize)>, @@ -66,7 +67,7 @@ impl Mempool { break; } Err(_) => { - info!(" - Waiting for Validator mempool to come online.."); + info!("Waiting for Validator mempool to come online"); tokio::time::sleep(std::time::Duration::from_secs(3)).await; } } @@ -90,7 +91,7 @@ impl Mempool { let (chain_tip_sender, _chain_tip_reciever) = tokio::sync::watch::channel(best_block_hash); - info!("Launching Mempool.."); + info!(chain_tip = %best_block_hash, "Launching Mempool"); let mut mempool = Mempool { fetcher: fetcher.clone(), state: match capacity_and_shard_amount { @@ -101,7 +102,7 @@ impl Mempool { }, mempool_chain_tip: chain_tip_sender, sync_task_handle: None, - status: AtomicStatus::new(StatusType::Spawning), + status: NamedAtomicStatus::new("Mempool", StatusType::Spawning), }; loop { @@ -360,7 +361,7 @@ pub struct MempoolSubscriber { subscriber: BroadcastSubscriber, seen_txids: HashSet, mempool_chain_tip: tokio::sync::watch::Receiver, - status: AtomicStatus, + status: NamedAtomicStatus, } impl MempoolSubscriber { diff --git a/zaino-state/src/chain_index/non_finalised_state.rs b/zaino-state/src/chain_index/non_finalised_state.rs index 884423a8b..cebf58b29 100644 --- a/zaino-state/src/chain_index/non_finalised_state.rs +++ b/zaino-state/src/chain_index/non_finalised_state.rs @@ -9,7 +9,7 @@ use futures::lock::Mutex; use primitive_types::U256; use std::{collections::HashMap, sync::Arc}; use tokio::sync::mpsc; -use tracing::{info, warn}; +use tracing::{info, instrument, warn}; use zebra_chain::{parameters::Network, serialization::BytesInDisplayOrder}; use zebra_state::HashOrHeight; @@ -223,12 +223,13 @@ impl NonFinalizedState { /// TODO: Currently, we can't initate without an snapshot, we need to create a cache /// of at least one block. Should this be tied to the instantiation of the data structure /// itself? + #[instrument(name = "NonFinalizedState::initialize", skip(source, start_block), fields(network = %network))] pub async fn initialize( source: Source, network: Network, start_block: Option, ) -> Result { - info!("Initialising non-finalised state."); + info!(network = %network, "Initializing non-finalized state"); let validator_tip = source .get_best_block_height() @@ -333,6 +334,7 @@ impl NonFinalizedState { } /// sync to the top of the chain, trimming to the finalised tip. + #[instrument(name = "NonFinalizedState::sync", skip(self, finalized_db))] pub(super) async fn sync(&self, finalized_db: Arc) -> Result<(), SyncError> { let mut initial_state = self.get_snapshot(); let local_finalized_tip = finalized_db.to_reader().db_height().await?; @@ -394,9 +396,9 @@ impl NonFinalizedState { })?; let chainblock = self.block_to_chainblock(prev_block, &block).await?; info!( - "syncing block {} at height {}", - &chainblock.index().hash(), - working_snapshot.best_tip.height + 1 + height = (working_snapshot.best_tip.height + 1).0, + hash = %chainblock.index().hash(), + "Syncing block" ); working_snapshot.add_block_new_chaintip(chainblock); } else { @@ -556,26 +558,28 @@ impl NonFinalizedState { if new_best_tip != stale_best_tip { if new_best_tip.height > stale_best_tip.height { info!( - "non-finalized tip advanced: Height: {} -> {}, Hash: {} -> {}", - stale_best_tip.height, - new_best_tip.height, - stale_best_tip.blockhash, - new_best_tip.blockhash, + old_height = stale_best_tip.height.0, + new_height = new_best_tip.height.0, + old_hash = %stale_best_tip.blockhash, + new_hash = %new_best_tip.blockhash, + "Non-finalized tip advanced" ); } else if new_best_tip.height == stale_best_tip.height && new_best_tip.blockhash != stale_best_tip.blockhash { info!( - "non-finalized tip reorg at height {}: Hash: {} -> {}", - new_best_tip.height, stale_best_tip.blockhash, new_best_tip.blockhash, + height = new_best_tip.height.0, + old_hash = %stale_best_tip.blockhash, + new_hash = %new_best_tip.blockhash, + "Non-finalized tip reorg" ); } else if new_best_tip.height < stale_best_tip.height { info!( - "non-finalized tip rollback from height {} to {}, Hash: {} -> {}", - stale_best_tip.height, - new_best_tip.height, - stale_best_tip.blockhash, - new_best_tip.blockhash, + old_height = stale_best_tip.height.0, + new_height = new_best_tip.height.0, + old_hash = %stale_best_tip.blockhash, + new_hash = %new_best_tip.blockhash, + "Non-finalized tip rollback" ); } } diff --git a/zaino-state/src/chain_index/source.rs b/zaino-state/src/chain_index/source.rs index 3c408fe8a..ba89254a1 100644 --- a/zaino-state/src/chain_index/source.rs +++ b/zaino-state/src/chain_index/source.rs @@ -239,7 +239,7 @@ impl BlockchainSource for ValidatorConnector { } ValidatorConnector::Fetch(fetch) => { let tree_responses = fetch - .get_treestate(id.to_string()) + .get_treestate(id.to_rpc_hex()) .await // As MethodError contains a GetTreestateError, which is an enum with no variants, // we don't need to account for it at all here @@ -532,7 +532,7 @@ impl BlockchainSource for ValidatorConnector { ValidatorConnector::Fetch(fetch) => { let transaction_object = if let GetTransactionResponse::Object(transaction_object) = fetch - .get_raw_transaction(txid.to_string(), Some(1)) + .get_raw_transaction(txid.to_rpc_hex(), Some(1)) .await .map_err(|e| { BlockchainSourceError::Unrecoverable(format!( diff --git a/zaino-state/src/chain_index/tests/finalised_state/v1.rs b/zaino-state/src/chain_index/tests/finalised_state/v1.rs index 889290126..1fd1fcd57 100644 --- a/zaino-state/src/chain_index/tests/finalised_state/v1.rs +++ b/zaino-state/src/chain_index/tests/finalised_state/v1.rs @@ -3,6 +3,7 @@ use std::path::PathBuf; use tempfile::TempDir; +use hex::ToHex; use zaino_common::network::ActivationHeights; use zaino_common::{DatabaseConfig, Network, StorageConfig}; use zaino_proto::proto::utils::{compact_block_with_pool_types, PoolTypeFilter}; @@ -579,7 +580,7 @@ async fn get_faucet_txids() { let block_txids: Vec = chain_block .transactions() .iter() - .map(|tx_data| tx_data.txid().to_string()) + .map(|tx_data| tx_data.txid().encode_hex::()) .collect(); let filtered_block_txids: Vec = block_txids .into_iter() @@ -595,7 +596,7 @@ async fn get_faucet_txids() { let mut reader_block_txids = Vec::new(); for tx_location in reader_faucet_tx_locations { let txid = db_reader.get_txid(tx_location).await.unwrap(); - reader_block_txids.push(txid.to_string()); + reader_block_txids.push(txid.encode_hex::()); } dbg!(&reader_block_txids); @@ -612,7 +613,7 @@ async fn get_faucet_txids() { let mut reader_faucet_txids = Vec::new(); for tx_location in reader_faucet_tx_locations { let txid = db_reader.get_txid(tx_location).await.unwrap(); - reader_faucet_txids.push(txid.to_string()); + reader_faucet_txids.push(txid.encode_hex::()); } assert_eq!(faucet.txids.len(), reader_faucet_txids.len()); @@ -687,7 +688,7 @@ async fn get_recipient_txids() { let block_txids: Vec = chain_block .transactions() .iter() - .map(|tx_data| tx_data.txid().to_string()) + .map(|tx_data| tx_data.txid().encode_hex::()) .collect(); // Get block txids that are relevant to recipient. @@ -708,7 +709,7 @@ async fn get_recipient_txids() { let mut reader_block_txids = Vec::new(); for tx_location in reader_recipient_tx_locations { let txid = db_reader.get_txid(tx_location).await.unwrap(); - reader_block_txids.push(txid.to_string()); + reader_block_txids.push(txid.encode_hex::()); } dbg!(&reader_block_txids); @@ -726,7 +727,7 @@ async fn get_recipient_txids() { let mut reader_recipient_txids = Vec::new(); for tx_location in reader_recipient_tx_locations { let txid = db_reader.get_txid(tx_location).await.unwrap(); - reader_recipient_txids.push(txid.to_string()); + reader_recipient_txids.push(txid.encode_hex::()); } assert_eq!(recipient.txids.len(), reader_recipient_txids.len()); @@ -753,7 +754,7 @@ async fn get_faucet_utxos() { for utxo in faucet.utxos.iter() { let (_faucet_address, txid, output_index, _faucet_script, satoshis, _height) = utxo.into_parts(); - cleaned_utxos.push((txid.to_string(), output_index.index(), satoshis)); + cleaned_utxos.push((txid.encode_hex::(), output_index.index(), satoshis)); } let reader_faucet_utxo_indexes = db_reader @@ -765,7 +766,7 @@ async fn get_faucet_utxos() { let mut reader_faucet_utxos = Vec::new(); for (tx_location, vout, value) in reader_faucet_utxo_indexes { - let txid = db_reader.get_txid(tx_location).await.unwrap().to_string(); + let txid = db_reader.get_txid(tx_location).await.unwrap().encode_hex::(); reader_faucet_utxos.push((txid, vout as u32, value)); } @@ -799,7 +800,7 @@ async fn get_recipient_utxos() { for utxo in recipient.utxos.iter() { let (_recipient_address, txid, output_index, _recipient_script, satoshis, _height) = utxo.into_parts(); - cleaned_utxos.push((txid.to_string(), output_index.index(), satoshis)); + cleaned_utxos.push((txid.encode_hex::(), output_index.index(), satoshis)); } let reader_recipient_utxo_indexes = db_reader @@ -811,7 +812,7 @@ async fn get_recipient_utxos() { let mut reader_recipient_utxos = Vec::new(); for (tx_location, vout, value) in reader_recipient_utxo_indexes { - let txid = db_reader.get_txid(tx_location).await.unwrap().to_string(); + let txid = db_reader.get_txid(tx_location).await.unwrap().encode_hex::(); reader_recipient_utxos.push((txid, vout as u32, value)); } @@ -941,7 +942,7 @@ async fn check_faucet_spent_map() { for utxo in faucet.utxos.iter() { let (_faucet_address, txid, output_index, _faucet_script, _satoshis, _height) = utxo.into_parts(); - faucet_utxo_indexes.push((txid.to_string(), output_index.index())); + faucet_utxo_indexes.push((txid.encode_hex::(), output_index.index())); } // check full spent outpoints map @@ -956,7 +957,7 @@ async fn check_faucet_spent_map() { .zip(faucet_ouptpoints_spent_status.iter()) { let outpoint_tuple = ( - TransactionHash::from(*outpoint.prev_txid()).to_string(), + TransactionHash::from(*outpoint.prev_txid()).encode_hex::(), outpoint.prev_index(), ); match spender_option { @@ -1111,7 +1112,7 @@ async fn check_recipient_spent_map() { for utxo in recipient.utxos.iter() { let (_recipient_address, txid, output_index, _recipient_script, _satoshis, _height) = utxo.into_parts(); - recipient_utxo_indexes.push((txid.to_string(), output_index.index())); + recipient_utxo_indexes.push((txid.encode_hex::(), output_index.index())); } // check full spent outpoints map @@ -1126,7 +1127,7 @@ async fn check_recipient_spent_map() { .zip(recipient_ouptpoints_spent_status.iter()) { let outpoint_tuple = ( - TransactionHash::from(*outpoint.prev_txid()).to_string(), + TransactionHash::from(*outpoint.prev_txid()).encode_hex::(), outpoint.prev_index(), ); match spender_option { diff --git a/zaino-state/src/chain_index/types/db/legacy.rs b/zaino-state/src/chain_index/types/db/legacy.rs index a46d859e6..4ece372d1 100644 --- a/zaino-state/src/chain_index/types/db/legacy.rs +++ b/zaino-state/src/chain_index/types/db/legacy.rs @@ -69,11 +69,28 @@ impl BlockHash { BlockHash(internal_byte_order) } + + /// Full hex string (big-endian / display order) for use in RPC interfaces. + /// + /// Unlike [`Display`], which is truncated for log readability, this always + /// returns the complete 64-character hex string required by RPC consumers. + /// + /// HACK: ad-hoc method to decouple serialisation from `Display` so PR #888 + /// can land cleanly. The proper destination-specific API is tracked in #640. + pub fn to_rpc_hex(&self) -> String { + self.encode_hex() + } } impl fmt::Display for BlockHash { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.write_str(&self.encode_hex::()) + // Show truncated hash for cleaner logs (first 8 hex chars = 4 bytes) + let full_hex: String = self.encode_hex(); + if full_hex.len() > 8 { + write!(f, "{}..", &full_hex[..8]) + } else { + f.write_str(&full_hex) + } } } @@ -204,11 +221,28 @@ impl TransactionHash { TransactionHash(internal_byte_order) } + + /// Full hex string (big-endian / display order) for use in RPC interfaces. + /// + /// Unlike [`Display`], which is truncated for log readability, this always + /// returns the complete 64-character hex string required by RPC consumers. + /// + /// HACK: ad-hoc method to decouple serialisation from `Display` so PR #888 + /// can land cleanly. The proper destination-specific API is tracked in #640. + pub fn to_rpc_hex(&self) -> String { + self.encode_hex() + } } impl fmt::Display for TransactionHash { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.write_str(&self.encode_hex::()) + // Show truncated hash for cleaner logs (first 8 hex chars = 4 bytes) + let full_hex: String = self.encode_hex(); + if full_hex.len() > 8 { + write!(f, "{}..", &full_hex[..8]) + } else { + f.write_str(&full_hex) + } } } diff --git a/zaino-state/src/lib.rs b/zaino-state/src/lib.rs index a4c7138ea..258c579fe 100644 --- a/zaino-state/src/lib.rs +++ b/zaino-state/src/lib.rs @@ -77,7 +77,7 @@ pub use error::{FetchServiceError, StateServiceError}; pub(crate) mod status; -pub use status::{AtomicStatus, Status, StatusType}; +pub use status::{AtomicStatus, NamedAtomicStatus, Status, StatusType}; pub(crate) mod stream; diff --git a/zaino-state/src/status.rs b/zaino-state/src/status.rs index c92b67d59..1afe177e9 100644 --- a/zaino-state/src/status.rs +++ b/zaino-state/src/status.rs @@ -1,12 +1,15 @@ //! Thread-safe status wrapper. //! -//! This module provides [`AtomicStatus`], a thread-safe wrapper for [`StatusType`]. +//! This module provides [`AtomicStatus`], a thread-safe wrapper for [`StatusType`], +//! and [`NamedAtomicStatus`], a variant that logs status transitions. use std::sync::{ atomic::{AtomicUsize, Ordering}, Arc, }; +use tracing::debug; + pub use zaino_common::status::{Status, StatusType}; /// Holds a thread-safe representation of a [`StatusType`]. @@ -39,3 +42,54 @@ impl Status for AtomicStatus { self.load() } } + +/// Thread-safe status wrapper with component name for observability. +/// +/// Unlike [`AtomicStatus`], this variant logs all status transitions, +/// making it easier to trace component lifecycle during debugging. +#[derive(Debug, Clone)] +pub struct NamedAtomicStatus { + name: &'static str, + inner: Arc, +} + +impl NamedAtomicStatus { + /// Creates a new NamedAtomicStatus with the given component name and initial status. + pub fn new(name: &'static str, status: StatusType) -> Self { + debug!(component = name, status = %status, "[STATUS] initial"); + Self { + name, + inner: Arc::new(AtomicUsize::new(status.into())), + } + } + + /// Returns the component name. + pub fn name(&self) -> &'static str { + self.name + } + + /// Loads the value held in the NamedAtomicStatus. + pub fn load(&self) -> StatusType { + StatusType::from(self.inner.load(Ordering::SeqCst)) + } + + /// Sets the value held in the NamedAtomicStatus, logging the transition. + pub fn store(&self, status: StatusType) { + let old = self.load(); + if old != status { + debug!( + component = self.name, + from = %old, + to = %status, + "[STATUS] transition" + ); + } + self.inner.store(status.into(), Ordering::SeqCst); + } +} + +impl Status for NamedAtomicStatus { + fn status(&self) -> StatusType { + self.load() + } +} diff --git a/zaino-testutils/src/lib.rs b/zaino-testutils/src/lib.rs index 7c35eb1c5..dc7241e54 100644 --- a/zaino-testutils/src/lib.rs +++ b/zaino-testutils/src/lib.rs @@ -16,8 +16,7 @@ use std::{ net::{IpAddr, Ipv4Addr, SocketAddr}, path::PathBuf, }; -use tracing::info; -use tracing_subscriber::EnvFilter; +use tracing::{debug, info, instrument}; use zaino_common::{ network::{ActivationHeights, ZEBRAD_DEFAULT_ACTIVATION_HEIGHTS}, probing::{Liveness, Readiness}, @@ -71,12 +70,14 @@ pub fn make_uri(indexer_port: portpicker::Port) -> http::Uri { /// /// Returns `true` if the component became ready within the timeout, /// `false` if the timeout was reached. +#[instrument(name = "poll_until_ready", skip(component), fields(timeout_ms = timeout.as_millis() as u64))] pub async fn poll_until_ready( component: &impl Readiness, poll_interval: std::time::Duration, timeout: std::time::Duration, ) -> bool { - tokio::time::timeout(timeout, async { + debug!("[POLL] Waiting for component to be ready"); + let result = tokio::time::timeout(timeout, async { let mut interval = tokio::time::interval(poll_interval); loop { interval.tick().await; @@ -86,7 +87,13 @@ pub async fn poll_until_ready( } }) .await - .is_ok() + .is_ok(); + if result { + debug!("[POLL] Component is ready"); + } else { + debug!("[POLL] Timeout waiting for component"); + } + result } // temporary until activation heights are unified to zebra-chain type. @@ -158,7 +165,7 @@ pub static ZEBRAD_TESTNET_CACHE_DIR: Lazy> = Lazy::new(|| { Some(home_path.join(".cache/zebra")) }); -#[derive(PartialEq, Clone, Copy)] +#[derive(Debug, PartialEq, Clone, Copy)] /// Represents the type of validator to launch. pub enum ValidatorKind { /// Zcashd. @@ -308,6 +315,11 @@ where /// TODO: Add TestManagerConfig struct and constructor methods of common test setups. /// /// TODO: Remove validator argument in favour of adding C::VALIDATOR associated const + #[instrument( + name = "TestManager::launch", + skip(activation_heights, chain_cache), + fields(validator = ?validator, network = ?network, enable_zaino, enable_clients) + )] pub async fn launch( validator: &ValidatorKind, network: Option, @@ -322,13 +334,7 @@ where "Cannot use state backend with zcashd.", )); } - let _ = tracing_subscriber::fmt() - .with_env_filter( - EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info")), - ) - .with_timer(tracing_subscriber::fmt::time::UtcTime::rfc_3339()) - .with_target(true) - .try_init(); + zaino_common::logging::try_init(); let activation_heights = activation_heights.unwrap_or_else(|| match validator { ValidatorKind::Zcashd => ActivationHeights::default(), @@ -357,10 +363,15 @@ where chain_cache.clone(), ); + debug!("[TEST] Launching validator"); let (local_net, validator_settings) = C::launch_validator_and_return_config(config) .await .expect("to launch a default validator"); let rpc_listen_port = local_net.get_port(); + debug!( + rpc_port = rpc_listen_port, + "[TEST] Validator launched" + ); let full_node_rpc_listen_address = SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), rpc_listen_port); @@ -386,7 +397,11 @@ where let zaino_json_listen_port = portpicker::pick_unused_port().expect("No ports free"); let zaino_json_listen_address = SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), zaino_json_listen_port); - info!("{:?}", validator_settings.validator_grpc_listen_address); + debug!( + grpc_address = %zaino_grpc_listen_address, + json_address = %zaino_json_listen_address, + "[TEST] Launching Zaino indexer" + ); let indexer_config = zainodlib::config::ZainodConfig { // TODO: Make configurable. backend: Service::BACKEND_TYPE, @@ -402,7 +417,7 @@ where listen_address: zaino_grpc_listen_address, tls: None, }, - validator_settings: dbg!(validator_settings.clone()), + validator_settings: validator_settings.clone(), service: ServiceConfig::default(), storage: StorageConfig { cache: CacheConfig::default(), @@ -490,6 +505,7 @@ where // Wait for zaino to be ready to serve requests if let Some(ref subscriber) = test_manager.service_subscriber { + debug!("[TEST] Waiting for Zaino to be ready"); poll_until_ready( subscriber, std::time::Duration::from_millis(100), @@ -498,6 +514,7 @@ where .await; } + debug!("[TEST] Test environment ready"); Ok(test_manager) } @@ -685,9 +702,12 @@ impl Drop for TestManager { fn drop(&mut self) { + debug!("[TEST] Shutting down test environment"); if let Some(handle) = &self.zaino_handle { + debug!("[TEST] Aborting Zaino handle"); handle.abort(); }; + debug!("[TEST] Test environment shutdown complete"); } } diff --git a/zainod/src/indexer.rs b/zainod/src/indexer.rs index cc4154f8b..1e66d02ff 100644 --- a/zainod/src/indexer.rs +++ b/zainod/src/indexer.rs @@ -32,7 +32,7 @@ pub async fn start_indexer( config: ZainodConfig, ) -> Result>, IndexerError> { startup_message(); - info!("Starting Zaino.."); + info!("Starting Zaino"); spawn_indexer(config).await } @@ -41,7 +41,10 @@ pub async fn spawn_indexer( config: ZainodConfig, ) -> Result>, IndexerError> { config.check_config()?; - info!("Checking connection with node.."); + info!( + address = %config.validator_settings.validator_jsonrpc_listen_address, + "Checking connection with node" + ); let zebrad_uri = test_node_and_return_url( &config.validator_settings.validator_jsonrpc_listen_address, config.validator_settings.validator_cookie_path.clone(), @@ -50,10 +53,7 @@ pub async fn spawn_indexer( ) .await?; - info!( - " - Connected to node using JsonRPSee at address {}.", - zebrad_uri - ); + info!(uri = %zebrad_uri, "Connected to node via JsonRPSee"); #[allow(deprecated)] match config.backend { diff --git a/zainod/src/lib.rs b/zainod/src/lib.rs index 5b6bb54fb..c6ee44cd2 100644 --- a/zainod/src/lib.rs +++ b/zainod/src/lib.rs @@ -6,8 +6,6 @@ use std::path::PathBuf; use tracing::{error, info}; -use tracing_subscriber::EnvFilter; - use crate::config::load_config; use crate::error::IndexerError; use crate::indexer::start_indexer; @@ -19,13 +17,13 @@ pub mod indexer; /// Run the Zaino indexer. /// -/// Initializes logging and runs the main indexer loop with restart support. +/// Runs the main indexer loop with restart support. +/// Logging should be initialized by the caller before calling this function. /// Returns an error if config loading or indexer startup fails. pub async fn run(config_path: PathBuf) -> Result<(), IndexerError> { - init_logging(); + zaino_common::logging::try_init(); info!("zainod v{}", env!("CARGO_PKG_VERSION")); - let config = load_config(&config_path)?; loop { @@ -60,14 +58,3 @@ pub async fn run(config_path: PathBuf) -> Result<(), IndexerError> { } } } - -/// Initialize the tracing subscriber for logging. -fn init_logging() { - tracing_subscriber::fmt() - .with_env_filter( - EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info")), - ) - .with_timer(tracing_subscriber::fmt::time::UtcTime::rfc_3339()) - .with_target(true) - .init(); -} diff --git a/zainod/src/main.rs b/zainod/src/main.rs index 843a1d346..660c564b8 100644 --- a/zainod/src/main.rs +++ b/zainod/src/main.rs @@ -6,6 +6,8 @@ use zainodlib::cli::{default_config_path, Cli, Command}; #[tokio::main] async fn main() { + zaino_common::logging::init(); + let cli = Cli::parse(); match cli.command {