Compare commits

...

15 Commits

Author SHA1 Message Date
d32c27b31c
Merge pull request #3 from durin42/metrics-update
metrics: update crates to latest versions and drop some unused features
2024-11-02 20:41:03 -04:00
Augie Fackler
4755513f5d metrics-exporter-prometheus: drop default features
This prunes quite a bit from the dependency graph that we weren't using anyway.
2024-11-01 21:44:13 -04:00
Augie Fackler
feb6684e8f metrics: update to latest version
Really the only reason I bothered was because the old version brings
in an ahash that fails to compile on macOS Arm or something like that,
but since I'd done the upgrade before for my own packages it wasn't
hard.
2024-10-28 12:23:47 -04:00
5341153a86 Use the metrics facade 2023-03-14 13:17:12 -04:00
f609dcfef3 Bump version to 0.2.2 2023-03-14 11:53:51 -04:00
390b61ee86 Higher resolution ping timings 2023-03-13 20:26:19 -04:00
b45b29e22d Update socket2 2023-02-27 15:19:16 -05:00
347ac8147a Update tiny_http 2023-02-27 15:17:30 -05:00
ca9ce99d49 Update prometheus 2023-02-27 15:16:34 -05:00
b7aafbce25 2022-07-14 21:37:32 -04:00
a91e316aec update tiny_http and socket2 2022-07-14 21:36:48 -04:00
3dc6ded1b0 Update icmp-socket version 2022-07-14 21:34:28 -04:00
2cea3a294e Update to tracing for logs 2022-07-14 21:13:42 -04:00
26ac114f88 create nix package wrapper using flake-compat 2022-03-03 17:45:22 -05:00
425ab1e959 nix flake 2022-03-01 17:53:35 -05:00
11 changed files with 845 additions and 584 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

3
.gitignore vendored
View File

@ -1,2 +1,3 @@
target/
.vscode/
.vscode/
result

712
Cargo.lock generated
View File

@ -1,12 +1,26 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "aho-corasick"
version = "0.7.15"
name = "ahash"
version = "0.8.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5"
checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
dependencies = [
"memchr",
"cfg-if",
"once_cell",
"version_check",
"zerocopy",
]
[[package]]
name = "ansi_term"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
dependencies = [
"winapi",
]
[[package]]
@ -28,27 +42,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbf56136a5198c7b01a49e3afcbef6cf84597273d298f54432926024107b0109"
[[package]]
name = "atty"
version = "0.2.11"
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652"
dependencies = [
"libc",
"termion",
"winapi",
]
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "autocfg"
version = "1.0.1"
name = "base64"
version = "0.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
[[package]]
name = "bitflags"
version = "1.2.1"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
[[package]]
name = "bumpalo"
version = "3.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535"
[[package]]
name = "byteorder"
@ -62,25 +77,34 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chrono"
version = "0.4.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73"
dependencies = [
"libc",
"num-integer",
"num-traits",
"time",
"winapi",
]
[[package]]
name = "chunked_transfer"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7477065d45a8fe57167bf3cf8bcd3729b54cfcb81cca49bda2d038ea89ae82ca"
[[package]]
name = "crossbeam-epoch"
version = "0.9.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695"
dependencies = [
"autocfg",
"cfg-if",
"crossbeam-utils",
"memoffset",
"scopeguard",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b"
dependencies = [
"cfg-if",
]
[[package]]
name = "ctor"
version = "0.1.18"
@ -88,40 +112,37 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10bcb9d7dcbf7002aaffbb53eac22906b64cdcc127971dcc387d8eb7c95d5560"
dependencies = [
"quote",
"syn",
"syn 1.0.60",
]
[[package]]
name = "durnitisp"
version = "0.2.1"
version = "0.2.3"
dependencies = [
"anyhow",
"gflags",
"icmp-socket",
"log 0.4.14",
"metrics",
"metrics-exporter-prometheus",
"nursery",
"prometheus",
"resolve",
"socket2",
"stderrlog",
"socket2 0.5.1",
"tiny_http",
"tracing",
"tracing-subscriber",
]
[[package]]
name = "fnv"
version = "1.0.7"
name = "equivalent"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
name = "form_urlencoded"
version = "1.0.0"
name = "foldhash"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ece68d15c92e84fa4f19d3780f1294e5ca82a78a6d515f1efaabcc144688be00"
dependencies = [
"matches",
"percent-encoding",
]
checksum = "f81ec6369c545a7d40e4589b5597581fa1c441fe1cce96dd1de43159910a36a2"
[[package]]
name = "fuchsia-cprng"
@ -149,7 +170,7 @@ checksum = "07ab1d33648a58677c98ee6ed81ce592e108d4e9847ce62a15302da7e5bfd437"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 1.0.60",
]
[[package]]
@ -160,17 +181,32 @@ checksum = "1a5bcf1bbeab73aa4cf2fde60a846858dc036163c7c33bec309f8d17de785479"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 1.0.60",
]
[[package]]
name = "icmp-socket"
version = "0.1.1"
name = "hashbrown"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c83b37323293113bad20766377951f5b51e0b23fc7cc6694b6b93e6ff02ecf8"
checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb"
dependencies = [
"foldhash",
]
[[package]]
name = "httpdate"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421"
[[package]]
name = "icmp-socket"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "98bc3daf82cd6b2f02709427c17f75e1023471f59bc74726bbd27d8a907af605"
dependencies = [
"byteorder",
"socket2",
"socket2 0.4.4",
]
[[package]]
@ -185,23 +221,13 @@ dependencies = [
]
[[package]]
name = "idna"
version = "0.2.0"
name = "indexmap"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9"
checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da"
dependencies = [
"matches",
"unicode-bidi",
"unicode-normalization",
]
[[package]]
name = "instant"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec"
dependencies = [
"cfg-if",
"equivalent",
"hashbrown",
]
[[package]]
@ -223,7 +249,16 @@ checksum = "75c094e94816723ab936484666968f5b58060492e880f3c8d00489a1e244fa51"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 1.0.60",
]
[[package]]
name = "js-sys"
version = "0.3.49"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc15e39392125075f60c95ba416f5381ff6c3a948ff02ab12464715adf56c821"
dependencies = [
"wasm-bindgen",
]
[[package]]
@ -234,18 +269,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.84"
version = "0.2.161"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1cca32fa0182e8c0989459524dc356b8f2b5c10f1b9eb521b7d182c03cf8c5ff"
[[package]]
name = "lock_api"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd96ffd135b2fd7b973ac026d28085defbe8983df057ced3eb4f2130b0831312"
dependencies = [
"scopeguard",
]
checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1"
[[package]]
name = "log"
@ -272,35 +298,51 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
[[package]]
name = "memchr"
version = "2.3.4"
name = "memoffset"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
[[package]]
name = "num-integer"
version = "0.1.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
dependencies = [
"autocfg",
"num-traits",
]
[[package]]
name = "num-traits"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1"
dependencies = [
"autocfg",
]
[[package]]
name = "numtoa"
version = "0.1.0"
name = "metrics"
version = "0.24.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef"
checksum = "8ae428771d17306715c5091d446327d1cfdedc82185c65ba8423ab404e45bf10"
dependencies = [
"ahash",
"portable-atomic",
]
[[package]]
name = "metrics-exporter-prometheus"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85b6f8152da6d7892ff1b7a1c0fa3f435e92b5918ad67035c3bb432111d9a29b"
dependencies = [
"base64",
"indexmap",
"metrics",
"metrics-util",
"quanta",
"thiserror",
]
[[package]]
name = "metrics-util"
version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "15b482df36c13dd1869d73d14d28cd4855fbd6cfc32294bee109908a9f4a4ed7"
dependencies = [
"crossbeam-epoch",
"crossbeam-utils",
"hashbrown",
"metrics",
"quanta",
"sketches-ddsketch",
]
[[package]]
name = "nursery"
@ -309,71 +351,52 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4bd2d4e0cd7c6bb256afbc59a5921c3ead56f05d7696c92e05b6978858b6fa5"
[[package]]
name = "parking_lot"
version = "0.11.1"
name = "once_cell"
version = "1.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb"
checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
[[package]]
name = "pin-project-lite"
version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
[[package]]
name = "portable-atomic"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2"
[[package]]
name = "proc-macro2"
version = "1.0.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e"
dependencies = [
"instant",
"lock_api",
"parking_lot_core",
"unicode-ident",
]
[[package]]
name = "parking_lot_core"
version = "0.8.2"
name = "quanta"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ccb628cad4f84851442432c60ad8e1f607e29752d0bf072cbd0baf28aa34272"
checksum = "8e5167a477619228a0b284fac2674e3c388cba90631d7b7de620e6f1fcd08da5"
dependencies = [
"cfg-if",
"instant",
"crossbeam-utils",
"libc",
"redox_syscall 0.1.57",
"smallvec",
"once_cell",
"raw-cpuid",
"wasi",
"web-sys",
"winapi",
]
[[package]]
name = "percent-encoding"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
[[package]]
name = "proc-macro2"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
dependencies = [
"unicode-xid",
]
[[package]]
name = "prometheus"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8425533e7122f0c3cc7a37e6244b16ad3a2cc32ae7ac6276e2a75da0d9c200d"
dependencies = [
"cfg-if",
"fnv",
"lazy_static",
"parking_lot",
"protobuf",
"regex",
"thiserror",
]
[[package]]
name = "protobuf"
version = "2.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86473d5f16580f10b131a0bf0afb68f8e029d1835d33a00f37281b05694e5312"
[[package]]
name = "quote"
version = "1.0.8"
version = "1.0.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "991431c3519a3f36861882da93630ce66b52918dcf1b8e2fd66b397fc96f28df"
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
dependencies = [
"proc-macro2",
]
@ -416,6 +439,15 @@ version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
[[package]]
name = "raw-cpuid"
version = "11.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ab240315c661615f2ee9f0f2cd32d5a7343a84d5ebcccb99d46e6637565e7b0"
dependencies = [
"bitflags",
]
[[package]]
name = "rdrand"
version = "0.4.0"
@ -425,30 +457,6 @@ dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "redox_syscall"
version = "0.1.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
[[package]]
name = "redox_syscall"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05ec8ca9416c5ea37062b502703cd7fcb207736bc294f6e0cf367ac6fc234570"
dependencies = [
"bitflags",
]
[[package]]
name = "redox_termios"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8440d8acb4fd3d277125b4bd01a6f38aee8d814b3b5fc09b3f2b825d37d3fe8f"
dependencies = [
"redox_syscall 0.2.4",
]
[[package]]
name = "ref-cast"
version = "1.0.6"
@ -466,34 +474,16 @@ checksum = "4c38e3aecd2b21cb3959637b883bb3714bc7e43f0268b9a29d3743ee3e55cdd2"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 1.0.60",
]
[[package]]
name = "regex"
version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9251239e129e16308e70d853559389de218ac275b515068abc96829d05b948a"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
"thread_local",
]
[[package]]
name = "regex-syntax"
version = "0.6.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5eb417147ba9860a96cfe72a0b93bf88fee1744b5636ec99ab20c1aa9376581"
[[package]]
name = "resolve"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19526b305899bea65f26edda78a64f5313958494321ee0ab66bd94b32958614a"
dependencies = [
"idna 0.1.5",
"idna",
"libc",
"log 0.3.9",
"rand 0.3.23",
@ -506,33 +496,44 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "smallvec"
version = "1.6.1"
name = "sharded-slab"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e"
checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31"
dependencies = [
"lazy_static",
]
[[package]]
name = "sketches-ddsketch"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1e9a774a6c28142ac54bb25d25562e6bcf957493a184f15ad4eebccb23e410a"
[[package]]
name = "smallvec"
version = "1.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
[[package]]
name = "socket2"
version = "0.3.19"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e"
checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0"
dependencies = [
"cfg-if",
"libc",
"winapi",
]
[[package]]
name = "stderrlog"
name = "socket2"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "45a53e2eff3e94a019afa6265e8ee04cb05b9d33fe9f5078b14e4e391d155a38"
checksum = "bc8d618c6641ae355025c449427f9e96b98abf99a772be3cef6708d15c77147a"
dependencies = [
"atty",
"chrono",
"log 0.4.14",
"termcolor",
"thread_local",
"libc",
"windows-sys",
]
[[package]]
@ -547,24 +548,14 @@ dependencies = [
]
[[package]]
name = "termcolor"
version = "1.1.2"
name = "syn"
version = "2.0.85"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4"
checksum = "5023162dfcd14ef8f32034d8bcd4cc5ddc61ef7a247c024a33e24e1f24d21b56"
dependencies = [
"winapi-util",
]
[[package]]
name = "termion"
version = "1.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "077185e2eac69c3f8379a4298e1e07cd36beb962290d4a51199acf0fdc10607e"
dependencies = [
"libc",
"numtoa",
"redox_syscall 0.2.4",
"redox_termios",
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
@ -584,40 +575,28 @@ checksum = "9be73a2caec27583d0046ef3796c3794f868a5bc813db689eed00c7631275cd1"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 1.0.60",
]
[[package]]
name = "thread_local"
version = "1.0.1"
version = "1.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180"
dependencies = [
"lazy_static",
]
[[package]]
name = "time"
version = "0.1.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
dependencies = [
"libc",
"wasi",
"winapi",
"once_cell",
]
[[package]]
name = "tiny_http"
version = "0.8.0"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eded47106b8e52d8ed8119f0ea6e8c0f5881e69783e0297b5a8462958f334bc1"
checksum = "389915df6413a2e74fb181895f933386023c71110878cd0825588928e64cdc82"
dependencies = [
"ascii",
"chrono",
"chunked_transfer",
"httpdate",
"log 0.4.14",
"url",
]
[[package]]
@ -635,6 +614,64 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
[[package]]
name = "tracing"
version = "0.1.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a400e31aa60b9d44a52a8ee0343b5b18566b03a8321e0d321f695cf56e940160"
dependencies = [
"cfg-if",
"pin-project-lite",
"tracing-attributes",
"tracing-core",
]
[[package]]
name = "tracing-attributes"
version = "0.1.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "11c75893af559bc8e10716548bdef5cb2b983f8e637db9d0e15126b61b484ee2"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.60",
]
[[package]]
name = "tracing-core"
version = "0.1.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b7358be39f2f274f322d2aaed611acc57f382e8eb1e5b48cb9ae30933495ce7"
dependencies = [
"once_cell",
"valuable",
]
[[package]]
name = "tracing-log"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922"
dependencies = [
"lazy_static",
"log 0.4.14",
"tracing-core",
]
[[package]]
name = "tracing-subscriber"
version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a713421342a5a666b7577783721d3117f1b69a393df803ee17bb73b1e122a59"
dependencies = [
"ansi_term",
"sharded-slab",
"smallvec",
"thread_local",
"tracing-core",
"tracing-log",
]
[[package]]
name = "unicode-bidi"
version = "0.3.4"
@ -644,6 +681,12 @@ dependencies = [
"matches",
]
[[package]]
name = "unicode-ident"
version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"
[[package]]
name = "unicode-normalization"
version = "0.1.16"
@ -660,22 +703,86 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
[[package]]
name = "url"
version = "2.2.0"
name = "valuable"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5909f2b0817350449ed73e8bcd81c8c3c8d9a7a5d8acba4b27db277f1868976e"
dependencies = [
"form_urlencoded",
"idna 0.2.0",
"matches",
"percent-encoding",
]
checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "wasi"
version = "0.10.0+wasi-snapshot-preview1"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
version = "0.2.72"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8fe8f61dba8e5d645a4d8132dc7a0a66861ed5e1045d2c0ed940fab33bac0fbe"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.72"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "046ceba58ff062da072c7cb4ba5b22a37f00a302483f7e2a6cdc18fedbdc1fd3"
dependencies = [
"bumpalo",
"lazy_static",
"log 0.4.14",
"proc-macro2",
"quote",
"syn 1.0.60",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.72"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ef9aa01d36cda046f797c57959ff5f3c615c9cc63997a8d545831ec7976819b"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.72"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96eb45c1b2ee33545a813a92dbb53856418bf7eb54ab34f7f7ff1448a5b3735d"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.60",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.72"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7148f4696fb4960a346eaa60bbfb42a1ac4ebba21f750f75fc1375b098d5ffa"
[[package]]
name = "web-sys"
version = "0.3.49"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59fe19d70f5dacc03f6e46777213facae5ac3801575d56ca6cbd4c93dcd12310"
dependencies = [
"js-sys",
"wasm-bindgen",
]
[[package]]
name = "winapi"
@ -693,17 +800,94 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
dependencies = [
"winapi",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
version = "0.45.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608"
[[package]]
name = "windows_aarch64_msvc"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7"
[[package]]
name = "windows_i686_gnu"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640"
[[package]]
name = "windows_i686_msvc"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605"
[[package]]
name = "windows_x86_64_gnu"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463"
[[package]]
name = "windows_x86_64_msvc"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd"
[[package]]
name = "zerocopy"
version = "0.7.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
dependencies = [
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
version = "0.7.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.85",
]

View File

@ -1,19 +1,20 @@
[package]
name = "durnitisp"
version = "0.2.1"
version = "0.2.3"
authors = ["Jeremy Wall <jeremy@marzhillstudios.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
tracing = "0.1.35"
tracing-subscriber = "0.3.14"
anyhow = "1"
gflags = "^0.3"
log = "0.4"
nursery = "^0.0.1"
prometheus = "0.11.0"
stderrlog = "0.5.1"
tiny_http = "0.8.0"
socket2 = "0.3.19"
icmp-socket = "0.1.1"
resolve = "^0.2.0"
metrics = "0.24.0"
metrics-exporter-prometheus = {version = "0.16.0", default-features = false}
tiny_http = "0.12.0"
socket2 = "0.5.1"
icmp-socket = "0.2.0"
resolve = "^0.2.0"

11
default.nix Normal file
View File

@ -0,0 +1,11 @@
let
lock = builtins.fromJSON (builtins.readFile ./flake.lock);
in
(import (
fetchTarball {
url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz";
sha256 = lock.nodes.flake-compat.locked.narHash;
}
) {
src = ./.;
}).defaultNix

76
flake.lock generated Normal file
View File

@ -0,0 +1,76 @@
{
"nodes": {
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1641205782,
"narHash": "sha256-4jY7RCWUoZ9cKD8co0/4tFARpWB+57+r1bLLvXNJliY=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "b7547d3eed6f32d06102ead8991ec52ab0a4f1a7",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"flake-utils": {
"locked": {
"lastModified": 1644229661,
"narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"naersk": {
"inputs": {
"nixpkgs": "nixpkgs"
},
"locked": {
"lastModified": 1671096816,
"narHash": "sha256-ezQCsNgmpUHdZANDCILm3RvtO1xH8uujk/+EqNvzIOg=",
"owner": "nix-community",
"repo": "naersk",
"rev": "d998160d6a076cfe8f9741e56aeec7e267e3e114",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "naersk",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1678724065,
"narHash": "sha256-MjeRjunqfGTBGU401nxIjs7PC9PZZ1FBCZp/bRB3C2M=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b8afc8489dc96f29f69bec50fdc51e27883f89c1",
"type": "github"
},
"original": {
"id": "nixpkgs",
"type": "indirect"
}
},
"root": {
"inputs": {
"flake-compat": "flake-compat",
"flake-utils": "flake-utils",
"naersk": "naersk"
}
}
},
"root": "root",
"version": 7
}

21
flake.nix Normal file
View File

@ -0,0 +1,21 @@
{
inputs = {
flake-utils.url = "github:numtide/flake-utils";
naersk.url = "github:nix-community/naersk";
flake-compat = { url = github:edolstra/flake-compat; flake = false; };
};
outputs = {self, flake-utils, naersk, flake-compat}:
flake-utils.lib.eachDefaultSystem (system:
let
naersk-lib = naersk.lib."${system}";
in
{
defaultPackage = naersk-lib.buildPackage rec {
pname = "kitchen";
src = ./.;
};
}
);
}

View File

@ -14,7 +14,7 @@
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
use std::ops::Sub;
use std::{
collections::HashMap,
collections::{BTreeMap, HashMap},
time::{Duration, Instant},
};
@ -25,9 +25,9 @@ use icmp_socket::{
packet::{Icmpv4Message, Icmpv6Message, WithEchoRequest},
IcmpSocket, IcmpSocket4, IcmpSocket6, Icmpv4Packet, Icmpv6Packet,
};
use log::{debug, error, info};
use metrics::{counter, gauge, histogram};
use nursery::{thread, Nursery};
use prometheus::{CounterVec, GaugeVec};
use tracing::{debug, error, info, instrument, warn};
gflags::define! {
/// The payload to use for the ping requests.
@ -62,15 +62,89 @@ fn resolve_host_address(host: &str) -> String {
struct State<AddrType> {
destinations: HashMap<u16, (String, AddrType)>, // domain, address
// TODO(jwall): This should be a time tracker by both identifier and sequence
time_tracker: HashMap<u16, (Option<Instant>, u16)>,
latency_guage: GaugeVec,
ping_counter: CounterVec,
time_tracker: BTreeMap<u16, BTreeMap<u16, Instant>>,
destination_counter: BTreeMap<u16, u16>,
// TODO(jwall): Add histogram for latency as well.
}
fn make_ping_count_labels(domain_name: &str, result: &str) -> [(&'static str, String); 2] {
[
("domain", domain_name.to_owned()),
("result", result.to_owned()),
]
}
impl<AddrType: std::fmt::Display> State<AddrType> {
fn handle_echo_reply(&mut self, identifier: u16, sequence: u16) -> bool {
if let Some((domain_name, dest)) = self.destinations.get(&identifier) {
let time_tracker = self.time_tracker.get_mut(&identifier);
let mut result = false;
if let Some(Some(send_time)) = time_tracker.as_ref().map(|m| m.get(&sequence)) {
let elapsed = Instant::now().sub(send_time.clone()).as_micros() as f64 / 1000.00;
// We make a copy here to avoid the borrow above sticking around for too long.
info!(
domain=domain_name,
%dest,
time = elapsed,
seq = sequence,
"Reply",
);
counter!("ping_counter", &make_ping_count_labels(domain_name, "ok")).increment(1);
if elapsed as i32 != 0 {
let labels = [("domain", domain_name.to_owned())];
let latency = gauge!("ping_latency", &labels);
latency.increment(elapsed);
let latency_hist = histogram!("ping_latency_hist_ms", &labels);
latency_hist.record(elapsed);
}
self.time_tracker
.get_mut(&identifier)
.and_then(|m| m.remove(&sequence));
result = true;
} else {
error!(sequence, "Discarding unexpected sequence",);
};
// Check all the other sequences to see if they have expired timeouts yet.
// Record timeout for the expired sequences.
// Remove the timeouts for the expired sequences.
let expired_sequences = self.time_tracker.get(&identifier).map(|m| {
let mut for_delete = Vec::with_capacity(m.len());
let m = m.clone();
{
for (k, send_time) in m.iter() {
if Instant::now().sub(*send_time) >= Duration::from_secs(PINGTIMEOUT.flag) {
info!(
domain=domain_name,
%dest,
seq = sequence,
"Dropped"
);
counter!(
"ping_counter",
&make_ping_count_labels(domain_name, "dropped")
)
.increment(1);
for_delete.push(*k);
}
}
}
for_delete
});
for k in expired_sequences.unwrap_or_default() {
self.time_tracker
.get_mut(&identifier)
.and_then(|m| m.remove(&k));
}
return result;
} else {
warn!(identifier, "Discarding wrong identifier");
}
return false;
}
}
struct PingerImpl<Sock: IcmpSocket> {
sock: Sock,
timeout: Duration,
}
trait PacketHandler<PacketType, AddrType>
@ -87,8 +161,9 @@ impl<'a> PacketHandler<Icmpv6Packet, Ipv6Addr> for &'a mut State<Ipv6Addr> {
return self;
}
#[instrument(level = "debug", skip(self))]
fn handle_pkt(&mut self, pkt: Icmpv6Packet) -> bool {
debug!("ICMP: handling packet {:?}", pkt);
debug!("handling packet");
match pkt.message {
Icmpv6Message::Unreachable {
_unused,
@ -107,15 +182,17 @@ impl<'a> PacketHandler<Icmpv6Packet, Ipv6Addr> for &'a mut State<Ipv6Addr> {
},
}) => {
if let Some((domain_name, _addr)) = self.destinations.get(&identifier) {
self.ping_counter
.with(&prometheus::labels! {"result" => "unreachable", "domain" => domain_name})
.inc();
counter!(
"ping_counter",
&make_ping_count_labels(domain_name, "unreachable")
)
.increment(1);
return true;
}
}
Err(e) => {
// We ignore these as well but log it.
error!("ICMP: Error parsing Unreachable invoking packet {:?}", e);
error!(err = ?e, "Error parsing Unreachable");
}
_ => {
// We ignore these
@ -133,21 +210,16 @@ impl<'a> PacketHandler<Icmpv6Packet, Ipv6Addr> for &'a mut State<Ipv6Addr> {
checksum: _,
message:
Icmpv6Message::EchoRequest {
identifier,
identifier: _,
sequence: _,
payload: _,
},
}) => {
if let Some((domain_name, _addr)) = self.destinations.get(&identifier) {
self.ping_counter
.with(&prometheus::labels! {"result" => "parameter_problem", "domain" => domain_name})
.inc();
return true;
}
// TODO log but otherwise ignore this.
}
Err(e) => {
// We ignore these as well but log it.
error!("ICMP: Error parsing Unreachable invoking packet {:?}", e);
error!(err = ?e, "Error parsing ParameterProblem");
}
_ => {
// We ignore these
@ -159,44 +231,7 @@ impl<'a> PacketHandler<Icmpv6Packet, Ipv6Addr> for &'a mut State<Ipv6Addr> {
sequence,
payload: _,
} => {
if let Some((domain_name, dest)) = self.destinations.get(&identifier) {
if let Some((Some(send_time), expected_sequence)) =
self.time_tracker.get(&identifier)
{
let elapsed =
Instant::now().sub(send_time.clone()).as_millis() as f64 / 1000.00;
// We make a copy here to avoid the borrow above sticking around for too long.
let expected_sequence = *expected_sequence;
if sequence != expected_sequence {
error!(
"ICMP: Discarding unexpected sequence sequence={} expected={}",
sequence, expected_sequence
);
self.time_tracker
.insert(identifier, (None, expected_sequence.wrapping_add(1)));
return false;
}
info!(
"ICMP: Reply from {}({}): time={}ms, seq={}",
domain_name, dest, elapsed, sequence,
);
self.ping_counter
.with(&prometheus::labels! {"result" => "ok", "domain" => domain_name})
.inc();
if elapsed as i32 != 0 {
self.latency_guage
.with(&prometheus::labels! {"domain" => domain_name.as_str()})
.set(elapsed);
}
self.time_tracker
.insert(identifier, (None, expected_sequence.wrapping_add(1)));
return true;
} else {
return false;
};
} else {
info!("ICMP: Discarding wrong identifier {}", identifier);
}
return self.handle_echo_reply(identifier, sequence);
}
_ => {
// We ignore the rest.
@ -211,53 +246,20 @@ impl<'a> PacketHandler<Icmpv4Packet, Ipv4Addr> for &'a mut State<Ipv4Addr> {
return self;
}
#[instrument(level = "debug", skip(self))]
fn handle_pkt(&mut self, pkt: Icmpv4Packet) -> bool {
debug!("ICMP: handling packet {:?}", pkt);
debug!("handling packet");
match pkt.message {
Icmpv4Message::EchoReply {
identifier,
sequence,
payload: _,
} => {
if let Some((domain_name, dest)) = self.destinations.get(&identifier) {
if let Some((Some(send_time), expected_sequence)) =
self.time_tracker.get(&identifier)
{
let elapsed =
Instant::now().sub(send_time.clone()).as_micros() as f64 / 1000.00;
let expected_sequence = *expected_sequence;
if expected_sequence != sequence {
error!(
"ICMP: Discarding unexpected sequence sequence={} expected={}",
sequence, expected_sequence
);
self.time_tracker
.insert(identifier, (None, expected_sequence.wrapping_add(1)));
return false;
}
info!(
"ICMP: Reply from {}({}): time={}ms, seq={}",
domain_name, dest, elapsed, sequence,
);
self.ping_counter
.with(&prometheus::labels! {"result" => "ok", "domain" => domain_name})
.inc();
self.latency_guage
.with(&prometheus::labels! {"domain" => domain_name.as_str()})
.set(elapsed);
self.time_tracker
.insert(identifier, (None, expected_sequence.wrapping_add(1)));
return true;
} else {
return false;
};
} else {
info!("ICMP: Discarding wrong identifier {}", identifier);
}
return self.handle_echo_reply(identifier, sequence);
}
p => {
_ => {
// We ignore the rest.
info!("ICMP Unhandled packet {:?}", p);
info!("Unhandled packet");
}
}
return false;
@ -279,6 +281,41 @@ where
fn recv_pkt(&mut self) -> std::io::Result<PacketType>;
fn recv_all<H: PacketHandler<PacketType, AddrType>>(&mut self, handler: H);
fn send_pkt(
&mut self,
state: &mut State<AddrType>,
identifier: u16,
dest: AddrType,
domain_name: &String,
) -> std::io::Result<()> {
let sequence = *state.destination_counter.entry(identifier).or_insert(0);
debug!(
domain=domain_name, %dest, sequence,
"Sending echo request",
);
match self.send_to_destination(dest, identifier, sequence) {
Err(e) => {
counter!("ping_counter", &make_ping_count_labels(domain_name, "err")).increment(1);
error!(
domain=domain_name, %dest, err=?e,
"Error sending. Trying again later",
);
}
Ok(send_time) => {
state
.time_tracker
.entry(identifier)
.or_insert_with(|| BTreeMap::new())
.insert(sequence, send_time);
}
}
state
.destination_counter
.get_mut(&identifier)
.map(|v| *v = v.wrapping_add(1));
Ok(())
}
}
impl<Sock> Pinger<Sock::AddrType, Sock::PacketType> for PingerImpl<Sock>
@ -287,66 +324,14 @@ where
Sock::AddrType: std::fmt::Display + Copy,
Sock::PacketType: WithEchoRequest<Packet = Sock::PacketType>,
{
#[instrument(skip_all)]
fn send_all(&mut self, state: &mut State<Sock::AddrType>) -> std::io::Result<()> {
let destinations = state.destinations.clone();
info!("ICMP: Attempting to send packets for all domains");
debug!("Attempting to send packets for all domains");
for (identifier, (domain_name, dest)) in destinations.into_iter() {
let previous_tracker = state.time_tracker.get(&identifier);
let sequence = if previous_tracker.is_some() {
let (send_status, sequence) = previous_tracker.unwrap();
if let Some(send_time) = send_status {
// We haven't recieved the previous packet response yet so don't send unless we've waited
// for timeout length of time.
let elapsed = Instant::now() - *send_time;
if elapsed > Duration::from_secs(PINGTIMEOUT.flag) {
info!(
"ICMP: Dropped packet detected for domain_name={} send_time={:?} elapsed={:?} sequence={}",
domain_name, send_time, elapsed, sequence
);
state.ping_counter
.with(&prometheus::labels! {"result" => "dropped", "domain" => &domain_name})
.inc();
sequence.wrapping_add(1)
} else {
debug!(
"ICMP: Waiting for timeout before sending next packet domain_name={} sequence={}",
domain_name, sequence
);
continue;
}
} else {
*sequence
}
} else {
debug!(
"ICMP: Initializing sequence for first send domain_name={} sequence=0",
domain_name
);
0
};
info!(
"ICMP: sending echo request to {}({}) sequence={}",
domain_name, dest, sequence
);
match self.send_to_destination(dest, identifier, sequence) {
Err(e) => {
state
.ping_counter
.with(&prometheus::labels! {"result" => "err", "type" => "send"})
.inc();
error!(
"ICMP: error sending to domain: {} and address: {} failed: {:?}, Trying again later",
domain_name, &dest, e
);
}
Ok(send_time) => {
state
.time_tracker
.insert(identifier, (Some(send_time), sequence));
}
}
self.send_pkt(state, identifier, dest, &domain_name)?;
}
debug!("ICMP: finished sending for domains");
debug!("Finished sending for domains");
Ok(())
}
@ -372,6 +357,7 @@ where
Ok(response)
}
#[instrument(skip(self, handler))]
fn recv_all<H: PacketHandler<Sock::PacketType, Sock::AddrType>>(&mut self, mut handler: H) {
if handler.get_mut_state().destinations.is_empty() {
debug!("Nothing to send to so skipping for this socket");
@ -381,40 +367,35 @@ where
.get_mut_state()
.time_tracker
.values()
.find(|item| item.0.is_some())
.find(|item| !item.is_empty())
.is_none()
{
// nothing has been sent yet so no need to try to recv packets
debug!("Nothing to recieve for so skipping for this socket");
debug!("Nothing to recieve so skipping for this socket");
return;
}
self.sock
.set_timeout(self.timeout)
.expect("Unable to set timout for recieves on socket.");
self.sock.set_timeout(None);
let loop_start_time = Instant::now();
loop {
// Receive loop
debug!("ICMP: Attempting to recieve packets on socket");
debug!("Attempting to recieve packets on socket");
match self.recv_pkt() {
Ok(pkt) => {
if handler.handle_pkt(pkt) {
// break out of the recv loop
debug!("ICMP: Recieved Packet");
debug!("Recieved Packet");
return;
}
}
Err(e) => {
error!("ICMP: Error receiving packet: {:?}", e);
handler
.get_mut_state()
.ping_counter
.with(&prometheus::labels! {"result" => "err", "domain" => "unknown"})
.inc();
error!(err = ?e, "Error receiving packet");
counter!("ping_counter", &make_ping_count_labels("unknown", "err"))
.increment(1);
return;
}
}
if (Instant::now() - loop_start_time) > Duration::from_secs(PINGTIMEOUT.flag) {
info!("ICMP: Timing out on recieve loop");
info!("Timing out on recieve loop");
return;
}
}
@ -444,12 +425,8 @@ impl Multi {
}
}
pub fn schedule_echo_server(
domain_names: &Vec<&str>,
ping_latency_guage: GaugeVec,
ping_counter: CounterVec,
parent: &mut Nursery,
) {
#[instrument(name = "ICMP", skip_all)]
pub fn schedule_echo_server(domain_names: &Vec<&str>, parent: &mut Nursery) {
let resolved: Vec<(String, IpAddr)> = domain_names
.iter()
.map(|domain_name| {
@ -476,36 +453,40 @@ pub fn schedule_echo_server(
let mut v4_destinations = HashMap::new();
let mut v4_id_counter = 42;
for target in v4_targets {
info!("ICMP: Attempting ping to {}({})", target.0, target.1);
info!(
domain_name = target.0,
address = %target.1,
"Attempting ping"
);
v4_destinations.insert(v4_id_counter, target.clone());
v4_id_counter += 1;
}
let v4_state = State {
destinations: v4_destinations,
time_tracker: HashMap::new(),
latency_guage: ping_latency_guage.clone(),
ping_counter: ping_counter.clone(),
time_tracker: BTreeMap::new(),
destination_counter: BTreeMap::new(),
};
let mut v6_destinations = HashMap::new();
let mut v6_id_counter = 42;
for target in v6_targets {
info!("ICMP: Attempting ping to {}({})", target.0, target.1);
info!(
domain_name = target.0,
address = %target.1,
"Attempting ping"
);
v6_destinations.insert(v6_id_counter, target.clone());
v6_id_counter += 1;
}
let v4_pinger = PingerImpl {
sock: IcmpSocket4::new().expect("Failed to open Icmpv4 Socket"),
timeout: Duration::from_millis(10),
};
let v6_state = State {
destinations: v6_destinations,
time_tracker: HashMap::new(),
latency_guage: ping_latency_guage,
ping_counter,
time_tracker: BTreeMap::new(),
destination_counter: BTreeMap::new(),
};
let v6_pinger = PingerImpl {
sock: IcmpSocket6::new().expect("Failed to open Icmpv6 Socket"),
timeout: Duration::from_millis(10),
};
let multi = std::sync::Arc::new(std::sync::Mutex::new(Multi {
v4_pinger,
@ -515,7 +496,7 @@ pub fn schedule_echo_server(
}));
let send_multi = multi.clone();
let send_thread = thread::Pending::new(move || {
info!("ICMP: Starrting send thread");
info!("Starting send thread");
loop {
{
send_multi.lock().unwrap().send_all();
@ -524,7 +505,7 @@ pub fn schedule_echo_server(
}
});
let recv_thread = thread::Pending::new(move || {
info!("ICMP: Starrting recv thread");
info!("Starting recv thread");
loop {
{
multi.lock().unwrap().recv_all();

View File

@ -11,18 +11,16 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use std::convert::Into;
use std::sync::Arc;
use gflags;
use log::{debug, error, info};
use metrics_exporter_prometheus;
use nursery::thread;
use nursery::{Nursery, Waitable};
use prometheus::{self, GaugeVec};
use prometheus::{CounterVec, Encoder, IntGaugeVec, Opts, Registry, TextEncoder};
use stderrlog;
use tiny_http;
use tracing::{debug, error, info, instrument, Level};
use tracing_subscriber::FmtSubscriber;
mod icmp;
mod stun;
@ -43,6 +41,11 @@ gflags::define! {
--debug = false
}
gflags::define! {
/// Enable trace logging
--trace = false
}
gflags::define! {
/// Comma separated list of hosts to ping
--pingHosts = "google.com"
@ -53,6 +56,7 @@ gflags::define! {
--stunHosts = "stun.l.google.com:19302,stun.ekiga.net:3478,stun.xten.com:3478,stun.ideasip.com:3478,stun.rixtelecom.se:3478,stun.schlund.de:3478,stun.softjoys.com:3478,stun.stunprotocol.org:3478,stun.voiparound.com:3478,stun.voipbuster.com:3478,stun.voipstunt.com:3478,stun1.noc.ams-ix.net:3478"
}
#[instrument]
fn main() -> anyhow::Result<()> {
gflags::parse();
let stun_servers: Vec<&str> = STUNHOSTS.flag.split(",").collect();
@ -67,59 +71,32 @@ fn main() -> anyhow::Result<()> {
gflags::print_help_and_exit(0);
}
let level = if DEBUG.flag || cfg!(debug_assertions) {
3
let subscriber_builder = if DEBUG.flag {
FmtSubscriber::builder()
// all spans/events with a level higher than debug
// will be written to stdout.
.with_max_level(Level::DEBUG)
} else if TRACE.flag {
FmtSubscriber::builder()
// all spans/events with a level will be written to stdout.
.with_max_level(Level::TRACE)
} else {
2
FmtSubscriber::builder()
// all spans/events with a level higher than info (e.g, error, info, warn, etc.)
// will be written to stdout.
.with_max_level(Level::INFO)
};
stderrlog::new()
.verbosity(level)
.timestamp(stderrlog::Timestamp::Millisecond)
.init()?;
tracing::subscriber::set_global_default(subscriber_builder.finish())
.expect("setting default subscriber failed");
let ping_hosts: Vec<&str> = PINGHOSTS.flag.split(",").collect();
let builder = metrics_exporter_prometheus::PrometheusBuilder::new();
let prom_handle = builder
.install_recorder()
.expect("Failed to install prometheus exporter");
// Create a Registry and register metrics.
let r = Registry::new();
let stun_counter_vec = CounterVec::new(
Opts::new(
"stun_attempt_counter",
"Counter for the good, bad, and total attempts to connect to stun server.",
),
&["result", "domain"],
)
.unwrap();
let stun_success_vec = IntGaugeVec::new(
Opts::new("stun_success", "Stun probe successes"),
&["domain"],
)
.unwrap();
let stun_latency_vec = IntGaugeVec::new(
Opts::new(
"stun_attempt_latency_ms",
"Latency guage in millis per stun domain.",
),
&["domain"],
)
.unwrap();
let ping_latency_vec =
GaugeVec::new(Opts::new("ping_latency", "ICMP Ping latency"), &["domain"]).unwrap();
let ping_counter_vec = CounterVec::new(
Opts::new("ping_counter", "Ping Request Counter"),
&["result", "domain"],
)
.unwrap();
r.register(Box::new(stun_counter_vec.clone()))
.expect("Failed to register stun connection counter");
r.register(Box::new(stun_latency_vec.clone()))
.expect("Failed to register stun latency guage");
r.register(Box::new(stun_success_vec.clone()))
.expect("Failed to register stun success gauge");
r.register(Box::new(ping_latency_vec.clone()))
.expect("Failed to register ping latency guage");
r.register(Box::new(ping_counter_vec.clone()))
.expect("Failed to register ping counter");
let stun_socket_addrs = util::resolve_socket_addrs(&stun_servers).unwrap();
let stun_servers = Arc::new(stun_servers);
let ping_hosts = Arc::new(ping_hosts);
@ -130,33 +107,33 @@ fn main() -> anyhow::Result<()> {
// Introduce a new scope for our Arc to clone before moving it into the thread.
// thread::Handle starts the thread immediately so the render thread will usually start first.
let render_thread = thread::Handle::new(move || {
debug!("attempting to start server on {}", LISTENHOST.flag);
debug!(listenhost = LISTENHOST.flag, "attempting to start server");
let server = match tiny_http::Server::http(LISTENHOST.flag) {
Ok(server) => server,
Err(err) => {
error!("Error starting render thread {}", err);
error!("Shutting down all threads...");
error!(
?err,
"Error starting render thread. Shutting down all thread.",
);
std::process::exit(1);
}
};
info!("Listening for metrics request on {}", LISTENHOST.flag);
info!(
listenthost = LISTENHOST.flag,
"Listening for metrics request on"
);
loop {
info!("Waiting for request");
match server.recv() {
Ok(req) => {
let mut buffer = vec![];
// Gather the metrics.
let encoder = TextEncoder::new();
let metric_families = r.gather();
encoder.encode(&metric_families, &mut buffer).unwrap();
let response = tiny_http::Response::from_data(buffer).with_status_code(200);
let response = tiny_http::Response::from_data(prom_handle.render())
.with_status_code(200);
if let Err(e) = req.respond(response) {
error!("Error responding to request {}", e);
error!(err = ?e, "Error responding to request");
}
}
Err(e) => {
info!("Invalid http request! {}", e);
error!(err = ?e, "Invalid http request!");
}
}
}
@ -164,27 +141,15 @@ fn main() -> anyhow::Result<()> {
parent.adopt(Box::new(render_thread));
}
{
let ping_latency_vec = ping_latency_vec.clone();
let ping_counter_vec = ping_counter_vec.clone();
icmp::schedule_echo_server(&ping_hosts, ping_latency_vec, ping_counter_vec, &mut parent);
icmp::schedule_echo_server(&ping_hosts, &mut parent);
}
// Then we attempt to start connections to each stun server.
for (i, s) in stun_socket_addrs.iter().enumerate() {
let stun_servers_copy = stun_servers.clone();
let stun_counter_vec_copy = stun_counter_vec.clone();
let stun_latency_vec_copy = stun_latency_vec.clone();
let stun_success_vec_copy = stun_success_vec.clone();
if let Some(s) = s.clone() {
let domain_name = *stun_servers_copy.get(i).unwrap();
let connect_thread = thread::Pending::new(move || {
stun::start_listen_thread(
domain_name,
s.into(),
stun_counter_vec_copy,
stun_latency_vec_copy,
stun_success_vec_copy,
)
});
let connect_thread =
thread::Pending::new(move || stun::start_listen_thread(domain_name, s.into()));
parent.schedule(Box::new(connect_thread));
// Spread the probe threads out so they're somewhat uniformly distributed.
std::thread::sleep(std::time::Duration::from_micros(

View File

@ -13,12 +13,12 @@
// limitations under the License.
use gflags;
use log::{debug, error, info};
use prometheus::{CounterVec, IntGaugeVec};
use metrics::{counter, gauge};
use std::convert::From;
use std::io;
use std::net::{SocketAddr, UdpSocket};
use std::time::SystemTime;
use tracing::{debug, error, info, instrument};
gflags::define! {
/// Read timeout for the stun server udp receive
@ -70,61 +70,81 @@ fn attempt_stun_connect(addr: SocketAddr) -> Result<SystemTime, ConnectError> {
Ok(SystemTime::now())
}
pub fn start_listen_thread(
domain_name: &str,
s: SocketAddr,
stun_counter_vec_copy: CounterVec,
stun_latency_vec_copy: IntGaugeVec,
stun_success_vec_copy: IntGaugeVec,
) {
debug!("started thread for {}", domain_name);
fn make_count_labels(domain_name: &str, result: &str) -> [(&'static str, String); 2] {
[
("domain", domain_name.to_owned()),
("result", result.to_owned()),
]
}
#[instrument(
name = "STUN",
fields(domain=domain_name, socket=%s),
)]
pub fn start_listen_thread(domain_name: &str, s: SocketAddr) {
let labels: [(&str, String); 1] = [("domain", domain_name.to_owned())];
let success = gauge!("stun_success", &labels);
debug!("starting thread");
loop {
let now = SystemTime::now();
info!("Attempting to connect to {}", domain_name);
info!("Attempting to connect");
match attempt_stun_connect(s) {
Ok(finish_time) => {
info!("Success! connecting to {}", domain_name);
stun_counter_vec_copy
.with(&prometheus::labels! {"result" => "ok", "domain" => domain_name})
.inc();
stun_latency_vec_copy
.with(&prometheus::labels! {"domain" => domain_name})
// Technically this could be lossy but we'll chance it anyway.
.set(finish_time.duration_since(now).unwrap().as_millis() as i64);
stun_success_vec_copy
.with(&prometheus::labels! {"domain" => domain_name})
.set(1);
info!(
timeout = false,
success = true,
millis = finish_time.duration_since(now).unwrap().as_millis(),
conn_type = "Stun connection",
);
counter!(
"stun_attempt_counter",
&make_count_labels(domain_name, "ok")
)
.increment(1);
gauge!("stun_attempt_latency_ms", &labels)
.increment(finish_time.duration_since(now).unwrap().as_millis() as f64);
success.set(1);
}
Err(ConnectError::Timeout(finish_time)) => {
info!(
"Stun connection to {} timedout after {} millis",
domain_name,
finish_time.duration_since(now).unwrap().as_millis()
timeout = true,
success = false,
millis = finish_time.duration_since(now).unwrap().as_millis(),
conn_type = "Stun connection",
);
stun_counter_vec_copy
.with(&prometheus::labels! {"result" => "timeout", "domain" => domain_name})
.inc();
stun_success_vec_copy
.with(&prometheus::labels! {"domain" => domain_name})
.set(0);
counter!(
"stun_attempt_counter",
&make_count_labels(domain_name, "timeout")
)
.increment(1);
success.set(0);
}
Err(ConnectError::Err(e)) => {
error!("Error connecting to {}: {}", domain_name, e);
stun_counter_vec_copy
.with(&prometheus::labels! {"result" => "err", "domain" => domain_name})
.inc();
stun_success_vec_copy
.with(&prometheus::labels! {"domain" => domain_name})
.set(0);
error!(
timeout=true, success=false, err = ?e,
conn_type="Stun connection",
);
counter!(
"stun_attempt_counter",
&make_count_labels(domain_name, "err")
)
.increment(1);
success.set(0);
}
Err(ConnectError::Incomplete) => {
error!("Connection to {} was incomplete", domain_name);
stun_counter_vec_copy
.with(&prometheus::labels! {"result" => "incomplete", "domain" => domain_name})
.inc();
stun_success_vec_copy
.with(&prometheus::labels! {"domain" => domain_name})
.set(0);
error!(
timeout = true,
success = false,
err = "Incomplete",
conn_type = "Stun connection",
);
counter!(
"stun_attempt_counter",
&make_count_labels(domain_name, "incomplete")
)
.increment(1);
success.set(0);
}
}

View File

@ -17,9 +17,9 @@ use std::net::IpAddr;
use std::net::{SocketAddr, ToSocketAddrs};
use gflags;
use log::info;
use resolve::config::DnsConfig;
use resolve::resolver::DnsResolver;
use tracing::{error, instrument};
gflags::define! {
/// Allow IPv6 addresses for domain name lookups.
@ -46,6 +46,7 @@ pub fn resolve_hosts<'a>(servers: &'a Vec<&str>) -> io::Result<Vec<Option<IpAddr
return Ok(results);
}
#[instrument]
pub fn resolve_socket_addrs<'a>(servers: &'a Vec<&str>) -> io::Result<Vec<Option<SocketAddr>>> {
let mut results = Vec::new();
for name in servers.iter().cloned() {
@ -53,7 +54,7 @@ pub fn resolve_socket_addrs<'a>(servers: &'a Vec<&str>) -> io::Result<Vec<Option
match name.to_socket_addrs() {
Ok(addr) => results.push(addr.into_iter().next()),
Err(e) => {
info!("Failed to resolve {} with error {}", name, e);
error!(name, err = ?e, "Failed to resolve");
results.push(None);
}
}