diff --git a/docs/monitoring/prometheus.yml b/docs/monitoring/prometheus.yml index 26eb585..db4e34e 100644 --- a/docs/monitoring/prometheus.yml +++ b/docs/monitoring/prometheus.yml @@ -13,4 +13,4 @@ scrape_configs: scrape_interval: 1s static_configs: - - targets: ['localhost:9273'] \ No newline at end of file + - targets: ['telegraf:9273'] \ No newline at end of file diff --git a/usertools/monitoring/docker-compose.yml b/usertools/monitoring/docker-compose.yml new file mode 100644 index 0000000..a67491c --- /dev/null +++ b/usertools/monitoring/docker-compose.yml @@ -0,0 +1,27 @@ +version: '3.8' +services: + telegraf: + image: telegraf:latest + volumes: + - ./telegraf.conf:/etc/telegraf/telegraf.conf:ro + networks: + - monitoring + + prometheus: + image: prom/prometheus:latest + volumes: + - ./prometheus.yml:/etc/prometheus/prometheus.yml + command: + - '--config.file=/etc/prometheus/prometheus.yml' + networks: + - monitoring + + grafana: + image: grafana/grafana:latest + ports: + - "3000:3000" + networks: + - monitoring + +networks: + monitoring: diff --git a/usertools/monitoring/docker.sh b/usertools/monitoring/docker.sh new file mode 100644 index 0000000..0ddd77e --- /dev/null +++ b/usertools/monitoring/docker.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +# create docker image +docker build -t lf-monitoring -f monitoring.Dockerfile . + +# create docker container +docker create --name lf-monitoring --net=host lf-monitoring + +# start docker container +docker start lf-monitoring \ No newline at end of file diff --git a/usertools/monitoring/lf-monitor/.gitignore b/usertools/monitoring/lf-monitor/.gitignore new file mode 100644 index 0000000..c41cc9e --- /dev/null +++ b/usertools/monitoring/lf-monitor/.gitignore @@ -0,0 +1 @@ +/target \ No newline at end of file diff --git a/usertools/monitoring/lf-monitor/Cargo.lock b/usertools/monitoring/lf-monitor/Cargo.lock new file mode 100644 index 0000000..9d2d3dc --- /dev/null +++ b/usertools/monitoring/lf-monitor/Cargo.lock @@ -0,0 +1,783 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "anstream" +version = "0.6.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" + +[[package]] +name = "anstyle-parse" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" +dependencies = [ + "anstyle", + "windows-sys 0.52.0", +] + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "base64" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" +dependencies = [ + "byteorder", + "safemem", +] + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "clap" +version = "4.5.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e5a21b8495e732f1b3c364c9949b201ca7bae518c502c80256c96ad79eaf6ac" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cf2dd12af7a047ad9d6da2b6b249759a22a7abc0f474c1dae1777afa4b21a73" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" + +[[package]] +name = "colorchoice" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" + +[[package]] +name = "ctrlc" +version = "3.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90eeab0aa92f3f9b4e87f258c72b139c207d251f9cbc1080a0086b86a8870dd3" +dependencies = [ + "nix", + "windows-sys 0.59.0", +] + +[[package]] +name = "dtoa" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcbb2bf8e87535c23f7a8a321e364ce21462d0ff10cb6407820e8e96dfff6653" + +[[package]] +name = "groupable" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32619942b8be646939eaf3db0602b39f5229b74575b67efc897811ded1db4e57" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "httparse" +version = "1.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" + +[[package]] +name = "hyper" +version = "0.10.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a0652d9a2609a968c14be1a9ea00bf4b1d64e2e1f53a1b51b6fff3a6e829273" +dependencies = [ + "base64", + "httparse", + "language-tags", + "log 0.3.9", + "mime", + "num_cpus", + "time", + "traitobject", + "typeable", + "unicase", + "url", +] + +[[package]] +name = "idna" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" +dependencies = [ + "matches", + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "language-tags" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "lf-monitor" +version = "0.1.0" +dependencies = [ + "clap", + "ctrlc", + "nickel", + "prometheus-client", + "serde", + "serde_json", + "uds", +] + +[[package]] +name = "libc" +version = "0.2.158" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" +dependencies = [ + "log 0.4.22", +] + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "matches" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "mime" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0" +dependencies = [ + "log 0.3.9", +] + +[[package]] +name = "modifier" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41f5c9112cb662acd3b204077e0de5bc66305fa8df65c8019d5adb10e9ab6e58" + +[[package]] +name = "mustache" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51956ef1c5d20a1384524d91e616fb44dfc7d8f249bf696d49c97dd3289ecab5" +dependencies = [ + "log 0.3.9", + "serde", +] + +[[package]] +name = "nickel" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5061a832728db2dacb61cefe0ce303b58f85764ec680e71d9138229640a46d9" +dependencies = [ + "groupable", + "hyper", + "lazy_static", + "log 0.3.9", + "modifier", + "mustache", + "plugin", + "regex", + "serde", + "serde_json", + "time", + "typemap", + "url", +] + +[[package]] +name = "nix" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" +dependencies = [ + "bitflags", + "cfg-if", + "cfg_aliases", + "libc", +] + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets", +] + +[[package]] +name = "percent-encoding" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" + +[[package]] +name = "plugin" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a6a0dc3910bc8db877ffed8e457763b317cf880df4ae19109b9f77d277cf6e0" +dependencies = [ + "typemap", +] + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "prometheus-client" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d6fa99d535dd930d1249e6c79cb3c2915f9172a540fe2b02a4c8f9ca954721e" +dependencies = [ + "dtoa", + "itoa", + "parking_lot", + "prometheus-client-derive-encode", +] + +[[package]] +name = "prometheus-client-derive-encode" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "redox_syscall" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" +dependencies = [ + "bitflags", +] + +[[package]] +name = "regex" +version = "1.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "safemem" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "serde" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.127" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8043c06d9f82bd7271361ed64f415fe5e12a77fdb52e573e7f06a516dea329ad" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "syn" +version = "2.0.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6af063034fc1935ede7be0122941bafa9bacb949334d090b77ca98b5817c7d9" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "time" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" +dependencies = [ + "libc", + "wasi", + "winapi", +] + +[[package]] +name = "tinyvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "traitobject" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" + +[[package]] +name = "typeable" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" + +[[package]] +name = "typemap" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "653be63c80a3296da5551e1bfd2cca35227e13cdd08c6668903ae2f4f77aa1f6" +dependencies = [ + "unsafe-any", +] + +[[package]] +name = "uds" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "885c31f06fce836457fe3ef09a59f83fe8db95d270b11cd78f40a4666c4d1661" +dependencies = [ + "libc", +] + +[[package]] +name = "unicase" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" +dependencies = [ + "version_check", +] + +[[package]] +name = "unicode-bidi" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-normalization" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unsafe-any" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f30360d7979f5e9c6e6cea48af192ea8fab4afb3cf72597154b8f08935bc9c7f" +dependencies = [ + "traitobject", +] + +[[package]] +name = "url" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" +dependencies = [ + "idna", + "matches", + "percent-encoding", +] + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "version_check" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" + +[[package]] +name = "wasi" +version = "0.10.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[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.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" diff --git a/usertools/monitoring/lf-monitor/Cargo.toml b/usertools/monitoring/lf-monitor/Cargo.toml new file mode 100644 index 0000000..3655fcc --- /dev/null +++ b/usertools/monitoring/lf-monitor/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "lf-monitor" +version = "0.1.0" +edition = "2021" + +[dependencies] +clap = { version = "4.5.17", features = ["derive"] } +ctrlc = "3.4.5" +nickel = "0.11.0" +prometheus-client = "0.19.0" +serde = "1.0.210" +serde_json = "1.0.127" +uds = "0.4.2" diff --git a/usertools/monitoring/lf-monitor/README.md b/usertools/monitoring/lf-monitor/README.md new file mode 100644 index 0000000..b0df642 --- /dev/null +++ b/usertools/monitoring/lf-monitor/README.md @@ -0,0 +1,28 @@ +# Lightning-Filter Monitoring System + +The lf-monitor collects and stores metrics from the Lightning-Filter system and +provides a prometheus API endpoint for querying the metrics. +It is a standalone service written in Rust. + +## Running the service + +You can compile and run the service using the following commands: + +```bash +cargo build +sudo ./target/debug/lf-monitor --dpdk-file-prefix lf0 +``` + +Replace `lf0` with the correct dpdk file prefix for your running Lightning-Filter instance. + +Note: We do not recommend running the service with `cargo run` because you should +not run cargo as root. + +## Dependencies + +To run the rust code or compile it, you need to have the rust toolchain installed. +You can install the rust toolchain using the following command: + +```bash +curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh +``` diff --git a/usertools/monitoring/lf-monitor/src/collector.rs b/usertools/monitoring/lf-monitor/src/collector.rs new file mode 100644 index 0000000..0bc3ea5 --- /dev/null +++ b/usertools/monitoring/lf-monitor/src/collector.rs @@ -0,0 +1,154 @@ +use serde_json::Value; +use std::thread; + +use crate::dpdk::DpdkTelemetry; +use crate::prometheus::{ + CollectorCountLabel, EthdevStatsLabels, LFKeymanagerDictLabels, LFKeymanagerStatsLabels, + LFWorkerStatsLabels, PrometheusMetrics, +}; + +pub struct Collector { + dpdk_telemetry: DpdkTelemetry, + prometheus_metrics: PrometheusMetrics, + period: std::time::Duration, +} + +impl Collector { + pub fn new(dpdk_telemetry: DpdkTelemetry, prometheus_metrics: PrometheusMetrics) -> Self { + Collector { + dpdk_telemetry: dpdk_telemetry, + prometheus_metrics: prometheus_metrics, + // Default + period: std::time::Duration::from_secs(1), + } + } + + pub fn run(&self) { + loop { + self.collect(); + thread::sleep(self.period); + } + } + + fn collect(&self) { + self.collect_ethdev(); + self.collect_lf(); + self.prometheus_metrics + .collector_count_total + .metric + .get_or_create(&CollectorCountLabel { + result: "success".to_string(), + }) + .inc(); + } + + fn collect_ethdev(&self) { + // parameter list for ethdev metrics + let list: Value = self.dpdk_telemetry.query("/ethdev/list"); + let intfs = list["/ethdev/list"].as_array().unwrap(); + + for intf in intfs { + // Get interface name from info + let info_path = ["/ethdev/info", &intf.to_string()].join(","); + let info_result = self.dpdk_telemetry.query(&info_path); + let info = info_result["/ethdev/info"].as_object().unwrap(); + let intf_name = info["name"].as_str().unwrap(); + + // Get stats + let stats_path = ["/ethdev/stats", &intf.to_string()].join(","); + let result = self.dpdk_telemetry.query(&stats_path); + let stats = result["/ethdev/stats"].as_object().unwrap(); + for (key, value) in stats { + if !value.is_number() { + continue; + } + let value = value.as_i64().unwrap(); + let labels = EthdevStatsLabels { + port_id: intf.as_i64().unwrap() as i16, + port_name: intf_name.to_string(), + metric: key.to_string(), + }; + let counter = self + .prometheus_metrics + .ethdev_stats + .metric + .get_or_create(&labels); + counter.set(value); + } + } + } + + fn collect_lf(&self) { + self.collect_lf_worker(); + self.collect_lf_keymanager(); + } + + fn collect_lf_worker(&self) { + // Obtain the list of workers: get the the number of eal lcores and subtract the master and + // keymanager cores. + let result = self.dpdk_telemetry.query("/eal/lcore/list"); + let lcores = result["/eal/lcore/list"].as_array().unwrap(); + let num_workers = lcores.len() - 2; + + for i in 0..num_workers { + let result = self + .dpdk_telemetry + .query(&format!("/lf/worker/stats,{}", i)); + let stats = result["/lf/worker/stats"].as_object().unwrap(); + for (key, value) in stats { + if !value.is_number() { + continue; + } + let value = value.as_i64().unwrap(); + let labels = LFWorkerStatsLabels { + worker_id: i as i16, + metric: key.to_string(), + }; + let counter = self + .prometheus_metrics + .lf_worker_stats + .metric + .get_or_create(&labels); + counter.set(value); + } + } + } + + fn collect_lf_keymanager(&self) { + let result = self.dpdk_telemetry.query("/lf/keymanager/stats"); + let stats = result["/lf/keymanager/stats"].as_object().unwrap(); + for (key, value) in stats { + if !value.is_number() { + continue; + } + let value = value.as_i64().unwrap(); + let labels = LFKeymanagerStatsLabels { + result: key.to_string(), + }; + let counter = self + .prometheus_metrics + .lf_keymanager_stats + .metric + .get_or_create(&labels); + counter.set(value); + } + + let result = self.dpdk_telemetry.query("/lf/keymanager/dict"); + let dict = result["/lf/keymanager/dict"].as_object().unwrap(); + for (key, value) in dict { + if !value.is_number() { + continue; + } + let value = value.as_i64().unwrap(); + let labels = LFKeymanagerDictLabels { + key: key.to_string(), + }; + let counter = self + .prometheus_metrics + .lf_keymanager_dict + .metric + .get_or_create(&labels); + counter.set(value); + } + } +} diff --git a/usertools/monitoring/lf-monitor/src/dpdk.rs b/usertools/monitoring/lf-monitor/src/dpdk.rs new file mode 100644 index 0000000..cf390fb --- /dev/null +++ b/usertools/monitoring/lf-monitor/src/dpdk.rs @@ -0,0 +1,72 @@ +use uds::UnixSeqpacketConn; +use serde_json::Value; + + +#[derive(Debug)] +pub struct DpdkTelemetry { + socket_path: String, + socket: UnixSeqpacketConn, + dpdk_version: String, + dpdk_pid: i64, + max_output_len: i64, +} + +impl DpdkTelemetry { + pub fn new(file_prefix: String) -> Self { + let runtime_dir: String = get_dpdk_runtime_dir(&file_prefix); + let socket_path: String = format!("{}/dpdk_telemetry.v2", runtime_dir); + + // Check if socket exists by reading from it + let socket: UnixSeqpacketConn = UnixSeqpacketConn::connect(socket_path.clone()).unwrap(); + let mut buff: [u8; 16384] = [0u8; 16384]; + socket.recv(&mut buff).unwrap(); + let response: String = String::from_utf8(buff.to_vec()).unwrap(); + // remove trailing null bytes + let response: String = response.trim_matches(char::from(0)).to_string(); + let dpdk_info: Value = serde_json::from_str(&response).unwrap(); + + DpdkTelemetry { + socket_path: socket_path, + socket: socket, + dpdk_version: dpdk_info["version"].to_string(), + dpdk_pid: dpdk_info["pid"].as_i64().unwrap(), + max_output_len: dpdk_info["max_output_len"].as_i64().unwrap(), + } + } + + pub fn query(&self, query: &str) -> serde_json::Value { + self.socket.send(query.as_bytes()).unwrap(); + + // XXX: For now, we assume that max buffer length is 16384 (which seems to be the DPDK + // telementry default). + let mut buff: [u8; 16384] = [0u8; 16384]; + let mut result: String = String::from(""); + loop { + let n: usize = self.socket.recv(&mut buff).unwrap(); + if n == 0 { + break; + } + let string_result = std::str::from_utf8(&buff[..n]).unwrap(); + result.push_str(string_result); + + // XXX: In case the buffer is not long enough, we might have to call recv again. + // However, I was not able to implement this behavior. + break; + } + + // Parse JSON response + let v: Value = serde_json::from_str(&result).unwrap(); + return v; + } +} + +impl Drop for DpdkTelemetry { + fn drop(&mut self) { + let _ = self.socket.shutdown(std::net::Shutdown::Both); + } +} + +fn get_dpdk_runtime_dir(dpdk_file_prefix: &str) -> String { + let dpdk_runtime_dir = format!("/var/run/dpdk/{}", dpdk_file_prefix); + return dpdk_runtime_dir; +} diff --git a/usertools/monitoring/lf-monitor/src/main.rs b/usertools/monitoring/lf-monitor/src/main.rs new file mode 100644 index 0000000..217ad21 --- /dev/null +++ b/usertools/monitoring/lf-monitor/src/main.rs @@ -0,0 +1,57 @@ +#[macro_use] extern crate nickel; +use prometheus_client::encoding::text::encode; +use prometheus_client::registry::Registry; +use nickel::{Nickel, HttpRouter}; +use clap::Parser; + +mod prometheus; +mod collector; +mod dpdk; + +use prometheus::PrometheusMetrics; +use collector::Collector; +use dpdk::DpdkTelemetry; + +#[derive(Parser, Debug)] +#[command(version, about, long_about = None)] +struct Args { + /// Address and port to expose the metrics + #[arg(short, long, default_value = "0.0.0.0:8080")] + address: String, + + /// Path to expose the metrics + #[arg(short, long, default_value = "/metrics")] + path: String, + + /// DPDK file prefix for determine DPDK runtime directory + #[arg(short, long)] + dpdk_file_prefix: String, +} + +fn main() { + + let args = Args::parse(); + + // Create DPDK Telemetry object + let dpdk_telemetry: DpdkTelemetry = DpdkTelemetry::new(args.dpdk_file_prefix); + println!("{:?}", dpdk_telemetry); + + // Create Prometheus metrics + let prometheus_metrics: PrometheusMetrics = PrometheusMetrics::new(); + let registry: Registry = prometheus::new_registry(&prometheus_metrics); + + // Create metric collector and start it + let collector: Collector = Collector::new(dpdk_telemetry, prometheus_metrics); + std::thread::spawn(move || collector.run()); + + // Start HTTP server + let mut server: Nickel = Nickel::new(); + server.get(args.path, middleware! { + let mut buffer = String::new(); + encode(&mut buffer, ®istry).unwrap(); + buffer + }); + server.listen(args.address).unwrap(); + +} + diff --git a/usertools/monitoring/lf-monitor/src/prometheus.rs b/usertools/monitoring/lf-monitor/src/prometheus.rs new file mode 100644 index 0000000..6ee5a56 --- /dev/null +++ b/usertools/monitoring/lf-monitor/src/prometheus.rs @@ -0,0 +1,102 @@ +use prometheus_client::encoding::EncodeLabelSet; +use prometheus_client::metrics::family::Family; +use prometheus_client::metrics::gauge::Gauge; +use prometheus_client::registry::{Metric, Registry}; + +pub struct PrometheusMetrics { + pub collector_count_total: PrometheusMetric>, + pub ethdev_stats: PrometheusMetric>, + pub lf_worker_stats: PrometheusMetric>, + pub lf_keymanager_stats: PrometheusMetric>, + pub lf_keymanager_dict: PrometheusMetric>, +} + +impl PrometheusMetrics { + pub fn new() -> Self { + PrometheusMetrics { + collector_count_total: PrometheusMetric { + name: "lf_monitor_collecting_total".to_string(), + help: "Number of times the lf-monitor has collected stats".to_string(), + metric: Family::default(), + }, + ethdev_stats: PrometheusMetric { + name: "dpdk_ethdev_stats".to_string(), + help: "DPDK ethdev statistics".to_string(), + metric: Family::default(), + }, + lf_worker_stats: PrometheusMetric { + name: "dpdk_lf_worker_stats".to_string(), + help: "DPDK LF worker statistics".to_string(), + metric: Family::default(), + }, + lf_keymanager_stats: PrometheusMetric { + name: "dpdk_lf_keymanager_stats".to_string(), + help: "DPDK LF keymanager statistics".to_string(), + metric: Family::default(), + }, + lf_keymanager_dict: PrometheusMetric { + name: "dpdk_lf_keymanager_dict".to_string(), + help: "DPDK LF keymanager dictionary statistics".to_string(), + metric: Family::default(), + }, + } + } +} + +pub struct PrometheusMetric { + pub name: String, + pub help: String, + pub metric: T, +} + +#[derive(Clone, Debug, Hash, PartialEq, Eq, EncodeLabelSet)] +pub struct CollectorCountLabel { + pub result: String, +} + +#[derive(Clone, Debug, Hash, PartialEq, Eq, EncodeLabelSet)] +pub struct EthdevStatsLabels { + pub port_id: i16, + pub port_name: String, + pub metric: String, +} + +#[derive(Clone, Debug, Hash, PartialEq, Eq, EncodeLabelSet)] +pub struct LFWorkerStatsLabels { + pub worker_id: i16, + pub metric: String, +} + + + +#[derive(Clone, Debug, Hash, PartialEq, Eq, EncodeLabelSet)] +pub struct LFKeymanagerStatsLabels { + pub result: String, +} + +#[derive(Clone, Debug, Hash, PartialEq, Eq, EncodeLabelSet)] +pub struct LFKeymanagerDictLabels { + pub key: String, +} + +pub fn new_registry(metrics : &PrometheusMetrics) -> Registry { + let mut registry = Registry::default(); + register_metrics(&mut registry, metrics); + registry +} + +fn register_metrics(registry: &mut Registry, metrics : &PrometheusMetrics) { + register_metric(registry, &metrics.collector_count_total); + register_metric(registry, &metrics.ethdev_stats); + register_metric(registry, &metrics.lf_worker_stats); + register_metric(registry, &metrics.lf_keymanager_stats); + register_metric(registry, &metrics.lf_keymanager_dict); +} + +fn register_metric(registry: &mut Registry, metric: &PrometheusMetric) { + registry.register( + metric.name.to_string(), + metric.help.to_string(), + metric.metric.clone(), + ); +} \ No newline at end of file diff --git a/usertools/monitoring/prometheus.yml b/usertools/monitoring/prometheus.yml new file mode 100644 index 0000000..9f7bb80 --- /dev/null +++ b/usertools/monitoring/prometheus.yml @@ -0,0 +1,12 @@ +global: + scrape_interval: 15s + + external_labels: + monitor: 'lf-monitor' + +scrape_configs: + - job_name: 'lightningfilter' + # Override the global default and scrape targets from this job every 5 seconds. + scrape_interval: 1s + static_configs: + - targets: ['telegraf:9273'] diff --git a/usertools/monitoring/rust.md b/usertools/monitoring/rust.md new file mode 100644 index 0000000..f1d2fdb --- /dev/null +++ b/usertools/monitoring/rust.md @@ -0,0 +1,11 @@ + + +## Install Rust + +```bash +curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh +``` + +## Rust Prometheus Client + +https://www.youtube.com/watch?v=x51zfjeVaR0 \ No newline at end of file diff --git a/usertools/monitoring/telegraf.conf b/usertools/monitoring/telegraf.conf new file mode 100644 index 0000000..e10ef31 --- /dev/null +++ b/usertools/monitoring/telegraf.conf @@ -0,0 +1,62 @@ +[agent] + interval = "10s" + round_interval = true + metric_batch_size = 1000 + metric_buffer_limit = 10000 + collection_jitter = "0s" + flush_interval = "10s" + flush_jitter = "0s" + precision = "" + debug = false + quiet = false + logfile = "" + +############################################################################### +# OUTPUT PLUGINS # +############################################################################### + +# Transmit metrics over HTTP to Grafana +#[[outputs.http]] +# url = "http://localhost:3000/api/live/push/lf0" +# data_format = "influx" +# [outputs.http.headers] +# Authorization = "Bearer eyJrIjoiZnA4Y25LVFkzMXRHZmZ6SlU3UU1QUnB2NVZTNVdEMkIiLCJuIjoiVGVsZWdyYWYiLCJpZCI6MX0=" + + +[[outputs.prometheus_client]] + ## Address to listen on. + listen = ":9273" + string_as_label = true + +############################################################################### +# INPUT PLUGINS # +############################################################################### + +# Read metrics about cpu usage +[[inputs.cpu]] + ## Whether to report per-cpu stats or not + percpu = true + ## Whether to report total system cpu stats or not + totalcpu = true + ## If true, collect raw CPU time metrics + collect_cpu_time = false + ## If true, compute and report the sum of all non-idle CPU states + report_active = false + ## If true and the info is available then add core_id and physical_id tags + core_tags = false + +# Read metrics about memory usage +[[inputs.mem]] + # no configuration + +# Get the number of processes and group them by status +[[inputs.processes]] + # no configuration + +# Read metrics about swap memory usage +[[inputs.swap]] + # no configuration + +# Read metrics about system load & uptime +[[inputs.system]] + # no configuration \ No newline at end of file