@cryptotaxi247 / netdata-1 / commits / 8f048c802

Assortement of journal-viewer plugin fixes. (#21612)

* Add count of log entries without the field of the histogram. We need the histogram UI element to display not only the counts of the different values it takes in each bucket, but the overall count of log entries that do not contain the field used for the histogram. * Use raw value for dimension IDs in the histogram. This allows the UI to send follow-up requests with the correct information as stored in the journal files. * Add a separate variant for unaligned object access. * Add file-based telemetry check. Previously, we were checking only the DISABLE_TELEMETRY environment variable. However, we also support disabling telemetry through the `.opt-out-from-anonymous-statistics` file. * Remove sentry. * Install sigbus handler.

vkalintiris committed Jan 22, 2026 at 23:00 UTC 8f048c8029ccf46686044ba189778d6197d718e8
11 files changed +116 -639
src/crates/Cargo.lock
+16 -529
@@ -343,15 +343,6 @@ dependencies = [
343 "generic-array",
344 ]
345
346 -[[package]]
347 -name = "block2"
348 -version = "0.6.2"
349 -source = "registry+https://github.com/rust-lang/crates.io-index"
350 -checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5"
351 -dependencies = [
352 - "objc2",
353 -]
354 -
346 [[package]]
347 name = "bridge"
348 version = "0.1.1"
@@ -700,25 +691,6 @@ dependencies = [
691 "syn 1.0.109",
692 ]
693
703 -[[package]]
704 -name = "debugid"
705 -version = "0.8.0"
706 -source = "registry+https://github.com/rust-lang/crates.io-index"
707 -checksum = "bef552e6f588e446098f6ba40d89ac146c8c7b64aade83c051ee00bb5d2bc18d"
708 -dependencies = [
709 - "serde",
710 - "uuid",
711 -]
712 -
713 -[[package]]
714 -name = "deranged"
715 -version = "0.5.5"
716 -source = "registry+https://github.com/rust-lang/crates.io-index"
717 -checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587"
718 -dependencies = [
719 - "powerfmt",
720 -]
721 -
694 [[package]]
695 name = "digest"
696 version = "0.10.7"
@@ -729,16 +701,6 @@ dependencies = [
701 "crypto-common",
702 ]
703
732 -[[package]]
733 -name = "dispatch2"
734 -version = "0.3.0"
735 -source = "registry+https://github.com/rust-lang/crates.io-index"
736 -checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec"
737 -dependencies = [
738 - "bitflags 2.10.0",
739 - "objc2",
740 -]
741 -
704 [[package]]
705 name = "displaydoc"
706 version = "0.2.5"
@@ -914,7 +876,7 @@ dependencies = [
876 "mixtrics",
877 "pin-project",
878 "serde",
917 - "thiserror 2.0.17",
879 + "thiserror",
880 "tokio",
881 "tracing",
882 ]
@@ -934,7 +896,7 @@ dependencies = [
896 "parking_lot",
897 "pin-project",
898 "serde",
937 - "thiserror 2.0.17",
899 + "thiserror",
900 "tokio",
901 "twox-hash",
902 ]
@@ -967,7 +929,7 @@ dependencies = [
929 "parking_lot",
930 "pin-project",
931 "serde",
970 - "thiserror 2.0.17",
932 + "thiserror",
933 "tokio",
934 "tracing",
935 ]
@@ -1000,7 +962,7 @@ dependencies = [
962 "pin-project",
963 "rand 0.9.2",
964 "serde",
1003 - "thiserror 2.0.17",
965 + "thiserror",
966 "tokio",
967 "tracing",
968 "twox-hash",
@@ -1154,11 +1116,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1116 checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd"
1117 dependencies = [
1118 "cfg-if",
1157 - "js-sys",
1119 "libc",
1120 "r-efi",
1121 "wasip2",
1161 - "wasm-bindgen",
1122 ]
1123
1124 [[package]]
@@ -1251,23 +1211,6 @@ version = "0.5.2"
1211 source = "registry+https://github.com/rust-lang/crates.io-index"
1212 checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c"
1213
1254 -[[package]]
1255 -name = "hex"
1256 -version = "0.4.3"
1257 -source = "registry+https://github.com/rust-lang/crates.io-index"
1258 -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
1259 -
1260 -[[package]]
1261 -name = "hostname"
1262 -version = "0.4.2"
1263 -source = "registry+https://github.com/rust-lang/crates.io-index"
1264 -checksum = "617aaa3557aef3810a6369d0a99fac8a080891b68bd9f9812a1eeda0c0730cbd"
1265 -dependencies = [
1266 - "cfg-if",
1267 - "libc",
1268 - "windows-link",
1269 -]
1270 -
1214 [[package]]
1215 name = "http"
1216 version = "1.3.1"
@@ -1353,23 +1296,6 @@ dependencies = [
1296 "want",
1297 ]
1298
1356 -[[package]]
1357 -name = "hyper-rustls"
1358 -version = "0.27.7"
1359 -source = "registry+https://github.com/rust-lang/crates.io-index"
1360 -checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58"
1361 -dependencies = [
1362 - "http",
1363 - "hyper",
1364 - "hyper-util",
1365 - "rustls",
1366 - "rustls-pki-types",
1367 - "tokio",
1368 - "tokio-rustls",
1369 - "tower-service",
1370 - "webpki-roots 1.0.5",
1371 -]
1372 -
1299 [[package]]
1300 name = "hyper-timeout"
1301 version = "0.5.2"
@@ -1679,7 +1605,7 @@ dependencies = [
1605 "siphasher",
1606 "static_assertions",
1607 "tempfile",
1682 - "thiserror 2.0.17",
1608 + "thiserror",
1609 "tokio",
1610 "tracing",
1611 "tracing-subscriber",
@@ -1711,7 +1637,7 @@ dependencies = [
1637 "serde_json",
1638 "static_assertions",
1639 "tempfile",
1714 - "thiserror 2.0.17",
1640 + "thiserror",
1641 "tokio",
1642 "tracing",
1643 "tracing-subscriber",
@@ -1740,7 +1666,7 @@ dependencies = [
1666 "schemars",
1667 "serde",
1668 "serde_json",
1743 - "thiserror 2.0.17",
1669 + "thiserror",
1670 "tokio",
1671 "tracing",
1672 "tracing-subscriber",
@@ -1759,7 +1685,7 @@ dependencies = [
1685 "serde",
1686 "static_assertions",
1687 "tempfile",
1762 - "thiserror 2.0.17",
1688 + "thiserror",
1689 "tracing",
1690 "uuid",
1691 ]
@@ -1777,7 +1703,7 @@ dependencies = [
1703 "serde",
1704 "serde_json",
1705 "tempfile",
1780 - "thiserror 2.0.17",
1706 + "thiserror",
1707 "tracing",
1708 "uuid",
1709 ]
@@ -1791,7 +1717,7 @@ dependencies = [
1717 "notify",
1718 "parking_lot",
1719 "serde",
1794 - "thiserror 2.0.17",
1720 + "thiserror",
1721 "tokio",
1722 "tracing",
1723 "uuid",
@@ -1819,11 +1745,10 @@ dependencies = [
1745 "parking_lot",
1746 "rt",
1747 "schemars",
1822 - "sentry",
1748 "serde",
1749 "serde_json",
1750 "serde_yaml",
1826 - "thiserror 2.0.17",
1751 + "thiserror",
1752 "tokio",
1753 "tracing",
1754 ]
@@ -1906,12 +1831,6 @@ dependencies = [
1831 "hashbrown 0.16.0",
1832 ]
1833
1909 -[[package]]
1910 -name = "lru-slab"
1911 -version = "0.1.2"
1912 -source = "registry+https://github.com/rust-lang/crates.io-index"
1913 -checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154"
1914 -
1834 [[package]]
1835 name = "lz4"
1836 version = "1.28.1"
@@ -2125,7 +2044,7 @@ dependencies = [
2044 name = "netdata-plugin-error"
2045 version = "0.1.1"
2046 dependencies = [
2128 - "thiserror 2.0.17",
2047 + "thiserror",
2048 ]
2049
2050 [[package]]
@@ -2222,12 +2141,6 @@ dependencies = [
2141 "windows-sys 0.61.2",
2142 ]
2143
2225 -[[package]]
2226 -name = "num-conv"
2227 -version = "0.1.0"
2228 -source = "registry+https://github.com/rust-lang/crates.io-index"
2229 -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
2230 -
2144 [[package]]
2145 name = "num-traits"
2146 version = "0.2.19"
@@ -2247,165 +2160,6 @@ dependencies = [
2160 "libc",
2161 ]
2162
2250 -[[package]]
2251 -name = "objc2"
2252 -version = "0.6.3"
2253 -source = "registry+https://github.com/rust-lang/crates.io-index"
2254 -checksum = "b7c2599ce0ec54857b29ce62166b0ed9b4f6f1a70ccc9a71165b6154caca8c05"
2255 -dependencies = [
2256 - "objc2-encode",
2257 -]
2258 -
2259 -[[package]]
2260 -name = "objc2-cloud-kit"
2261 -version = "0.3.2"
2262 -source = "registry+https://github.com/rust-lang/crates.io-index"
2263 -checksum = "73ad74d880bb43877038da939b7427bba67e9dd42004a18b809ba7d87cee241c"
2264 -dependencies = [
2265 - "bitflags 2.10.0",
2266 - "objc2",
2267 - "objc2-foundation",
2268 -]
2269 -
2270 -[[package]]
2271 -name = "objc2-core-data"
2272 -version = "0.3.2"
2273 -source = "registry+https://github.com/rust-lang/crates.io-index"
2274 -checksum = "0b402a653efbb5e82ce4df10683b6b28027616a2715e90009947d50b8dd298fa"
2275 -dependencies = [
2276 - "objc2",
2277 - "objc2-foundation",
2278 -]
2279 -
2280 -[[package]]
2281 -name = "objc2-core-foundation"
2282 -version = "0.3.2"
2283 -source = "registry+https://github.com/rust-lang/crates.io-index"
2284 -checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536"
2285 -dependencies = [
2286 - "bitflags 2.10.0",
2287 - "dispatch2",
2288 - "objc2",
2289 -]
2290 -
2291 -[[package]]
2292 -name = "objc2-core-graphics"
2293 -version = "0.3.2"
2294 -source = "registry+https://github.com/rust-lang/crates.io-index"
2295 -checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807"
2296 -dependencies = [
2297 - "bitflags 2.10.0",
2298 - "dispatch2",
2299 - "objc2",
2300 - "objc2-core-foundation",
2301 - "objc2-io-surface",
2302 -]
2303 -
2304 -[[package]]
2305 -name = "objc2-core-image"
2306 -version = "0.3.2"
2307 -source = "registry+https://github.com/rust-lang/crates.io-index"
2308 -checksum = "e5d563b38d2b97209f8e861173de434bd0214cf020e3423a52624cd1d989f006"
2309 -dependencies = [
2310 - "objc2",
2311 - "objc2-foundation",
2312 -]
2313 -
2314 -[[package]]
2315 -name = "objc2-core-location"
2316 -version = "0.3.2"
2317 -source = "registry+https://github.com/rust-lang/crates.io-index"
2318 -checksum = "ca347214e24bc973fc025fd0d36ebb179ff30536ed1f80252706db19ee452009"
2319 -dependencies = [
2320 - "objc2",
2321 - "objc2-foundation",
2322 -]
2323 -
2324 -[[package]]
2325 -name = "objc2-core-text"
2326 -version = "0.3.2"
2327 -source = "registry+https://github.com/rust-lang/crates.io-index"
2328 -checksum = "0cde0dfb48d25d2b4862161a4d5fcc0e3c24367869ad306b0c9ec0073bfed92d"
2329 -dependencies = [
2330 - "bitflags 2.10.0",
2331 - "objc2",
2332 - "objc2-core-foundation",
2333 - "objc2-core-graphics",
2334 -]
2335 -
2336 -[[package]]
2337 -name = "objc2-encode"
2338 -version = "4.1.0"
2339 -source = "registry+https://github.com/rust-lang/crates.io-index"
2340 -checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33"
2341 -
2342 -[[package]]
2343 -name = "objc2-foundation"
2344 -version = "0.3.2"
2345 -source = "registry+https://github.com/rust-lang/crates.io-index"
2346 -checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272"
2347 -dependencies = [
2348 - "bitflags 2.10.0",
2349 - "block2",
2350 - "libc",
2351 - "objc2",
2352 - "objc2-core-foundation",
2353 -]
2354 -
2355 -[[package]]
2356 -name = "objc2-io-surface"
2357 -version = "0.3.2"
2358 -source = "registry+https://github.com/rust-lang/crates.io-index"
2359 -checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d"
2360 -dependencies = [
2361 - "bitflags 2.10.0",
2362 - "objc2",
2363 - "objc2-core-foundation",
2364 -]
2365 -
2366 -[[package]]
2367 -name = "objc2-quartz-core"
2368 -version = "0.3.2"
2369 -source = "registry+https://github.com/rust-lang/crates.io-index"
2370 -checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f"
2371 -dependencies = [
2372 - "bitflags 2.10.0",
2373 - "objc2",
2374 - "objc2-core-foundation",
2375 - "objc2-foundation",
2376 -]
2377 -
2378 -[[package]]
2379 -name = "objc2-ui-kit"
2380 -version = "0.3.2"
2381 -source = "registry+https://github.com/rust-lang/crates.io-index"
2382 -checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22"
2383 -dependencies = [
2384 - "bitflags 2.10.0",
2385 - "block2",
2386 - "objc2",
2387 - "objc2-cloud-kit",
2388 - "objc2-core-data",
2389 - "objc2-core-foundation",
2390 - "objc2-core-graphics",
2391 - "objc2-core-image",
2392 - "objc2-core-location",
2393 - "objc2-core-text",
2394 - "objc2-foundation",
2395 - "objc2-quartz-core",
2396 - "objc2-user-notifications",
2397 -]
2398 -
2399 -[[package]]
2400 -name = "objc2-user-notifications"
2401 -version = "0.3.2"
2402 -source = "registry+https://github.com/rust-lang/crates.io-index"
2403 -checksum = "9df9128cbbfef73cda168416ccf7f837b62737d748333bfe9ab71c245d76613e"
2404 -dependencies = [
2405 - "objc2",
2406 - "objc2-foundation",
2407 -]
2408 -
2163 [[package]]
2164 name = "once_cell"
2165 version = "1.21.3"
@@ -2428,7 +2182,7 @@ dependencies = [
2182 "futures-sink",
2183 "js-sys",
2184 "pin-project-lite",
2431 - "thiserror 2.0.17",
2185 + "thiserror",
2186 "tracing",
2187 ]
2188
@@ -2458,7 +2212,7 @@ dependencies = [
2212 "opentelemetry_sdk",
2213 "prost 0.14.1",
2214 "reqwest",
2461 - "thiserror 2.0.17",
2215 + "thiserror",
2216 "tokio",
2217 "tonic 0.14.2",
2218 "tracing",
@@ -2493,27 +2247,11 @@ dependencies = [
2247 "opentelemetry",
2248 "percent-encoding",
2249 "rand 0.9.2",
2496 - "thiserror 2.0.17",
2250 + "thiserror",
2251 "tokio",
2252 "tokio-stream",
2253 ]
2254
2501 -[[package]]
2502 -name = "os_info"
2503 -version = "3.14.0"
2504 -source = "registry+https://github.com/rust-lang/crates.io-index"
2505 -checksum = "e4022a17595a00d6a369236fdae483f0de7f0a339960a53118b818238e132224"
2506 -dependencies = [
2507 - "android_system_properties",
2508 - "log",
2509 - "nix",
2510 - "objc2",
2511 - "objc2-foundation",
2512 - "objc2-ui-kit",
2513 - "serde",
2514 - "windows-sys 0.61.2",
2515 -]
2516 -
2255 [[package]]
2256 name = "otel-plugin"
2257 version = "0.1.1"
@@ -2671,12 +2409,6 @@ dependencies = [
2409 "zerovec",
2410 ]
2411
2674 -[[package]]
2675 -name = "powerfmt"
2676 -version = "0.2.0"
2677 -source = "registry+https://github.com/rust-lang/crates.io-index"
2678 -checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
2679 -
2412 [[package]]
2413 name = "ppv-lite86"
2414 version = "0.2.21"
@@ -2765,61 +2497,6 @@ dependencies = [
2497 "prost 0.13.5",
2498 ]
2499
2768 -[[package]]
2769 -name = "quinn"
2770 -version = "0.11.9"
2771 -source = "registry+https://github.com/rust-lang/crates.io-index"
2772 -checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20"
2773 -dependencies = [
2774 - "bytes",
2775 - "cfg_aliases",
2776 - "pin-project-lite",
2777 - "quinn-proto",
2778 - "quinn-udp",
2779 - "rustc-hash",
2780 - "rustls",
2781 - "socket2 0.6.1",
2782 - "thiserror 2.0.17",
2783 - "tokio",
2784 - "tracing",
2785 - "web-time",
2786 -]
2787 -
2788 -[[package]]
2789 -name = "quinn-proto"
2790 -version = "0.11.13"
2791 -source = "registry+https://github.com/rust-lang/crates.io-index"
2792 -checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31"
2793 -dependencies = [
2794 - "bytes",
2795 - "getrandom 0.3.4",
2796 - "lru-slab",
2797 - "rand 0.9.2",
2798 - "ring",
2799 - "rustc-hash",
2800 - "rustls",
2801 - "rustls-pki-types",
2802 - "slab",
2803 - "thiserror 2.0.17",
2804 - "tinyvec",
2805 - "tracing",
2806 - "web-time",
2807 -]
2808 -
2809 -[[package]]
2810 -name = "quinn-udp"
2811 -version = "0.5.14"
2812 -source = "registry+https://github.com/rust-lang/crates.io-index"
2813 -checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd"
2814 -dependencies = [
2815 - "cfg_aliases",
2816 - "libc",
2817 - "once_cell",
2818 - "socket2 0.6.1",
2819 - "tracing",
2820 - "windows-sys 0.60.2",
2821 -]
2822 -
2500 [[package]]
2501 name = "quote"
2502 version = "1.0.42"
@@ -3012,21 +2689,16 @@ dependencies = [
2689 "http-body",
2690 "http-body-util",
2691 "hyper",
3015 - "hyper-rustls",
2692 "hyper-util",
2693 "js-sys",
2694 "log",
2695 "percent-encoding",
2696 "pin-project-lite",
3021 - "quinn",
3022 - "rustls",
3023 - "rustls-pki-types",
2697 "serde",
2698 "serde_json",
2699 "serde_urlencoded",
2700 "sync_wrapper",
2701 "tokio",
3029 - "tokio-rustls",
2702 "tower 0.5.2",
2703 "tower-http",
2704 "tower-service",
@@ -3034,7 +2706,6 @@ dependencies = [
2706 "wasm-bindgen",
2707 "wasm-bindgen-futures",
2708 "web-sys",
3037 - "webpki-roots 1.0.5",
2709 ]
2710
2711 [[package]]
@@ -3094,15 +2765,6 @@ version = "2.1.1"
2765 source = "registry+https://github.com/rust-lang/crates.io-index"
2766 checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
2767
3097 -[[package]]
3098 -name = "rustc_version"
3099 -version = "0.4.1"
3100 -source = "registry+https://github.com/rust-lang/crates.io-index"
3101 -checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
3102 -dependencies = [
3103 - "semver",
3104 -]
3105 -
2768 [[package]]
2769 name = "rustix"
2770 version = "1.1.2"
@@ -3137,7 +2799,6 @@ version = "1.13.0"
2799 source = "registry+https://github.com/rust-lang/crates.io-index"
2800 checksum = "94182ad936a0c91c324cd46c6511b9510ed16af436d7b5bab34beab0afd55f7a"
2801 dependencies = [
3140 - "web-time",
2802 "zeroize",
2803 ]
2804
@@ -3213,72 +2874,6 @@ version = "1.2.0"
2874 source = "registry+https://github.com/rust-lang/crates.io-index"
2875 checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
2876
3216 -[[package]]
3217 -name = "semver"
3218 -version = "1.0.27"
3219 -source = "registry+https://github.com/rust-lang/crates.io-index"
3220 -checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2"
3221 -
3222 -[[package]]
3223 -name = "sentry"
3224 -version = "0.35.0"
3225 -source = "registry+https://github.com/rust-lang/crates.io-index"
3226 -checksum = "016958f51b96861dead7c1e02290f138411d05e94fad175c8636a835dee6e51e"
3227 -dependencies = [
3228 - "httpdate",
3229 - "reqwest",
3230 - "rustls",
3231 - "sentry-contexts",
3232 - "sentry-core",
3233 - "tokio",
3234 - "ureq",
3235 - "webpki-roots 0.26.11",
3236 -]
3237 -
3238 -[[package]]
3239 -name = "sentry-contexts"
3240 -version = "0.35.0"
3241 -source = "registry+https://github.com/rust-lang/crates.io-index"
3242 -checksum = "eba8754ec3b9279e00aa6d64916f211d44202370a1699afde1db2c16cbada089"
3243 -dependencies = [
3244 - "hostname",
3245 - "libc",
3246 - "os_info",
3247 - "rustc_version",
3248 - "sentry-core",
3249 - "uname",
3250 -]
3251 -
3252 -[[package]]
3253 -name = "sentry-core"
3254 -version = "0.35.0"
3255 -source = "registry+https://github.com/rust-lang/crates.io-index"
3256 -checksum = "f9f8b6dcd4fbae1e3e22b447f32670360b27e31b62ab040f7fb04e0f80c04d92"
3257 -dependencies = [
3258 - "once_cell",
3259 - "rand 0.8.5",
3260 - "sentry-types",
3261 - "serde",
3262 - "serde_json",
3263 -]
3264 -
3265 -[[package]]
3266 -name = "sentry-types"
3267 -version = "0.35.0"
3268 -source = "registry+https://github.com/rust-lang/crates.io-index"
3269 -checksum = "a71ed3a389948a6a6d92b98e997a2723ca22f09660c5a7b7388ecd509a70a527"
3270 -dependencies = [
3271 - "debugid",
3272 - "hex",
3273 - "rand 0.8.5",
3274 - "serde",
3275 - "serde_json",
3276 - "thiserror 1.0.69",
3277 - "time",
3278 - "url",
3279 - "uuid",
3280 -]
3281 -
2877 [[package]]
2878 name = "serde"
2879 version = "1.0.228"
@@ -3557,33 +3152,13 @@ dependencies = [
3152 "windows-sys 0.61.2",
3153 ]
3154
3560 -[[package]]
3561 -name = "thiserror"
3562 -version = "1.0.69"
3563 -source = "registry+https://github.com/rust-lang/crates.io-index"
3564 -checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
3565 -dependencies = [
3566 - "thiserror-impl 1.0.69",
3567 -]
3568 -
3155 [[package]]
3156 name = "thiserror"
3157 version = "2.0.17"
3158 source = "registry+https://github.com/rust-lang/crates.io-index"
3159 checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8"
3160 dependencies = [
3575 - "thiserror-impl 2.0.17",
3576 -]
3577 -
3578 -[[package]]
3579 -name = "thiserror-impl"
3580 -version = "1.0.69"
3581 -source = "registry+https://github.com/rust-lang/crates.io-index"
3582 -checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
3583 -dependencies = [
3584 - "proc-macro2",
3585 - "quote",
3586 - "syn 2.0.110",
3161 + "thiserror-impl",
3162 ]
3163
3164 [[package]]
@@ -3606,37 +3181,6 @@ dependencies = [
3181 "cfg-if",
3182 ]
3183
3609 -[[package]]
3610 -name = "time"
3611 -version = "0.3.45"
3612 -source = "registry+https://github.com/rust-lang/crates.io-index"
3613 -checksum = "f9e442fc33d7fdb45aa9bfeb312c095964abdf596f7567261062b2a7107aaabd"
3614 -dependencies = [
3615 - "deranged",
3616 - "itoa",
3617 - "num-conv",
3618 - "powerfmt",
3619 - "serde_core",
3620 - "time-core",
3621 - "time-macros",
3622 -]
3623 -
3624 -[[package]]
3625 -name = "time-core"
3626 -version = "0.1.7"
3627 -source = "registry+https://github.com/rust-lang/crates.io-index"
3628 -checksum = "8b36ee98fd31ec7426d599183e8fe26932a8dc1fb76ddb6214d05493377d34ca"
3629 -
3630 -[[package]]
3631 -name = "time-macros"
3632 -version = "0.2.25"
3633 -source = "registry+https://github.com/rust-lang/crates.io-index"
3634 -checksum = "71e552d1249bf61ac2a52db88179fd0673def1e1ad8243a00d9ec9ed71fee3dd"
3635 -dependencies = [
3636 - "num-conv",
3637 - "time-core",
3638 -]
3639 -
3184 [[package]]
3185 name = "tinystr"
3186 version = "0.8.2"
@@ -3647,21 +3191,6 @@ dependencies = [
3191 "zerovec",
3192 ]
3193
3650 -[[package]]
3651 -name = "tinyvec"
3652 -version = "1.10.0"
3653 -source = "registry+https://github.com/rust-lang/crates.io-index"
3654 -checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa"
3655 -dependencies = [
3656 - "tinyvec_macros",
3657 -]
3658 -
3659 -[[package]]
3660 -name = "tinyvec_macros"
3661 -version = "0.1.1"
3662 -source = "registry+https://github.com/rust-lang/crates.io-index"
3663 -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
3664 -
3194 [[package]]
3195 name = "tokio"
3196 version = "1.48.0"
@@ -4021,15 +3550,6 @@ version = "1.19.0"
3550 source = "registry+https://github.com/rust-lang/crates.io-index"
3551 checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb"
3552
4024 -[[package]]
4025 -name = "uname"
4026 -version = "0.1.1"
4027 -source = "registry+https://github.com/rust-lang/crates.io-index"
4028 -checksum = "b72f89f0ca32e4db1c04e2a72f5345d59796d4866a1ee0609084569f73683dc8"
4029 -dependencies = [
4030 - "libc",
4031 -]
4032 -
3553 [[package]]
3554 name = "unarray"
3555 version = "0.1.4"
@@ -4054,21 +3574,6 @@ version = "0.9.0"
3574 source = "registry+https://github.com/rust-lang/crates.io-index"
3575 checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
3576
4057 -[[package]]
4058 -name = "ureq"
4059 -version = "2.12.1"
4060 -source = "registry+https://github.com/rust-lang/crates.io-index"
4061 -checksum = "02d1a66277ed75f640d608235660df48c8e3c19f3b4edb6a263315626cc3c01d"
4062 -dependencies = [
4063 - "base64 0.22.1",
4064 - "log",
4065 - "once_cell",
4066 - "rustls",
4067 - "rustls-pki-types",
4068 - "url",
4069 - "webpki-roots 0.26.11",
4070 -]
4071 -
3577 [[package]]
3578 name = "url"
3579 version = "2.5.7"
@@ -4229,24 +3734,6 @@ dependencies = [
3734 "wasm-bindgen",
3735 ]
3736
4232 -[[package]]
4233 -name = "webpki-roots"
4234 -version = "0.26.11"
4235 -source = "registry+https://github.com/rust-lang/crates.io-index"
4236 -checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9"
4237 -dependencies = [
4238 - "webpki-roots 1.0.5",
4239 -]
4240 -
4241 -[[package]]
4242 -name = "webpki-roots"
4243 -version = "1.0.5"
4244 -source = "registry+https://github.com/rust-lang/crates.io-index"
4245 -checksum = "12bed680863276c63889429bfd6cab3b99943659923822de1c8a39c49e4d722c"
4246 -dependencies = [
4247 - "rustls-pki-types",
4248 -]
4249 -
3737 [[package]]
3738 name = "winapi"
3739 version = "0.3.9"
src/crates/Cargo.toml
+1 -4
@@ -30,7 +30,7 @@ members = [
30 ]
31
32 [workspace.package]
33 -version = "0.1.1"
33 +version = "0.1.2"
34 edition = "2024"
35 rust-version = "1.85"
36
@@ -125,9 +125,6 @@ tower = "0.5"
125
126 flatten-serde-json = { git = "https://github.com/meilisearch/meilisearch", tag = "v1.22.1" }
127
128 -# Error tracking
129 -sentry = { version = "0.35", default-features = false }
130 -
128 # Internal workspace crates
129 journal-common = { path = "journal-common" }
130 journal-core = { path = "journal-core" }
src/crates/journal-core/src/error.rs
+3
@@ -66,6 +66,9 @@ pub enum JournalError {
66 #[error("zerocopy failure")]
67 ZerocopyFailure,
68
69 + #[error("misaligned object offset: {0:#x}")]
70 + MisalignedOffset(u64),
71 +
72 #[error("sigbus handler error")]
73 SigbusHandlerError,
74
src/crates/journal-core/src/file/file.rs
+23 -5
@@ -18,6 +18,15 @@ use crate::file::value_guard::ValueGuard;
18 // Size to pad objects to (8 bytes)
19 const OBJECT_ALIGNMENT: u64 = 8;
20
21 +/// Validates that an offset is properly aligned for journal objects.
22 +/// Journal objects must be 8-byte aligned.
23 +fn validate_offset_alignment(offset: NonZeroU64) -> Result<()> {
24 + if offset.get() % OBJECT_ALIGNMENT != 0 {
25 + return Err(JournalError::MisalignedOffset(offset.get()));
26 + }
27 + Ok(())
28 +}
29 +
30 pub trait BucketVisitor<'a> {
31 type Object: JournalObject<&'a [u8]> + HashableObject;
32 type Output;
@@ -398,16 +407,19 @@ impl<M: MemoryMap> JournalFile<M> {
407 }
408
409 pub fn object_header_ref(&self, position: NonZeroU64) -> Result<&ObjectHeader> {
410 + validate_offset_alignment(position)?;
411 let size_needed = std::mem::size_of::<ObjectHeader>() as u64;
412 let window_manager = self.window_manager.borrow_mut_checked()?;
413 let header_slice = window_manager.get_slice(position.get(), size_needed)?;
404 - Ok(ObjectHeader::ref_from_bytes(header_slice).unwrap())
414 + ObjectHeader::ref_from_bytes(header_slice).map_err(|_| JournalError::ZerocopyFailure)
415 }
416
417 fn journal_object_ref<'a, T>(&'a self, offset: NonZeroU64) -> Result<ValueGuard<'a, T>>
418 where
419 T: JournalObject<&'a [u8]>,
420 {
421 + validate_offset_alignment(offset)?;
422 +
423 let is_compact = self
424 .journal_header_ref()
425 .has_incompatible_flag(HeaderIncompatibleFlags::Compact);
@@ -417,7 +429,8 @@ impl<M: MemoryMap> JournalFile<M> {
429 let size_needed = {
430 let header_slice =
431 wm.get_slice(offset.get(), std::mem::size_of::<ObjectHeader>() as u64)?;
420 - let header = ObjectHeader::ref_from_bytes(header_slice).unwrap();
432 + let header = ObjectHeader::ref_from_bytes(header_slice)
433 + .map_err(|_| JournalError::ZerocopyFailure)?;
434 header.size
435 };
436
@@ -838,10 +851,11 @@ impl<M: MemoryMapMut> JournalFile<M> {
851
852 #[allow(clippy::mut_from_ref)]
853 fn object_header_mut(&self, offset: NonZeroU64) -> Result<&mut ObjectHeader> {
854 + validate_offset_alignment(offset)?;
855 let size_needed = std::mem::size_of::<ObjectHeader>() as u64;
856 let window_manager = self.window_manager.borrow_mut_checked()?;
857 let header_slice = window_manager.get_slice_mut(offset.get(), size_needed)?;
844 - Ok(ObjectHeader::mut_from_bytes(header_slice).unwrap())
858 + ObjectHeader::mut_from_bytes(header_slice).map_err(|_| JournalError::ZerocopyFailure)
859 }
860
861 fn journal_object_mut<'a, T>(
@@ -853,6 +867,8 @@ impl<M: MemoryMapMut> JournalFile<M> {
867 where
868 T: JournalObjectMut<&'a mut [u8]>,
869 {
870 + validate_offset_alignment(offset)?;
871 +
872 let is_compact = self
873 .journal_header_ref()
874 .has_incompatible_flag(HeaderIncompatibleFlags::Compact);
@@ -864,7 +880,8 @@ impl<M: MemoryMapMut> JournalFile<M> {
880 // Setting object header for a new object
881 let header_slice =
882 wm.get_slice_mut(offset.get(), std::mem::size_of::<ObjectHeader>() as u64)?;
867 - let header = ObjectHeader::mut_from_bytes(header_slice).unwrap();
883 + let header = ObjectHeader::mut_from_bytes(header_slice)
884 + .map_err(|_| JournalError::ZerocopyFailure)?;
885 header.type_ = type_ as u8;
886 header.size = size;
887 size
@@ -873,7 +890,8 @@ impl<M: MemoryMapMut> JournalFile<M> {
890 // Reading existing object header
891 let header_slice =
892 wm.get_slice(offset.get(), std::mem::size_of::<ObjectHeader>() as u64)?;
876 - let header = ObjectHeader::ref_from_bytes(header_slice).unwrap();
893 + let header = ObjectHeader::ref_from_bytes(header_slice)
894 + .map_err(|_| JournalError::ZerocopyFailure)?;
895 if header.type_ != type_ as u8 {
896 return Err(JournalError::InvalidObjectType);
897 }
src/crates/journal-core/src/file/mod.rs
+1 -1
@@ -8,7 +8,7 @@ pub mod mmap;
8 mod object;
9 pub mod offset_array;
10 pub mod reader;
11 -pub(crate) mod sigbus;
11 +pub mod sigbus;
12 mod value_guard;
13 pub mod writer;
14
src/crates/journal-core/src/lib.rs
+3
@@ -32,3 +32,6 @@ pub use file::{
32 BucketUtilization, Direction, JournalCursor, JournalFile, JournalFileOptions, JournalReader,
33 JournalWriter, Location,
34 };
35 +
36 +// SIGBUS handler for memory-mapped file access
37 +pub use file::sigbus::install_handler as install_sigbus_handler;
src/crates/journal-engine/src/histogram.rs
+30 -1
@@ -5,7 +5,7 @@
5
6 use crate::{cache::FileIndexKey, error::Result, facets::Facets};
7 use journal_core::collections::HashSet;
8 -use journal_index::{FieldName, FieldValuePair, FileIndex, Filter, Seconds};
8 +use journal_index::{Bitmap, FieldName, FieldValuePair, FileIndex, Filter, Seconds};
9 use lru::LruCache;
10 use parking_lot::RwLock;
11 use std::collections::HashMap;
@@ -100,6 +100,8 @@ pub struct BucketResponse {
100 pub fv_counts: HashMap<FieldValuePair, (usize, usize)>,
101 /// Set of fields that are not indexed
102 pub unindexed_fields: HashSet<FieldName>,
103 + /// Total entry counts (unfiltered, filtered) in this bucket across all files
104 + pub total_entries: (usize, usize),
105 }
106
107 impl BucketResponse {
@@ -108,6 +110,7 @@ impl BucketResponse {
110 Self {
111 fv_counts: HashMap::default(),
112 unindexed_fields: HashSet::default(),
113 + total_entries: (0, 0),
114 }
115 }
116
@@ -284,6 +287,32 @@ impl HistogramEngine {
287 None
288 };
289
290 + // Count total entries in this file for this bucket's time range
291 + let all_entries =
292 + Bitmap::insert_range(0..file_index.total_entries() as u32);
293 + let unfiltered_total = file_index
294 + .count_entries_in_time_range(
295 + &all_entries,
296 + bucket_request.start,
297 + bucket_request.end,
298 + )
299 + .unwrap_or(0);
300 +
301 + let filtered_total = if let Some(ref filter_bitmap) = filter_bitmap {
302 + file_index
303 + .count_entries_in_time_range(
304 + filter_bitmap,
305 + bucket_request.start,
306 + bucket_request.end,
307 + )
308 + .unwrap_or(0)
309 + } else {
310 + unfiltered_total
311 + };
312 +
313 + response.total_entries.0 += unfiltered_total;
314 + response.total_entries.1 += filtered_total;
315 +
316 // Track unindexed fields
317 for field in file_index.fields() {
318 if !file_index.is_indexed(field) {
src/crates/netdata-log-viewer/journal-function/src/netdata/histogram.rs
+32 -11
@@ -66,18 +66,20 @@ fn chart_from_histogram(
66 field: &FieldName,
67 transformations: &TransformationRegistry,
68 ) -> Chart {
69 - let result = chart_result_from_histogram(histogram_response, field, transformations);
70 - let view = chart_view_from_histogram(histogram_response, field, &result.labels);
69 + let (raw_values, result) = chart_result_from_histogram(histogram_response, field, transformations);
70 + let view = chart_view_from_histogram(histogram_response, field, &raw_values, &result.labels);
71
72 Chart { view, result }
73 }
74
75 /// Creates chart result data for the given field from a query histogram.
76 +///
77 +/// Returns both the raw values (for dimension IDs) and the ChartResult (with transformed labels).
78 fn chart_result_from_histogram(
79 histogram_response: &QueryHistogram,
80 field: &FieldName,
81 transformations: &TransformationRegistry,
80 -) -> ChartResult {
82 +) -> (Vec<String>, ChartResult) {
83 let field_str = field.as_str();
84
85 // Collect all unique values for the field across all buckets
@@ -106,7 +108,8 @@ fn chart_result_from_histogram(
108
109 for (request, bucket_response) in &histogram_response.buckets {
110 let timestamp = request.start;
109 - let mut counts = Vec::with_capacity(raw_values.len());
111 + let mut counts = Vec::with_capacity(raw_values.len() + 1);
112 + let mut field_sum = 0usize;
113
114 for raw_value in &raw_values {
115 // Create FieldValuePair for lookup using raw (untransformed) value
@@ -118,9 +121,14 @@ fn chart_result_from_histogram(
121 .map(|(_, filtered)| *filtered)
122 .unwrap_or(0);
123
124 + field_sum += count;
125 counts.push([count, 0, 0]);
126 }
127
128 + // Calculate entries without this field (unset)
129 + let unset_count = bucket_response.total_entries.1.saturating_sub(field_sum);
130 + counts.push([unset_count, 0, 0]);
131 +
132 data.push(DataPoint {
133 timestamp: timestamp.0 as u64 * std::time::Duration::from_secs(1).as_millis() as u64,
134 items: counts,
@@ -133,23 +141,36 @@ fn chart_result_from_histogram(
141 pa: 2,
142 };
143
144 + // Add "(unset)" for entries without this field
145 + raw_values.push(String::from("(unset)"));
146 + labels.push(String::from("(unset)"));
147 labels.insert(0, String::from("time"));
148
138 - ChartResult {
139 - labels,
140 - point,
141 - data,
142 - }
149 + (
150 + raw_values,
151 + ChartResult {
152 + labels,
153 + point,
154 + data,
155 + },
156 + )
157 }
158
159 /// Creates chart view metadata for the given field from a query histogram.
160 +///
161 +/// # Arguments
162 +/// * `histogram_response` - The query histogram
163 +/// * `field` - The field name
164 +/// * `raw_values` - Raw (untransformed) values for dimension IDs
165 +/// * `labels` - Transformed values for dimension names (first element is "time", skip it)
166 fn chart_view_from_histogram(
167 histogram_response: &QueryHistogram,
168 field: &FieldName,
169 + raw_values: &[String],
170 labels: &[String],
171 ) -> ChartView {
151 - let ids: Vec<String> = labels.iter().skip(1).cloned().collect();
152 - let names = ids.clone();
172 + let ids = raw_values.to_vec();
173 + let names: Vec<String> = labels.iter().skip(1).cloned().collect();
174 let units = std::iter::repeat_n("events".to_string(), ids.len()).collect();
175
176 let dimensions = ChartDimensions { ids, names, units };
src/crates/netdata-log-viewer/journal-viewer-plugin/Cargo.toml
-3
@@ -43,6 +43,3 @@ journal-core = { workspace = true }
43 journal-index = { workspace = true }
44 journal-function = { workspace = true }
45 journal-registry = { workspace = true }
46 -
47 -# Error tracking
48 -sentry = { workspace = true, features = ["reqwest", "rustls", "contexts"] }
src/crates/netdata-log-viewer/journal-viewer-plugin/src/catalog.rs
-53
@@ -6,7 +6,6 @@ use netdata_plugin_protocol::FunctionDeclaration;
6 use netdata_plugin_schema::HttpAccess;
7 use parking_lot::RwLock;
8 use rt::FunctionHandler;
9 -use sentry::protocol::Value;
9 use std::sync::Arc;
10 use tracing::{debug, error, info, instrument, warn};
11
@@ -69,44 +68,6 @@ fn build_filter_from_selections(selections: &HashMap<String, Vec<String>>) -> Fi
68 }
69 }
70
72 -/// Captures an error to Sentry with request context.
73 -fn capture_request_error(
74 - transaction_id: &str,
75 - operation: &str,
76 - error_message: &str,
77 - context: &RequestContext,
78 -) {
79 - // Capture the error event with context
80 - sentry::with_scope(
81 - |scope| {
82 - scope.set_tag("transaction_id", transaction_id);
83 - scope.set_tag("operation", operation);
84 - scope.set_extra("time_range_start", Value::from(context.time_range_start));
85 - scope.set_extra("time_range_end", Value::from(context.time_range_end));
86 - scope.set_extra("file_count", Value::from(context.file_count));
87 - if let Some(duration) = context.find_files_duration_ms {
88 - scope.set_extra("find_files_duration_ms", Value::from(duration));
89 - }
90 - if let Some(duration) = context.indexing_duration_ms {
91 - scope.set_extra("indexing_duration_ms", Value::from(duration));
92 - }
93 - },
94 - || {
95 - sentry::capture_message(error_message, sentry::Level::Error);
96 - },
97 - );
98 -}
99 -
100 -/// Context for a request, used for error reporting.
101 -#[derive(Default)]
102 -struct RequestContext {
103 - time_range_start: i64,
104 - time_range_end: i64,
105 - file_count: usize,
106 - find_files_duration_ms: Option<u64>,
107 - indexing_duration_ms: Option<u64>,
108 -}
109 -
71 fn accepted_params() -> Vec<netdata::RequestParam> {
72 use netdata::RequestParam;
73
@@ -542,18 +503,10 @@ impl FunctionHandler for CatalogFunction {
503 };
504 info!("[{}] started transaction", txn.id());
505
545 - // Initialize request context for error reporting
546 - let mut ctx = RequestContext {
547 - time_range_start: request.after as i64,
548 - time_range_end: request.before as i64,
549 - ..Default::default()
550 - };
551 -
506 // Create query time range with automatic alignment
507 let time_range = journal_function::QueryTimeRange::new(request.after, request.before)
508 .map_err(|e| {
509 let msg = format!("[{}] {}", txn.id(), e);
556 - capture_request_error(&txn.id(), "time_range_creation", &msg, &ctx);
510 netdata_plugin_error::NetdataPluginError::Other { message: msg }
511 })?;
512
@@ -575,12 +528,9 @@ impl FunctionHandler for CatalogFunction {
528 .find_files_in_range(Seconds(request.after), Seconds(request.before))
529 .map_err(|e| {
530 let msg = format!("[{}] failed to find files in range: {}", txn.id(), e);
578 - capture_request_error(&txn.id(), "find_files", &msg, &ctx);
531 netdata_plugin_error::NetdataPluginError::Other { message: msg }
532 })?;
533 let find_files_duration = op_start.elapsed();
582 - ctx.find_files_duration_ms = Some(find_files_duration.as_millis() as u64);
583 - ctx.file_count = files.len();
534 info!("[{}] found {} files in time range", txn.id(), files.len(),);
535 if tracing::enabled!(tracing::Level::DEBUG) {
536 for (idx, file_info) in files.iter().enumerate() {
@@ -637,11 +587,9 @@ impl FunctionHandler for CatalogFunction {
587 .await
588 .map_err(|e| {
589 let msg = format!("[{}] failed to index files: {}", txn.id(), e);
640 - capture_request_error(&txn.id(), "file_indexing", &msg, &ctx);
590 netdata_plugin_error::NetdataPluginError::Other { message: msg }
591 })?;
592 let indexing_duration = op_start.elapsed();
644 - ctx.indexing_duration_ms = Some(indexing_duration.as_millis() as u64);
593
594 info!(
595 "[{}] retrieved {}/{} file indexes for histogram buckets and log entries",
@@ -672,7 +620,6 @@ impl FunctionHandler for CatalogFunction {
620 .compute_from_indexes(&indexed_files, &time_range, &request.facets, &filter_expr)
621 .map_err(|e| {
622 let msg = format!("[{}] failed to compute histogram: {}", txn.id(), e);
675 - capture_request_error(&txn.id(), "histogram_computation", &msg, &ctx);
623 netdata_plugin_error::NetdataPluginError::Other { message: msg }
624 })?;
625 let histogram_duration = op_start.elapsed();
src/crates/netdata-log-viewer/journal-viewer-plugin/src/main.rs
+7 -32
@@ -11,41 +11,16 @@ use plugin_config::PluginConfig;
11 use rt::PluginRuntime;
12 use tracing::{error, info};
13
14 -/// Initialize Sentry error tracking.
15 -///
16 -/// Returns a guard that must be kept alive for the duration of the program.
17 -fn init_sentry() -> Option<sentry::ClientInitGuard> {
18 - if std::env::var("DISABLE_TELEMETRY").is_ok() {
19 - return None;
20 - }
21 -
22 - let dsn =
23 - "https://e6e6b1488ab279fc702439e15d6112cc@o382276.ingest.us.sentry.io/4510709226143744";
24 -
25 - let guard = sentry::init((
26 - dsn,
27 - sentry::ClientOptions {
28 - release: sentry::release_name!(),
29 - // Enable session tracking for counting plugin starts
30 - auto_session_tracking: true,
31 - // Set sample rate for transactions (0.0 = no transactions, saves quota)
32 - traces_sample_rate: 0.0,
33 - ..Default::default()
34 - },
35 - ));
36 -
37 - // Start a session to track this plugin run
38 - sentry::start_session();
39 -
40 - Some(guard)
41 -}
42 -
14 #[tokio::main]
15 async fn main() {
45 - println!("TRUST_DURATIONS 1");
16 + // Install SIGBUS handler first, before any memory-mapped file operations,
17 + // because systemd can rotate journal files at any time.
18 + if let Err(e) = journal_core::install_sigbus_handler() {
19 + eprintln!("failed to install SIGBUS handler: {}", e);
20 + std::process::exit(1);
21 + }
22
47 - // Initialize Sentry before tracing so panics are captured
48 - let _sentry_guard = init_sentry();
23 + println!("TRUST_DURATIONS 1");
24
25 rt::init_tracing();
26