diff --git a/Cargo.lock b/Cargo.lock index c39b0c9..64530b9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,15 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "aho-corasick" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +dependencies = [ + "memchr", +] + [[package]] name = "ansi_term" version = "0.12.1" @@ -11,23 +20,47 @@ dependencies = [ "winapi", ] +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + [[package]] name = "autocfg" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +[[package]] +name = "base64" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" + [[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bumpalo" +version = "3.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" + [[package]] name = "burp_exporter" version = "0.1.0" dependencies = [ "openssl", + "prometheus_exporter_base", "serde", "serde_json", "tokio", @@ -54,6 +87,21 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "clap" +version = "2.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +dependencies = [ + "ansi_term", + "atty", + "bitflags", + "strsim", + "textwrap", + "unicode-width", + "vec_map", +] + [[package]] name = "core-foundation" version = "0.9.2" @@ -70,6 +118,28 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" +[[package]] +name = "ct-logs" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1a816186fa68d9e426e3cb4ae4dff1fcd8e4a2c34b781bf7a822574a0d0aac8" +dependencies = [ + "sct", +] + +[[package]] +name = "env_logger" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" +dependencies = [ + "atty", + "humantime", + "log", + "regex", + "termcolor", +] + [[package]] name = "fastrand" version = "1.7.0" @@ -79,6 +149,12 @@ dependencies = [ "instant", ] +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + [[package]] name = "foreign-types" version = "0.3.2" @@ -94,6 +170,144 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +[[package]] +name = "futures-channel" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" + +[[package]] +name = "futures-macro" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-task" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" + +[[package]] +name = "futures-util" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" +dependencies = [ + "futures-core", + "futures-macro", + "futures-task", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "http" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31f4c6746584866f0feabcc69893c5b51beef3831656a968ed7ae254cdc4fd03" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ff4f84919677303da5f147645dbea6b1881f368d03ac84e1dc09031ebd7b2c6" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9100414882e15fb7feccb4897e5f0ff0ff1ca7d1a86a23208ada4d7a18e6c6c4" + +[[package]] +name = "httpdate" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" + +[[package]] +name = "humantime" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" +dependencies = [ + "quick-error", +] + +[[package]] +name = "hyper" +version = "0.14.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "043f0e083e9901b6cc658a77d1eb86f4fc650bbb977a4337dd63192826aa85dd" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f9f7a97316d44c0af9b0301e65010573a853a9fc97046d7331d7f6bc0fd5a64" +dependencies = [ + "ct-logs", + "futures-util", + "hyper", + "log", + "rustls", + "rustls-native-certs", + "tokio", + "tokio-rustls", + "webpki", +] + [[package]] name = "instant" version = "0.1.12" @@ -109,6 +323,15 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" +[[package]] +name = "js-sys" +version = "0.3.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a38fc24e30fd564ce974c02bf1d337caddff65be6cc4735a1f7eab22a7440f04" +dependencies = [ + "wasm-bindgen", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -194,6 +417,83 @@ dependencies = [ "winapi", ] +[[package]] +name = "num" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8536030f9fea7127f841b45bb6243b27255787fb4eb83958aa1ef9d2fdc0c36" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6b19411a9719e753aff12e5187b74d60d3dc449ec3f4dc21e3989c3f554bc95" +dependencies = [ + "autocfg", + "num-traits", +] + +[[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-iter" +version = "0.1.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2021c8337a54d21aca0d59a92577a029af9431cb59b909b03252b9c164fad59" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef" +dependencies = [ + "autocfg", + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +dependencies = [ + "autocfg", +] + [[package]] name = "once_cell" version = "1.9.0" @@ -239,6 +539,12 @@ version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c" +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + [[package]] name = "pkg-config" version = "0.3.24" @@ -254,6 +560,30 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "prometheus_exporter_base" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05b214e11b8c1d9a9d659eb097b77326cb74fcde851477adb97d145222d17585" +dependencies = [ + "clap", + "env_logger", + "http", + "hyper", + "hyper-rustls", + "log", + "num", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + [[package]] name = "quote" version = "1.0.15" @@ -278,6 +608,8 @@ version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" dependencies = [ + "aho-corasick", + "memchr", "regex-syntax", ] @@ -305,6 +637,46 @@ dependencies = [ "winapi", ] +[[package]] +name = "ring" +version = "0.16.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin", + "untrusted", + "web-sys", + "winapi", +] + +[[package]] +name = "rustls" +version = "0.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35edb675feee39aec9c99fa5ff985081995a06d594114ae14cbe797ad7b7a6d7" +dependencies = [ + "base64", + "log", + "ring", + "sct", + "webpki", +] + +[[package]] +name = "rustls-native-certs" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a07b7c1885bd8ed3831c289b7870b13ef46fe0e856d288c30d9cc17d75a2092" +dependencies = [ + "openssl-probe", + "rustls", + "schannel", + "security-framework", +] + [[package]] name = "ryu" version = "1.0.9" @@ -321,6 +693,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "sct" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b362b83898e0e69f38515b82ee15aa80636befe47c3b6d3d89a911e78fc228ce" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "security-framework" version = "2.6.1" @@ -393,12 +775,40 @@ dependencies = [ "libc", ] +[[package]] +name = "slab" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" + [[package]] name = "smallvec" version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" +[[package]] +name = "socket2" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + +[[package]] +name = "strsim" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" + [[package]] name = "syn" version = "1.0.86" @@ -424,6 +834,44 @@ dependencies = [ "winapi", ] +[[package]] +name = "termcolor" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "thiserror" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "thread_local" version = "1.1.4" @@ -471,6 +919,23 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-rustls" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc6844de72e57df1980054b38be3a9f4702aba4858be64dd700181a8a6d0e1b6" +dependencies = [ + "rustls", + "tokio", + "webpki", +] + +[[package]] +name = "tower-service" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" + [[package]] name = "tracing" version = "0.1.30" @@ -533,12 +998,30 @@ dependencies = [ "tracing-log", ] +[[package]] +name = "try-lock" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" + +[[package]] +name = "unicode-width" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" + [[package]] name = "unicode-xid" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + [[package]] name = "valuable" version = "0.1.0" @@ -551,6 +1034,96 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +[[package]] +name = "vec_map" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" + +[[package]] +name = "want" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +dependencies = [ + "log", + "try-lock", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25f1af7423d8588a3d840681122e72e6a24ddbcb3f0ec385cac0d12d24256c06" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b21c0df030f5a177f3cba22e9bc4322695ec43e7257d865302900290bcdedca" +dependencies = [ + "bumpalo", + "lazy_static", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f4203d69e40a52ee523b2529a773d5ffc1dc0071801c87b3d270b471b80ed01" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa8a30d46208db204854cadbb5d4baf5fcf8071ba5bf48190c3e59937962ebc" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d958d035c4438e28c70e4321a2911302f10135ce78a9c7834c0cab4123d06a2" + +[[package]] +name = "web-sys" +version = "0.3.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c060b319f29dd25724f09a2ba1418f142f539b2be99fbf4d2d5a8f7330afb8eb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki" +version = "0.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e38c0608262c46d4a56202ebabdeb094cef7e560ca7a226c6bf055188aa4ea" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "winapi" version = "0.3.9" @@ -567,6 +1140,15 @@ 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" diff --git a/Cargo.toml b/Cargo.toml index 189644d..e37c411 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,10 @@ serde_json = "1.0.78" tokio-native-tls = "^0.3.0" tracing = "^0.1.30" +[dependencies.prometheus_exporter_base] +version = "^1.3.0" +features = ["hyper_server"] + [dependencies.serde] version = "^1.0.136" features = ["derive"] diff --git a/src/metrics.rs b/src/metrics.rs new file mode 100644 index 0000000..c2afbbe --- /dev/null +++ b/src/metrics.rs @@ -0,0 +1,296 @@ +//! BURP client backup metrics +use prometheus_exporter_base::prelude::*; +use tracing::error; + +use crate::burp::client::Client; +use crate::burp::error::Error; +use crate::burp::model::BackupStats; + +macro_rules! metric { + ($client:ident, $count:literal, $value:expr) => { + PrometheusInstance::new() + .with_label("client", $client.as_ref()) + .with_label("count", $count) + .with_value($value) + }; +} + +macro_rules! counter { + ($metric:expr, $client:ident, $counter:ident) => { + $metric + .render_and_append_instance(&metric!( + $client, + "count", + $counter.count + )) + .render_and_append_instance(&metric!( + $client, + "changed", + $counter.changed + )) + .render_and_append_instance(&metric!( + $client, + "same", + $counter.same + )) + .render_and_append_instance(&metric!( + $client, + "deleted", + $counter.deleted + )) + .render_and_append_instance(&metric!( + $client, + "scanned", + $counter.scanned + )) + }; +} + +/// BURP backup metrics +/// +/// This structure manages the Prometheus metrics for a BURP backup. +struct Metrics<'a> { + backup_number: PrometheusMetric<'a>, + backup_timestamp: PrometheusMetric<'a>, + files: PrometheusMetric<'a>, + meta_data: PrometheusMetric<'a>, + directories: PrometheusMetric<'a>, + soft_links: PrometheusMetric<'a>, + hard_links: PrometheusMetric<'a>, + special_files: PrometheusMetric<'a>, + grand_total: PrometheusMetric<'a>, + bytes_estimated: PrometheusMetric<'a>, + bytes: PrometheusMetric<'a>, + bytes_received: PrometheusMetric<'a>, + bytes_sent: PrometheusMetric<'a>, + elapsed_time: PrometheusMetric<'a>, +} + +impl<'a> Metrics<'a> { + pub fn new() -> Self { + Self { + backup_number: PrometheusMetric::build() + .with_name("burp_client_last_backup_number") + .with_metric_type(MetricType::Counter) + .with_help("Last backup number") + .build(), + backup_timestamp: PrometheusMetric::build() + .with_name("burp_client_last_backup_timestamp") + .with_metric_type(MetricType::Counter) + .with_help("Last backup timestamp") + .build(), + files: PrometheusMetric::build() + .with_name("burp_backup_files_count") + .with_metric_type(MetricType::Gauge) + .with_help("Files in last backup") + .build(), + meta_data: PrometheusMetric::build() + .with_name("burp_backup_metadata_count") + .with_metric_type(MetricType::Gauge) + .with_help("Metadata in last backup") + .build(), + directories: PrometheusMetric::build() + .with_name("burp_backup_directories_count") + .with_metric_type(MetricType::Gauge) + .with_help("Directories in last backup") + .build(), + soft_links: PrometheusMetric::build() + .with_name("burp_backup_soft_links_count") + .with_metric_type(MetricType::Gauge) + .with_help("Soft (symbolic) links in last backup") + .build(), + hard_links: PrometheusMetric::build() + .with_name("burp_backup_hard_links_count") + .with_metric_type(MetricType::Gauge) + .with_help("Hard links in last backup") + .build(), + special_files: PrometheusMetric::build() + .with_name("burp_backup_special_files_count") + .with_metric_type(MetricType::Gauge) + .with_help("Special files in last backup") + .build(), + grand_total: PrometheusMetric::build() + .with_name("burp_backup_total_count") + .with_metric_type(MetricType::Gauge) + .with_help("Total files in last backup") + .build(), + bytes_estimated: PrometheusMetric::build() + .with_name("burp_backup_estimated_bytes") + .with_metric_type(MetricType::Gauge) + .with_help("Estimated bytes in last backup") + .build(), + bytes: PrometheusMetric::build() + .with_name("burp_backup_bytes") + .with_metric_type(MetricType::Gauge) + .with_help("Size of last backup") + .build(), + bytes_received: PrometheusMetric::build() + .with_name("burp_backup_received_bytes") + .with_metric_type(MetricType::Gauge) + .with_help("Bytes received in last backup") + .build(), + bytes_sent: PrometheusMetric::build() + .with_name("burp_backup_sent_bytes") + .with_metric_type(MetricType::Gauge) + .with_help("Bytes sent in last backup") + .build(), + elapsed_time: PrometheusMetric::build() + .with_name("burp_backup_elapsed_time_seconds") + .with_metric_type(MetricType::Gauge) + .with_help("Time taken performing last backup") + .build(), + } + } + + /// Add metrics for a client's latest backup + /// + /// This method adds values for the `burp_client_last_backup_number` + /// and `burp_client_last_backup_timestamp` metrics. + pub fn add_backup>( + &mut self, + client: S, + number: u64, + timestamp: u64, + ) { + self.backup_number.render_and_append_instance( + &PrometheusInstance::new() + .with_label("client", client.as_ref()) + .with_value(number), + ); + self.backup_timestamp.render_and_append_instance( + &PrometheusInstance::new() + .with_label("client", client.as_ref()) + .with_value(timestamp), + ); + } + + /// Add metrics backup statistics + /// + /// This method adds values for file, directory, metadata, and + /// soft/hard link count metrics, bytes total, sent, and received + /// metrics, and elapsed time metrics for a backup. + pub fn add_stats>( + &mut self, + client: S, + stats: &BackupStats, + ) { + let mut time_start: Option = None; + let mut time_end: Option = None; + for counter in &stats.counters { + match counter.name.as_ref() { + "files" => { + counter!(self.files, client, counter); + } + "meta_data" => { + counter!(self.meta_data, client, counter); + } + "directories" => { + counter!(self.directories, client, counter); + } + "soft_links" => { + counter!(self.soft_links, client, counter); + } + "hard_links" => { + counter!(self.hard_links, client, counter); + } + "special_files" => { + counter!(self.special_files, client, counter); + } + "grand_total" => { + counter!(self.grand_total, client, counter); + } + "bytes_estimated" => { + self.bytes_estimated.render_and_append_instance( + &PrometheusInstance::new() + .with_label("client", client.as_ref()) + .with_value(counter.count), + ); + } + "bytes" => { + self.bytes.render_and_append_instance( + &PrometheusInstance::new() + .with_label("client", client.as_ref()) + .with_value(counter.count), + ); + } + "bytes_received" => { + self.bytes_received.render_and_append_instance( + &PrometheusInstance::new() + .with_label("client", client.as_ref()) + .with_value(counter.count), + ); + } + "bytes_sent" => { + self.bytes_sent.render_and_append_instance( + &PrometheusInstance::new() + .with_label("client", client.as_ref()) + .with_value(counter.count), + ); + } + "time_start" => { + time_start = Some(counter.count); + } + "time_end" => { + time_end = Some(counter.count); + } + _ => {} + } + } + if let Some(start) = time_start { + if let Some(end) = time_end { + self.elapsed_time.render_and_append_instance( + &PrometheusInstance::new() + .with_label("client", client.as_ref()) + .with_value(end - start), + ); + } + } + } + + /// Render the metrics in Prometheus exposition format + pub fn to_string(&self) -> String { + let mut value = String::new(); + value.push_str(&self.backup_number.render()); + value.push_str(&self.backup_timestamp.render()); + value.push_str(&self.files.render()); + value.push_str(&self.meta_data.render()); + value.push_str(&self.directories.render()); + value.push_str(&self.soft_links.render()); + value.push_str(&self.hard_links.render()); + value.push_str(&self.special_files.render()); + value.push_str(&self.grand_total.render()); + value.push_str(&self.bytes_estimated.render()); + value.push_str(&self.bytes.render()); + value.push_str(&self.bytes_received.render()); + value.push_str(&self.bytes_sent.render()); + value.push_str(&self.elapsed_time.render()); + value + } +} + +/// Get current BURP metrics +/// +/// This function returns the current BURP metrics as a string, in +/// Prometheus plain text exposition format. +pub async fn get_metrics(client: &mut Client) -> Result { + let mut metrics = Metrics::new(); + for c in client.get_clients().await?.clients { + if let Some(b) = c.backups.iter().next() { + metrics.add_backup(&c.name, b.number, b.timestamp); + match client.get_backup_stats(&c.name, b.number).await { + Ok(s) => { + if let Some(s) = s { + metrics.add_stats(c.name, &s); + } + } + Err(e) => { + error!( + "Could not get backup for client {}: {}", + &c.name, e + ); + } + } + }; + } + Ok(metrics.to_string()) +}