mirror of
https://github.com/orhun/systeroid
synced 2024-09-30 04:33:31 +00:00
feat(tui): improve logging (#83)
* chore(deps): add logging dependencies * refactor(cli): use log functions for logging * refactor(core): use log functions for logging * feat(tui): add logging for tui * feat(args): add an option for setting the log file for TUI logs * chore(core): add trace logging * fix(cli): make log level configurable via RUST_LOG * chore(log): improve logging * chore(tui): add logs to specific events * style(tui): update the colors for the logger widget * feat(log): allow setting the log level for tui * chore(config)!: remove the verbose option * fix(test): update render tui test * chore(tui): update MSRV for tui * chore(audit): add configuration file for cargo-audit * chore: Bump the Rust version in Dockerfile * feat(log): add target to logs * docs(readme): update documentation about logging
This commit is contained in:
parent
80be6c5053
commit
3ace96419c
8
.cargo/audit.toml
Normal file
8
.cargo/audit.toml
Normal file
|
@ -0,0 +1,8 @@
|
|||
[advisories]
|
||||
ignore = [
|
||||
"RUSTSEC-2020-0071", # `chrono` - Potential segfault in the time crate
|
||||
]
|
||||
|
||||
[output]
|
||||
quiet = false
|
||||
deny = ["warnings"]
|
536
Cargo.lock
generated
536
Cargo.lock
generated
|
@ -28,6 +28,15 @@ dependencies = [
|
|||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "android_system_properties"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atty"
|
||||
version = "0.2.14"
|
||||
|
@ -67,6 +76,12 @@ dependencies = [
|
|||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.4.3"
|
||||
|
@ -79,12 +94,33 @@ version = "0.3.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.79"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b"
|
||||
dependencies = [
|
||||
"iana-time-zone",
|
||||
"js-sys",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
"time",
|
||||
"wasm-bindgen",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clipboard-win"
|
||||
version = "3.1.1"
|
||||
|
@ -95,6 +131,16 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "codespan-reporting"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e"
|
||||
dependencies = [
|
||||
"termcolor",
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "colored"
|
||||
version = "2.0.0"
|
||||
|
@ -138,6 +184,12 @@ dependencies = [
|
|||
"x11-clipboard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation-sys"
|
||||
version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa"
|
||||
|
||||
[[package]]
|
||||
name = "crc32fast"
|
||||
version = "1.3.2"
|
||||
|
@ -190,6 +242,50 @@ dependencies = [
|
|||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cxx"
|
||||
version = "1.0.94"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f61f1b6389c3fe1c316bf8a4dccc90a38208354b330925bce1f74a6c4756eb93"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cxxbridge-flags",
|
||||
"cxxbridge-macro",
|
||||
"link-cplusplus",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cxx-build"
|
||||
version = "1.0.94"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "12cee708e8962df2aeb38f594aae5d827c022b6460ac71a7a3e2c3c2aae5a07b"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"codespan-reporting",
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"scratch",
|
||||
"syn 2.0.15",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cxxbridge-flags"
|
||||
version = "1.0.94"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7944172ae7e4068c533afbb984114a56c46e9ccddda550499caa222902c7f7bb"
|
||||
|
||||
[[package]]
|
||||
name = "cxxbridge-macro"
|
||||
version = "1.0.94"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2345488264226bf682893e25de0769f3360aac9957980ec49361b083ddaa5bc5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.15",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs-next"
|
||||
version = "2.0.0"
|
||||
|
@ -250,6 +346,40 @@ dependencies = [
|
|||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "env_logger"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0"
|
||||
dependencies = [
|
||||
"humantime",
|
||||
"is-terminal",
|
||||
"log",
|
||||
"regex",
|
||||
"termcolor",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a"
|
||||
dependencies = [
|
||||
"errno-dragonfly",
|
||||
"libc",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "errno-dragonfly"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.0.25"
|
||||
|
@ -266,6 +396,15 @@ version = "1.0.7"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||
|
||||
[[package]]
|
||||
name = "fxhash"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gethostname"
|
||||
version = "0.2.3"
|
||||
|
@ -293,7 +432,7 @@ checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4"
|
|||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -353,6 +492,42 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
|
||||
|
||||
[[package]]
|
||||
name = "humantime"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone"
|
||||
version = "0.1.56"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0722cd7114b7de04316e7ea5456a0bbb20e4adb46fd27a3697adb812cff0f37c"
|
||||
dependencies = [
|
||||
"android_system_properties",
|
||||
"core-foundation-sys",
|
||||
"iana-time-zone-haiku",
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone-haiku"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca"
|
||||
dependencies = [
|
||||
"cxx",
|
||||
"cxx-build",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ignore"
|
||||
version = "0.4.20"
|
||||
|
@ -370,12 +545,44 @@ dependencies = [
|
|||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "io-lifetimes"
|
||||
version = "1.0.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220"
|
||||
dependencies = [
|
||||
"hermit-abi 0.3.1",
|
||||
"libc",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "is-terminal"
|
||||
version = "0.4.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f"
|
||||
dependencies = [
|
||||
"hermit-abi 0.3.1",
|
||||
"io-lifetimes",
|
||||
"rustix",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.61"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730"
|
||||
dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy-bytes-cast"
|
||||
version = "5.0.1"
|
||||
|
@ -404,6 +611,31 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "link-cplusplus"
|
||||
version = "1.0.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b085a4f2cde5781fc4b1717f2e86c62f5cda49de7ba99a7c2eae02b61c9064c"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.17"
|
||||
|
@ -492,6 +724,25 @@ dependencies = [
|
|||
"minimal-lexical",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "1.15.0"
|
||||
|
@ -553,6 +804,29 @@ dependencies = [
|
|||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
|
||||
dependencies = [
|
||||
"lock_api",
|
||||
"parking_lot_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot_core"
|
||||
version = "0.9.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"smallvec",
|
||||
"windows-sys 0.45.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parseit"
|
||||
version = "0.1.2"
|
||||
|
@ -680,6 +954,20 @@ dependencies = [
|
|||
"ordered-multimap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.37.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f79bef90eb6d984c72722595b5b1348ab39275a5e5123faca6863bf07d75a4e0"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"errno",
|
||||
"io-lifetimes",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.13"
|
||||
|
@ -707,6 +995,12 @@ version = "1.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||
|
||||
[[package]]
|
||||
name = "scratch"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1792db035ce95be60c3f8853017b3999209281c24e2ba5bc8e59bf97a0c590c1"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.160"
|
||||
|
@ -812,7 +1106,9 @@ dependencies = [
|
|||
name = "systeroid"
|
||||
version = "0.3.2"
|
||||
dependencies = [
|
||||
"env_logger",
|
||||
"getopts",
|
||||
"log",
|
||||
"parseit",
|
||||
"systeroid-core",
|
||||
]
|
||||
|
@ -824,6 +1120,7 @@ dependencies = [
|
|||
"colored",
|
||||
"dirs-next",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"parseit",
|
||||
"rayon",
|
||||
"rust-ini",
|
||||
|
@ -840,13 +1137,24 @@ dependencies = [
|
|||
"colorsys",
|
||||
"copypasta-ext",
|
||||
"getopts",
|
||||
"log",
|
||||
"ratatui",
|
||||
"systeroid-core",
|
||||
"termion",
|
||||
"thiserror",
|
||||
"tui-logger",
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termcolor"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6"
|
||||
dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termion"
|
||||
version = "2.0.1"
|
||||
|
@ -889,6 +1197,31 @@ dependencies = [
|
|||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.1.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"wasi 0.10.0+wasi-snapshot-preview1",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tui-logger"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4b9e708d73f97e548b2d6e75f9931aff915a5b8bbad8fc7c7a63273994af6b5b"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"fxhash",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"parking_lot",
|
||||
"ratatui",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.8"
|
||||
|
@ -923,12 +1256,72 @@ dependencies = [
|
|||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.10.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.84"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"wasm-bindgen-macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.84"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"log",
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.84"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.84"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.84"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d"
|
||||
|
||||
[[package]]
|
||||
name = "wayland-client"
|
||||
version = "0.29.5"
|
||||
|
@ -1053,6 +1446,147 @@ version = "0.4.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f"
|
||||
dependencies = [
|
||||
"windows-targets 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.45.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
|
||||
dependencies = [
|
||||
"windows-targets 0.42.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
||||
dependencies = [
|
||||
"windows-targets 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm 0.42.2",
|
||||
"windows_aarch64_msvc 0.42.2",
|
||||
"windows_i686_gnu 0.42.2",
|
||||
"windows_i686_msvc 0.42.2",
|
||||
"windows_x86_64_gnu 0.42.2",
|
||||
"windows_x86_64_gnullvm 0.42.2",
|
||||
"windows_x86_64_msvc 0.42.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm 0.48.0",
|
||||
"windows_aarch64_msvc 0.48.0",
|
||||
"windows_i686_gnu 0.48.0",
|
||||
"windows_i686_msvc 0.48.0",
|
||||
"windows_x86_64_gnu 0.48.0",
|
||||
"windows_x86_64_gnullvm 0.48.0",
|
||||
"windows_x86_64_msvc 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
|
||||
|
||||
[[package]]
|
||||
name = "x11-clipboard"
|
||||
version = "0.7.1"
|
||||
|
|
|
@ -3,6 +3,7 @@ members = ["systeroid-core", "systeroid-tui", "systeroid"]
|
|||
|
||||
[workspace.dependencies]
|
||||
parseit = { version = "0.1.2", features = ["gzip"] }
|
||||
log = { version = "0.4.17", features = ["std"] }
|
||||
|
||||
[profile.dev]
|
||||
opt-level = 0
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
FROM rust:1.66.1-alpine3.17 as builder
|
||||
FROM rust:1.69.0-alpine3.17 as builder
|
||||
WORKDIR /app
|
||||
RUN apk update
|
||||
RUN apk add --no-cache musl-dev bash git
|
||||
|
|
85
README.md
85
README.md
|
@ -77,6 +77,7 @@ Although **systeroid** does not need the parameter section to be specified expli
|
|||
- [Loading values from the system directories](#loading-values-from-the-system-directories)
|
||||
- [Searching parameters](#searching-parameters)
|
||||
- [Showing information about parameters](#showing-information-about-parameters)
|
||||
- [Verbose logging](#verbose-logging)
|
||||
- [TUI](#tui)
|
||||
- [Usage](#usage-2)
|
||||
- [Key Bindings](#key-bindings)
|
||||
|
@ -93,6 +94,7 @@ Although **systeroid** does not need the parameter section to be specified expli
|
|||
- [Changing the colors](#changing-the-colors)
|
||||
- [Viewing the parameter documentation](#viewing-the-parameter-documentation)
|
||||
- [Setting the refresh rate](#setting-the-refresh-rate)
|
||||
- [Logging](#logging)
|
||||
- [Configuration](#configuration)
|
||||
- [Resources](#resources)
|
||||
- [References](#references)
|
||||
|
@ -398,6 +400,20 @@ It is also possible to retrieve information about multiple parameters:
|
|||
systeroid -E --pattern '.*ipv4.*' --no-pager
|
||||
```
|
||||
|
||||
#### Verbose logging
|
||||
|
||||
`--verbose` flag can be used to enable verbose logging:
|
||||
|
||||
```sh
|
||||
systeroid --verbose
|
||||
```
|
||||
|
||||
Also, `RUST_LOG` environment variable can be set accordingly to filter based on different log levels.
|
||||
|
||||
```sh
|
||||
RUST_LOG=trace systeroid
|
||||
```
|
||||
|
||||
## TUI
|
||||
|
||||
### Usage
|
||||
|
@ -440,6 +456,7 @@ systeroid-tui [options]
|
|||
| <kbd>enter</kbd> | select / set parameter value |
|
||||
| <kbd>s</kbd> | save parameter value |
|
||||
| <kbd>c</kbd> | copy to clipboard |
|
||||
| <kbd>ctrl-l</kbd>, <kbd>f2</kbd> | show logs |
|
||||
| <kbd>r</kbd>, <kbd>f5</kbd> | refresh |
|
||||
| <kbd>esc</kbd> | cancel / exit |
|
||||
| <kbd>q</kbd>, <kbd>ctrl-c/ctrl-d</kbd> | exit |
|
||||
|
@ -524,15 +541,16 @@ Press <kbd>:</kbd> to open the command prompt for running a command. Available c
|
|||
|
||||
| Command | Description |
|
||||
| ------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `:help` | Show help |
|
||||
| `:search` | Enable search |
|
||||
| `:select` | Select the current parameter in the list |
|
||||
| `:set <name> <value>` | Set parameter value |
|
||||
| `:save <name> <value>` | Save parameter value to file |
|
||||
| `:scroll [area] [direction] <amount>` | Scroll the list or text<br>- areas: `list`, `docs`, `section`<br>- directions: `up`, `down`, `top`, `bottom`, `right`, `left` |
|
||||
| `:copy` | Copy to clipboard |
|
||||
| `:refresh` | Refresh values |
|
||||
| `:quit`, `:q` | Quit |
|
||||
| `:help` | show help |
|
||||
| `:search` | enable search |
|
||||
| `:select` | select the current parameter in the list |
|
||||
| `:set <name> <value>` | set parameter value |
|
||||
| `:save <name> <value>` | save parameter value to file |
|
||||
| `:scroll [area] [direction] <amount>` | scroll the list or text<br>- areas: `list`, `docs`, `section`<br>- directions: `up`, `down`, `top`, `bottom`, `right`, `left` |
|
||||
| `:copy` | copy to clipboard |
|
||||
| `:logs` | show logs |
|
||||
| `:refresh` | refresh values |
|
||||
| `:quit`, `:q` | quit |
|
||||
|
||||
#### Copying to clipboard
|
||||
|
||||
|
@ -570,6 +588,55 @@ It is possible to specify a value in milliseconds via `--tick-rate` argument for
|
|||
systeroid-tui --tick-rate 500
|
||||
```
|
||||
|
||||
#### Logging
|
||||
|
||||
To view the log messages, press <kbd>ctrl-l</kbd>. It will bring up a pane in the TUI for analyzing the logs:
|
||||
|
||||
![Logs](assets/systeroid-tui-logs.gif)
|
||||
|
||||
This pane consists of two parts. Left is the target selector and on the right side the logging messages view scrolling up.
|
||||
|
||||
The target selector controls:
|
||||
|
||||
- Capturing of log messages by the logger.
|
||||
- Selection of levels for display in the logging message view.
|
||||
|
||||
The two columns have the following meaning:
|
||||
|
||||
- Code `EWIDT`: `E` stands for Error, `W` for Warn, and similarly Info, Debug and Trace.
|
||||
- Inverted characters (EWIDT) are enabled log levels in the view.
|
||||
- Normal characters show enabled capturing of a log level per target.
|
||||
- If any of EWIDT are not shown, then the respective log level is not captured.
|
||||
|
||||
This logger pane has the following key bindings and they are only activated while the logs are being shown:
|
||||
|
||||
| Key | Action |
|
||||
| ------------------- | -------------------------------------------------------------- |
|
||||
| <kbd>h</kbd> | toggles target selector widget hidden/visible |
|
||||
| <kbd>f</kbd> | toggle focus on the selected target only |
|
||||
| <kbd>up</kbd> | select previous target in target selector widget |
|
||||
| <kbd>down</kbd> | select next target in target selector widget |
|
||||
| <kbd>left</kbd> | reduce SHOWN (!) log messages by one level |
|
||||
| <kbd>right</kbd> | increase SHOWN (!) log messages by one level |
|
||||
| <kbd>-</kbd> | reduce CAPTURED (!) log messages by one level |
|
||||
| <kbd>+</kbd> | increase CAPTURED (!) log messages by one level |
|
||||
| <kbd>pageup</kbd> | enter Page Mode and scroll approx. half page up in log history |
|
||||
| <kbd>pagedown</kbd> | only in page mode: scroll 10 events down in log history |
|
||||
| <kbd>escape</kbd> | exit page mode and go back to scrolling mode |
|
||||
| <kbd>space</kbd> | toggles hiding of targets, which have logfilter set to off |
|
||||
|
||||
For saving the logs to a file, you can use the `--log-file` argument:
|
||||
|
||||
```sh
|
||||
systeroid-tui --log-file systeroid.log
|
||||
```
|
||||
|
||||
`RUST_LOG` environment variable can be used to set the log level accordingly.
|
||||
|
||||
```sh
|
||||
RUST_LOG=debug systeroid-tui
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
**systeroid** can be configured with a configuration file that uses the [INI format](https://en.wikipedia.org/wiki/INI_file). It can be specified via `--config` or `SYSTEROID_CONFIG` environment variable. It can also be placed in one of the following global locations:
|
||||
|
|
BIN
assets/systeroid-tui-logs.gif
Normal file
BIN
assets/systeroid-tui-logs.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 MiB |
|
@ -17,8 +17,6 @@ display_deprecated = false
|
|||
kernel_docs = "/usr/share/doc/linux"
|
||||
|
||||
[cli]
|
||||
; enable verbose logging
|
||||
verbose = false
|
||||
; ignore unknown variable errors
|
||||
ignore_errors = true
|
||||
; do not print variable after the value is set
|
||||
|
@ -59,6 +57,8 @@ tick_rate = 250
|
|||
no_docs = true
|
||||
; path for saving the changed kernel parameters
|
||||
save_path = "/etc/sysctl.conf"
|
||||
; file to save the logs
|
||||
;log_file = "systeroid.log"
|
||||
|
||||
[tui.colors]
|
||||
; available colors are defined in https://docs.rs/tui/latest/tui/style/enum.Color.html
|
||||
|
|
|
@ -23,6 +23,9 @@ Use this option to set a custom path for the kernel documentation.
|
|||
\fB\-\-save\-path\fR <path>
|
||||
Use this option to set the path for saving the changed parameters.
|
||||
.TP
|
||||
\fB\-l\fR, \fB\-\-log\-file\fR <path>
|
||||
Use this option to set the file to save the logs.
|
||||
.TP
|
||||
\fB\-s\fR, \fB\-\-section\fR <section>
|
||||
Use this option to set the section to filter.
|
||||
.HP
|
||||
|
@ -61,6 +64,8 @@ systeroid-tui \-D /usr/share/doc/linux
|
|||
.br
|
||||
systeroid-tui \-\-save-path 99-local.conf
|
||||
.br
|
||||
systeroid-tui \-\-log-file systeroid.log
|
||||
.br
|
||||
systeroid-tui -n
|
||||
|
||||
.SH KEY BINDINGS
|
||||
|
|
|
@ -12,6 +12,8 @@ edition = "2021"
|
|||
rust-version = "1.64.0"
|
||||
|
||||
[dependencies]
|
||||
parseit.workspace = true
|
||||
log.workspace = true
|
||||
sysctl = "0.5.4"
|
||||
thiserror = "1.0.40"
|
||||
lazy_static = "1.4.0"
|
||||
|
@ -20,5 +22,4 @@ colored = "2.0.0"
|
|||
serde = { version = "1.0.160", features = ["derive"] }
|
||||
serde_json = "1.0.96"
|
||||
dirs-next = "2.0.0"
|
||||
parseit.workspace = true
|
||||
rust-ini = "0.18.0"
|
||||
|
|
|
@ -54,8 +54,6 @@ pub struct Config {
|
|||
/// CLI configuration.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct CliConfig {
|
||||
/// Whether if the verbose logging is enabled.
|
||||
pub verbose: bool,
|
||||
/// Whether if the errors should be ignored.
|
||||
pub ignore_errors: bool,
|
||||
/// Whether if the quiet mode is enabled.
|
||||
|
@ -88,6 +86,8 @@ pub struct TuiConfig {
|
|||
pub no_docs: bool,
|
||||
/// Path for saving the changed kernel parameters.
|
||||
pub save_path: Option<PathBuf>,
|
||||
/// File to save the logs.
|
||||
pub log_file: Option<String>,
|
||||
/// Color configuration.
|
||||
pub color: TuiColorConfig,
|
||||
}
|
||||
|
@ -116,6 +116,7 @@ impl Config {
|
|||
}
|
||||
}
|
||||
if let Some(path) = config_path {
|
||||
log::trace!(target: "config", "Parsing configuration from {:?}", path);
|
||||
let ini = Ini::load_from_file(path)?;
|
||||
if let Some(general_section) = ini.section(Some("general")) {
|
||||
if let Some(display_deprecated) = general_section.get("display_deprecated") {
|
||||
|
@ -126,7 +127,6 @@ impl Config {
|
|||
}
|
||||
}
|
||||
if let Some(section) = ini.section(Some("cli")) {
|
||||
parse_ini_flag!(self, cli, section, verbose);
|
||||
parse_ini_flag!(self, cli, section, ignore_errors);
|
||||
parse_ini_flag!(self, cli, section, quiet);
|
||||
parse_ini_flag!(self, cli, section, no_pager);
|
||||
|
@ -162,6 +162,9 @@ impl Config {
|
|||
if let Some(save_path) = section.get("save_path") {
|
||||
self.tui.save_path = Some(PathBuf::from(save_path));
|
||||
}
|
||||
if let Some(log_file) = section.get("log_file") {
|
||||
self.tui.log_file = Some(log_file.to_string());
|
||||
}
|
||||
parse_ini_flag!(self, tui, section, no_docs);
|
||||
}
|
||||
if let Some(section) = ini.section(Some("tui.colors")) {
|
||||
|
@ -183,7 +186,6 @@ impl Default for Config {
|
|||
display_deprecated: false,
|
||||
kernel_docs: None,
|
||||
cli: CliConfig {
|
||||
verbose: false,
|
||||
ignore_errors: false,
|
||||
quiet: false,
|
||||
no_pager: false,
|
||||
|
@ -207,6 +209,7 @@ impl Default for Config {
|
|||
tick_rate: 250,
|
||||
no_docs: false,
|
||||
save_path: None,
|
||||
log_file: None,
|
||||
color: TuiColorConfig {
|
||||
fg_color: String::from("white"),
|
||||
bg_color: String::from("black"),
|
||||
|
|
|
@ -51,9 +51,7 @@ impl Sysctl {
|
|||
}
|
||||
}
|
||||
Err(e) => {
|
||||
if config.cli.verbose {
|
||||
eprintln!("{} ({})", e, ctl.name()?);
|
||||
}
|
||||
log::trace!(target: "sysctl", "{} ({})", e, ctl.name()?);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -68,6 +66,7 @@ impl Sysctl {
|
|||
|
||||
/// Returns the parameters that matches the given query.
|
||||
pub fn get_parameters(&self, query: &str) -> Vec<&Parameter> {
|
||||
log::trace!(target: "sysctl", "Querying parameters: {:?}", query);
|
||||
let query = query.replace('/', ".");
|
||||
let parameters = self
|
||||
.parameters
|
||||
|
@ -79,7 +78,8 @@ impl Sysctl {
|
|||
})
|
||||
.collect::<Vec<&Parameter>>();
|
||||
if parameters.is_empty() && !self.config.cli.ignore_errors {
|
||||
eprintln!(
|
||||
log::error!(
|
||||
target: "sysctl",
|
||||
"{}: cannot stat {}{}: No such file or directory",
|
||||
env!("CARGO_PKG_NAME").split('-').collect::<Vec<_>>()[0],
|
||||
PROC_PATH,
|
||||
|
@ -91,6 +91,7 @@ impl Sysctl {
|
|||
|
||||
/// Updates the descriptions of the kernel parameters using the given cached data.
|
||||
pub fn update_docs_from_cache(&mut self, cache: &Cache) -> Result<()> {
|
||||
log::trace!(target: "cache", "{:?}", cache);
|
||||
let mut kernel_docs_path = if let Some(path) = &self.config.kernel_docs {
|
||||
vec![path.to_path_buf()]
|
||||
} else {
|
||||
|
@ -109,6 +110,7 @@ impl Sysctl {
|
|||
}
|
||||
if let Some(path) = kernel_docs_path.iter().find(|path| path.exists()) {
|
||||
if cache.exists(PARAMETERS_CACHE_LABEL) {
|
||||
log::trace!(target: "cache", "Cache hit for {:?}", path);
|
||||
let cache_data = cache.read(PARAMETERS_CACHE_LABEL)?;
|
||||
if cache_data.timestamp == CacheData::<()>::get_timestamp(path)? {
|
||||
self.update_params(cache_data.data);
|
||||
|
@ -117,13 +119,14 @@ impl Sysctl {
|
|||
}
|
||||
self.update_docs(path)?;
|
||||
if env::var(DISABLE_CACHE_ENV).is_err() {
|
||||
log::trace!(target: "cache", "Writing cache to {:?}", cache);
|
||||
cache.write(
|
||||
CacheData::new(&self.parameters, path)?,
|
||||
PARAMETERS_CACHE_LABEL,
|
||||
)?;
|
||||
}
|
||||
} else {
|
||||
eprintln!("warning: `Linux kernel documentation cannot be found. Please specify a path via '-D' argument`");
|
||||
log::error!(target: "sysctl", "warning: `Linux kernel documentation cannot be found. Please specify a path via '-D' argument`");
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
@ -146,6 +149,7 @@ impl Sysctl {
|
|||
|
||||
/// Updates the descriptions of the kernel parameters.
|
||||
fn update_docs(&mut self, kernel_docs: &Path) -> Result<()> {
|
||||
log::trace!(target: "sysctl", "Parsing the kernel documentation from {:?}", kernel_docs);
|
||||
let documents = parse_kernel_docs(kernel_docs)?;
|
||||
self.parameters
|
||||
.par_iter_mut()
|
||||
|
@ -187,6 +191,13 @@ impl Sysctl {
|
|||
let save_path = save_path
|
||||
.clone()
|
||||
.unwrap_or_else(|| PathBuf::from(DEFAULT_PRELOAD));
|
||||
log::trace!(
|
||||
target: "param",
|
||||
"Writing the new value ({:?}) of {:?} to {:?}",
|
||||
new_value,
|
||||
param_name,
|
||||
save_path
|
||||
);
|
||||
let data = format!("{param_name} = {new_value}");
|
||||
if save_path.exists() {
|
||||
let contents = reader::read_to_string(&save_path)?;
|
||||
|
|
|
@ -188,6 +188,7 @@ impl Parameter {
|
|||
config: &Config,
|
||||
output: &mut Output,
|
||||
) -> Result<()> {
|
||||
log::trace!(target: "param", "Setting the value of {:?} to {:?}", self.name, new_value);
|
||||
let ctl = Ctl::new(&self.name)?;
|
||||
let new_value = ctl.set_value_string(new_value)?;
|
||||
self.value = new_value;
|
||||
|
|
|
@ -10,7 +10,7 @@ repository = "https://github.com/orhun/systeroid"
|
|||
keywords = ["linux", "kernel", "parameter", "sysctl", "tui"]
|
||||
categories = ["command-line-utilities"]
|
||||
edition = "2021"
|
||||
rust-version = "1.64.0"
|
||||
rust-version = "1.68.2"
|
||||
|
||||
[features]
|
||||
# clipboard support is enabled as default
|
||||
|
@ -24,6 +24,7 @@ thiserror = "1.0.40"
|
|||
getopts = "0.2.21"
|
||||
copypasta-ext = { version = "0.4.4", optional = true }
|
||||
colorsys = "0.6.7"
|
||||
log.workspace = true
|
||||
|
||||
[dependencies.systeroid-core]
|
||||
version = "0.3.2" # managed by release.sh
|
||||
|
@ -35,6 +36,11 @@ version = "0.20.1"
|
|||
default-features = false
|
||||
features = ["termion"]
|
||||
|
||||
[dependencies.tui-logger]
|
||||
version = "0.9.0"
|
||||
default-features = false
|
||||
features = ["ratatui-support"]
|
||||
|
||||
# metadata for cargo-binstall to get the right artifacts
|
||||
[package.metadata.binstall]
|
||||
pkg-url = "{ repo }/releases/download/v{ version }/systeroid-{ version }-{ target }.{ archive-format }"
|
||||
|
|
|
@ -4,11 +4,13 @@ use crate::options::{CopyOption, Direction, ScrollArea};
|
|||
use crate::widgets::SelectableList;
|
||||
#[cfg(feature = "clipboard")]
|
||||
use copypasta_ext::{display::DisplayServer, ClipboardProviderExt};
|
||||
use log::{Level, LevelFilter};
|
||||
use std::str::FromStr;
|
||||
use std::time::Instant;
|
||||
use systeroid_core::sysctl::controller::Sysctl;
|
||||
use systeroid_core::sysctl::parameter::Parameter;
|
||||
use systeroid_core::sysctl::section::Section;
|
||||
use tui_logger::TuiWidgetState;
|
||||
use unicode_width::UnicodeWidthStr;
|
||||
|
||||
/// Representation of a key binding.
|
||||
|
@ -87,6 +89,11 @@ pub const KEY_BINDINGS: &[&KeyBinding] = &[
|
|||
action: "copy to clipboard",
|
||||
command: None,
|
||||
},
|
||||
&KeyBinding {
|
||||
key: "ctrl-l, f2",
|
||||
action: "show logs",
|
||||
command: Some("logs"),
|
||||
},
|
||||
&KeyBinding {
|
||||
key: "r, f5",
|
||||
action: "refresh",
|
||||
|
@ -113,6 +120,10 @@ pub struct App<'a> {
|
|||
pub running: bool,
|
||||
/// Whether if the help message is shown.
|
||||
pub show_help: bool,
|
||||
/// Whether if the logs are shown.
|
||||
pub show_logs: bool,
|
||||
/// Logger state.
|
||||
pub logger_state: TuiWidgetState,
|
||||
/// Input buffer.
|
||||
pub input: Option<String>,
|
||||
/// Time tracker for measuring the time for clearing the input.
|
||||
|
@ -144,6 +155,8 @@ impl<'a> App<'a> {
|
|||
let mut app = Self {
|
||||
running: true,
|
||||
show_help: false,
|
||||
show_logs: false,
|
||||
logger_state: TuiWidgetState::new().set_default_display_level(LevelFilter::Trace),
|
||||
input: None,
|
||||
input_time: None,
|
||||
input_cursor: 0,
|
||||
|
@ -167,16 +180,16 @@ impl<'a> App<'a> {
|
|||
app.parameter_list.items = app.sysctl.parameters.clone();
|
||||
#[cfg(feature = "clipboard")]
|
||||
{
|
||||
app.clipboard = match DisplayServer::select().try_context() {
|
||||
None => {
|
||||
app.input = Some(String::from(
|
||||
app.clipboard =
|
||||
match DisplayServer::select().try_context() {
|
||||
None => {
|
||||
app.log(Level::Error, String::from(
|
||||
"Failed to initialize clipboard, no suitable clipboard provider found",
|
||||
));
|
||||
app.input_time = Some(Instant::now());
|
||||
None
|
||||
None
|
||||
}
|
||||
clipboard => clipboard,
|
||||
}
|
||||
clipboard => clipboard,
|
||||
}
|
||||
}
|
||||
app
|
||||
}
|
||||
|
@ -186,6 +199,13 @@ impl<'a> App<'a> {
|
|||
self.input.is_some() && self.input_time.is_none()
|
||||
}
|
||||
|
||||
/// Sets the log message for the application.
|
||||
pub fn log(&mut self, level: Level, message: String) {
|
||||
log::log!(target: "tui", level, "{message}");
|
||||
self.input = Some(message);
|
||||
self.input_time = Some(Instant::now());
|
||||
}
|
||||
|
||||
/// Performs a search operation in the kernel parameter list.
|
||||
pub fn search(&mut self) {
|
||||
let section = self
|
||||
|
@ -228,7 +248,8 @@ impl<'a> App<'a> {
|
|||
/// Copies the selected entry to the clipboard.
|
||||
#[cfg(feature = "clipboard")]
|
||||
fn copy_to_clipboard(&mut self, copy_option: CopyOption) -> Result<()> {
|
||||
self.input = Some(if let Some(clipboard) = self.clipboard.as_mut() {
|
||||
log::debug!(target: "tui", "Copying to clipboard: {:?}", copy_option);
|
||||
if let Some(clipboard) = self.clipboard.as_mut() {
|
||||
if let Some(parameter) = self.parameter_list.selected() {
|
||||
match copy_option {
|
||||
CopyOption::Name => clipboard.set_contents(parameter.name.clone()),
|
||||
|
@ -238,22 +259,23 @@ impl<'a> App<'a> {
|
|||
}
|
||||
}
|
||||
.map_err(|e| crate::error::Error::ClipboardError(e.to_string()))?;
|
||||
String::from("Copied to clipboard!")
|
||||
self.log(Level::Info, String::from("Copied to clipboard!"));
|
||||
} else {
|
||||
String::from("No parameter is selected")
|
||||
self.log(Level::Warn, String::from("No parameter is selected"));
|
||||
}
|
||||
} else {
|
||||
String::from("Clipboard is not initialized")
|
||||
});
|
||||
self.input_time = Some(Instant::now());
|
||||
self.log(Level::Error, String::from("Clipboard is not initialized"));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Shows a message about clipboard being not enabled.
|
||||
#[cfg(not(feature = "clipboard"))]
|
||||
fn copy_to_clipboard(&mut self, _: CopyOption) -> Result<()> {
|
||||
self.input = Some(String::from("Clipboard support is not enabled"));
|
||||
self.input_time = Some(Instant::now());
|
||||
self.log(
|
||||
Level::Warn,
|
||||
String::from("Clipboard support is not enabled"),
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -268,6 +290,12 @@ impl<'a> App<'a> {
|
|||
self.show_help = true;
|
||||
hide_popup = false;
|
||||
}
|
||||
Command::Logs => {
|
||||
self.show_logs = !self.show_logs;
|
||||
}
|
||||
Command::LoggerEvent(event) => {
|
||||
self.logger_state.transition(&event.0);
|
||||
}
|
||||
Command::Select => {
|
||||
if let Some(copy_option) = self
|
||||
.options
|
||||
|
@ -312,8 +340,7 @@ impl<'a> App<'a> {
|
|||
self.run_command(Command::Refresh)?;
|
||||
}
|
||||
Err(e) => {
|
||||
self.input = Some(e.to_string());
|
||||
self.input_time = Some(Instant::now());
|
||||
self.log(Level::Error, e.to_string());
|
||||
}
|
||||
}
|
||||
if save_to_file {
|
||||
|
@ -323,17 +350,15 @@ impl<'a> App<'a> {
|
|||
&self.sysctl.config.tui.save_path,
|
||||
) {
|
||||
Ok(path) => {
|
||||
self.input = Some(format!("Saved to file: {path:?}"));
|
||||
self.log(Level::Info, format!("Saved to file: {path:?}"));
|
||||
}
|
||||
Err(e) => {
|
||||
self.input = Some(format!("Failed to save: {e}"));
|
||||
self.log(Level::Error, format!("Failed to save: {e}"));
|
||||
}
|
||||
}
|
||||
self.input_time = Some(Instant::now());
|
||||
}
|
||||
} else {
|
||||
self.input = Some(String::from("Unknown parameter"));
|
||||
self.input_time = Some(Instant::now());
|
||||
self.log(Level::Warn, String::from("Unknown parameter"));
|
||||
}
|
||||
}
|
||||
Command::Scroll(ScrollArea::List, Direction::Up, amount) => {
|
||||
|
@ -442,8 +467,7 @@ impl<'a> App<'a> {
|
|||
self.run_command(command)?;
|
||||
hide_popup = false;
|
||||
} else {
|
||||
self.input = Some(String::from("Unknown command"));
|
||||
self.input_time = Some(Instant::now());
|
||||
self.log(Level::Warn, String::from("Unknown command"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -516,8 +540,7 @@ impl<'a> App<'a> {
|
|||
hide_popup = false;
|
||||
self.show_help = false;
|
||||
} else {
|
||||
self.input = Some(String::from("No parameter is selected"));
|
||||
self.input_time = Some(Instant::now());
|
||||
self.log(Level::Warn, String::from("No parameter is selected"));
|
||||
}
|
||||
}
|
||||
Command::Refresh => {
|
||||
|
@ -531,6 +554,7 @@ impl<'a> App<'a> {
|
|||
parameter.value = param.value.to_string();
|
||||
}
|
||||
});
|
||||
self.log(Level::Info, String::from("Refreshed!"));
|
||||
}
|
||||
Command::Cancel => {
|
||||
if self.input.is_some() {
|
||||
|
|
|
@ -26,6 +26,8 @@ pub struct Args {
|
|||
pub kernel_docs: Option<PathBuf>,
|
||||
/// Path for the changed parameters.
|
||||
pub save_path: Option<PathBuf>,
|
||||
/// File to save the logs.
|
||||
pub log_file: Option<String>,
|
||||
/// Sysctl section to filter.
|
||||
pub section: Option<Section>,
|
||||
/// Query to search on startup.
|
||||
|
@ -62,6 +64,7 @@ impl Args {
|
|||
"set the path for saving the changed parameters",
|
||||
"<path>",
|
||||
);
|
||||
opts.optopt("l", "log-file", "set the file to save the logs", "<path>");
|
||||
opts.optopt("s", "section", "set the section to filter", "<section>");
|
||||
opts.optopt("q", "query", "set the query to search", "<query>");
|
||||
opts.optopt(
|
||||
|
@ -123,6 +126,7 @@ impl Args {
|
|||
.or_else(|| env::var(KERNEL_DOCS_ENV).ok())
|
||||
.map(PathBuf::from),
|
||||
save_path: matches.opt_str("save-path").map(PathBuf::from),
|
||||
log_file: matches.opt_str("l"),
|
||||
section: matches.opt_str("s").map(Section::from),
|
||||
search_query: matches.opt_str("q"),
|
||||
fg_color: matches
|
||||
|
|
|
@ -1,12 +1,44 @@
|
|||
use crate::options::{Direction, ScrollArea};
|
||||
use std::str::FromStr;
|
||||
use termion::event::Key;
|
||||
use tui_logger::TuiWidgetEvent;
|
||||
|
||||
/// Possible logger widget commands.
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct LoggerCommand(pub TuiWidgetEvent);
|
||||
|
||||
impl Eq for LoggerCommand {}
|
||||
|
||||
impl LoggerCommand {
|
||||
/// Parses a logger command from the given key.
|
||||
pub fn parse(key: Key) -> Option<Self> {
|
||||
match key {
|
||||
Key::Char(' ') => Some(Self(TuiWidgetEvent::SpaceKey)),
|
||||
Key::Esc => Some(Self(TuiWidgetEvent::EscapeKey)),
|
||||
Key::PageUp => Some(Self(TuiWidgetEvent::PrevPageKey)),
|
||||
Key::PageDown => Some(Self(TuiWidgetEvent::NextPageKey)),
|
||||
Key::Up => Some(Self(TuiWidgetEvent::UpKey)),
|
||||
Key::Down => Some(Self(TuiWidgetEvent::DownKey)),
|
||||
Key::Left => Some(Self(TuiWidgetEvent::LeftKey)),
|
||||
Key::Right => Some(Self(TuiWidgetEvent::RightKey)),
|
||||
Key::Char('+') => Some(Self(TuiWidgetEvent::PlusKey)),
|
||||
Key::Char('-') => Some(Self(TuiWidgetEvent::MinusKey)),
|
||||
Key::Char('h') => Some(Self(TuiWidgetEvent::HideKey)),
|
||||
Key::Char('f') => Some(Self(TuiWidgetEvent::FocusKey)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Possible application commands.
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum Command {
|
||||
/// Show help.
|
||||
Help,
|
||||
/// Show logs.
|
||||
Logs,
|
||||
/// Logger event.
|
||||
LoggerEvent(LoggerCommand),
|
||||
/// Perform an action based on the selected entry.
|
||||
Select,
|
||||
/// Save the value of a parameter to a file.
|
||||
|
@ -42,6 +74,7 @@ impl FromStr for Command {
|
|||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
"help" => Ok(Command::Help),
|
||||
"logs" => Ok(Command::Logs),
|
||||
"search" => Ok(Command::Search),
|
||||
"select" => Ok(Command::Select),
|
||||
"copy" => Ok(Command::Copy),
|
||||
|
@ -91,6 +124,7 @@ impl Command {
|
|||
} else {
|
||||
match key {
|
||||
Key::Char('?') | Key::F(1) => Command::Help,
|
||||
Key::Ctrl('l') | Key::F(2) => Command::Logs,
|
||||
Key::Up | Key::Char('k') => Command::Scroll(ScrollArea::List, Direction::Up, 1),
|
||||
Key::Down | Key::Char('j') => Command::Scroll(ScrollArea::List, Direction::Down, 1),
|
||||
Key::PageUp => Command::Scroll(ScrollArea::List, Direction::Up, 4),
|
||||
|
@ -135,6 +169,7 @@ mod tests {
|
|||
fn test_command() {
|
||||
for (command, value) in vec![
|
||||
(Command::Help, "help"),
|
||||
(Command::Logs, "logs"),
|
||||
(Command::Search, "search"),
|
||||
(Command::Select, "select"),
|
||||
(Command::Copy, "copy"),
|
||||
|
@ -181,6 +216,7 @@ mod tests {
|
|||
assert_command_parser! {
|
||||
input_mode: false,
|
||||
Key::Char('?') => Command::Help,
|
||||
Key::Ctrl('l') => Command::Logs,
|
||||
Key::Up => Command::Scroll(ScrollArea::List, Direction::Up, 1),
|
||||
Key::Down => Command::Scroll(ScrollArea::List, Direction::Down, 1),
|
||||
Key::PageUp => Command::Scroll(ScrollArea::List, Direction::Up, 4),
|
||||
|
|
|
@ -15,6 +15,12 @@ pub enum Error {
|
|||
/// Error that may occur while parsing a color.
|
||||
#[error(transparent)]
|
||||
ColorParseError(#[from] colorsys::ParseError),
|
||||
/// Error that may occur if the logger is already set.
|
||||
#[error(transparent)]
|
||||
LoggerSetError(#[from] log::SetLoggerError),
|
||||
/// Error that may occur when the string doesn’t match any of the log levels.
|
||||
#[error(transparent)]
|
||||
LoggerParseError(#[from] log::ParseLevelError),
|
||||
/// Error that may occur in the core library.
|
||||
#[error(transparent)]
|
||||
SysctlError(#[from] systeroid_core::error::Error),
|
||||
|
|
|
@ -27,6 +27,10 @@ use crate::command::Command;
|
|||
use crate::error::Result;
|
||||
use crate::event::{Event, EventHandler};
|
||||
use crate::style::Colors;
|
||||
use command::LoggerCommand;
|
||||
use log::LevelFilter;
|
||||
use std::env;
|
||||
use std::str::FromStr;
|
||||
use systeroid_core::cache::Cache;
|
||||
use systeroid_core::config::Config;
|
||||
use systeroid_core::sysctl::controller::Sysctl;
|
||||
|
@ -42,11 +46,22 @@ pub fn run<B: Backend>(args: Args, backend: B) -> Result<()> {
|
|||
};
|
||||
config.tui.tick_rate = args.tick_rate;
|
||||
config.tui.save_path = args.save_path;
|
||||
config.tui.log_file = args.log_file;
|
||||
config.tui.no_docs = args.no_docs;
|
||||
config.tui.color.fg_color = args.fg_color;
|
||||
config.tui.color.bg_color = args.bg_color;
|
||||
config.parse(args.config)?;
|
||||
let colors = Colors::new(&config.tui.color.bg_color, &config.tui.color.fg_color)?;
|
||||
tui_logger::init_logger(if let Ok(log_level) = env::var("RUST_LOG") {
|
||||
LevelFilter::from_str(&log_level)?
|
||||
} else {
|
||||
LevelFilter::Trace
|
||||
})?;
|
||||
tui_logger::set_default_level(LevelFilter::Trace);
|
||||
if let Some(ref log_file) = config.tui.log_file {
|
||||
tui_logger::set_log_file(log_file)?;
|
||||
}
|
||||
log::trace!(target: "config", "{:?}", config);
|
||||
let mut sysctl = Sysctl::init(config)?;
|
||||
if !sysctl.config.tui.no_docs {
|
||||
sysctl.update_docs_from_cache(&Cache::init()?)?;
|
||||
|
@ -75,7 +90,12 @@ pub fn run<B: Backend>(args: Args, backend: B) -> Result<()> {
|
|||
terminal.draw(|frame| ui::render(frame, &mut app, &colors))?;
|
||||
match event_handler.next()? {
|
||||
Event::KeyPress(key) => {
|
||||
let command = Command::parse(key, app.is_input_mode());
|
||||
let mut command = Command::parse(key, app.is_input_mode());
|
||||
if app.show_logs {
|
||||
command = LoggerCommand::parse(key)
|
||||
.map(Command::LoggerEvent)
|
||||
.unwrap_or(command);
|
||||
}
|
||||
app.run_command(command)?;
|
||||
}
|
||||
#[cfg(not(test))]
|
||||
|
|
|
@ -3,9 +3,11 @@ use crate::style::Colors;
|
|||
use crate::widgets::SelectableList;
|
||||
use tui::backend::Backend;
|
||||
use tui::layout::{Alignment, Constraint, Direction, Layout, Rect};
|
||||
use tui::style::{Color as TuiColor, Style};
|
||||
use tui::text::{Span, Text};
|
||||
use tui::widgets::{Block, BorderType, Borders, Cell, Clear, Paragraph, Row, Table, Wrap};
|
||||
use tui::Frame;
|
||||
use tui_logger::{TuiLoggerLevelOutput, TuiLoggerSmartWidget};
|
||||
use unicode_width::UnicodeWidthStr;
|
||||
|
||||
/// Renders the user interface.
|
||||
|
@ -16,35 +18,48 @@ pub fn render<B: Backend>(frame: &mut Frame<'_, B>, app: &mut App, colors: &Colo
|
|||
.and_then(|parameter| parameter.get_documentation());
|
||||
let rect = frame.size();
|
||||
let chunks = Layout::default()
|
||||
.direction(Direction::Horizontal)
|
||||
.constraints(if documentation.is_some() {
|
||||
[Constraint::Percentage(50), Constraint::Percentage(50)]
|
||||
.direction(Direction::Vertical)
|
||||
.constraints(if app.show_logs {
|
||||
[Constraint::Percentage(60), Constraint::Percentage(40)]
|
||||
} else {
|
||||
[Constraint::Percentage(100), Constraint::Min(0)]
|
||||
})
|
||||
.split(rect);
|
||||
{
|
||||
let chunks = Layout::default()
|
||||
.direction(Direction::Vertical)
|
||||
.constraints(if app.input.is_some() {
|
||||
[Constraint::Min(rect.height - 3), Constraint::Min(3)]
|
||||
.direction(Direction::Horizontal)
|
||||
.constraints(if documentation.is_some() {
|
||||
[Constraint::Percentage(50), Constraint::Percentage(50)]
|
||||
} else {
|
||||
[Constraint::Percentage(100), Constraint::Min(0)]
|
||||
})
|
||||
.split(chunks[0]);
|
||||
render_parameter_list(frame, chunks[0], app, colors);
|
||||
if app.input.is_some() {
|
||||
render_input_prompt(frame, chunks[1], rect.height - 2, app, colors);
|
||||
{
|
||||
let chunks = Layout::default()
|
||||
.direction(Direction::Vertical)
|
||||
.constraints(if app.input.is_some() {
|
||||
[Constraint::Min(chunks[0].height - 3), Constraint::Min(3)]
|
||||
} else {
|
||||
[Constraint::Percentage(100), Constraint::Min(0)]
|
||||
})
|
||||
.split(chunks[0]);
|
||||
render_parameter_list(frame, chunks[0], app, colors);
|
||||
if app.input.is_some() {
|
||||
render_input_prompt(frame, chunks[1], chunks[0].height + 1, app, colors);
|
||||
}
|
||||
}
|
||||
if let Some(documentation) = documentation {
|
||||
render_parameter_documentation(
|
||||
frame,
|
||||
chunks[1],
|
||||
documentation,
|
||||
&mut app.docs_scroll_amount,
|
||||
colors,
|
||||
);
|
||||
}
|
||||
}
|
||||
if let Some(documentation) = documentation {
|
||||
render_parameter_documentation(
|
||||
frame,
|
||||
chunks[1],
|
||||
documentation,
|
||||
&mut app.docs_scroll_amount,
|
||||
colors,
|
||||
);
|
||||
if app.show_logs {
|
||||
render_log_view(frame, chunks[1], app, colors);
|
||||
}
|
||||
if app.show_help {
|
||||
render_help_text(frame, rect, &mut app.key_bindings, colors);
|
||||
|
@ -463,3 +478,24 @@ fn render_input_prompt<B: Backend>(
|
|||
rect,
|
||||
);
|
||||
}
|
||||
|
||||
/// Renders the log view.
|
||||
fn render_log_view<B: Backend>(frame: &mut Frame<'_, B>, rect: Rect, app: &App, colors: &Colors) {
|
||||
let logger_widget = TuiLoggerSmartWidget::default()
|
||||
.style_trace(Style::default().fg(TuiColor::DarkGray))
|
||||
.style_debug(Style::default().fg(TuiColor::Blue))
|
||||
.style_warn(Style::default().fg(TuiColor::Yellow))
|
||||
.style_error(Style::default().fg(TuiColor::Red))
|
||||
.style_info(Style::default().fg(TuiColor::Green))
|
||||
.highlight_style(colors.get_fg_style())
|
||||
.border_style(colors.get_fg_style())
|
||||
.style(colors.get_bg_style())
|
||||
.output_separator(':')
|
||||
.output_timestamp(Some("%H:%M:%S".to_string()))
|
||||
.output_level(Some(TuiLoggerLevelOutput::Long))
|
||||
.output_target(true)
|
||||
.output_file(true)
|
||||
.output_line(true)
|
||||
.state(&app.logger_state);
|
||||
frame.render_widget(logger_widget, rect);
|
||||
}
|
||||
|
|
|
@ -307,10 +307,10 @@ fn test_render_tui() -> Result<()> {
|
|||
"│vm.stat_interval =││============= │",
|
||||
"│ ││The time interval │",
|
||||
"│ ││between which vm │",
|
||||
"│ ││statistics are │",
|
||||
"│ ││updated │",
|
||||
"│ ││- │",
|
||||
"│ 2/2 ││Parameter: │",
|
||||
"│ 2/2 ││statistics are │",
|
||||
"╰──────────────────╯│updated │",
|
||||
"╭──────────────────╮│- │",
|
||||
"│MSG: Refreshed! ││Parameter: │",
|
||||
"╰──────────────────╯╰──────────────────╯",
|
||||
]),
|
||||
terminal.backend(),
|
||||
|
|
|
@ -10,7 +10,7 @@ repository = "https://github.com/orhun/systeroid"
|
|||
keywords = ["linux", "kernel", "parameter", "sysctl"]
|
||||
categories = ["command-line-utilities"]
|
||||
edition = "2021"
|
||||
default-run="systeroid"
|
||||
default-run = "systeroid"
|
||||
rust-version = "1.64.0"
|
||||
|
||||
[features]
|
||||
|
@ -18,8 +18,10 @@ rust-version = "1.64.0"
|
|||
live-tests = []
|
||||
|
||||
[dependencies]
|
||||
getopts = "0.2.21"
|
||||
parseit.workspace = true
|
||||
log.workspace = true
|
||||
env_logger = "0.10.0"
|
||||
getopts = "0.2.21"
|
||||
|
||||
[dependencies.systeroid-core]
|
||||
version = "0.3.2" # managed by release.sh
|
||||
|
|
|
@ -95,7 +95,7 @@ impl<'a, Output: Write> App<'a, Output> {
|
|||
}
|
||||
Err(e) => {
|
||||
if !pager.is_empty() {
|
||||
eprintln!("pager error: `{e}`");
|
||||
log::error!("pager error: `{e}`");
|
||||
}
|
||||
fallback_to_default = true;
|
||||
}
|
||||
|
@ -130,7 +130,7 @@ impl<'a, Output: Write> App<'a, Output> {
|
|||
if parameters.len() == 1 {
|
||||
let param = parameters[0];
|
||||
if DEPRECATED_PARAMS.contains(¶m.get_absolute_name().unwrap_or_default()) {
|
||||
eprintln!(
|
||||
log::error!(
|
||||
"{}: {} is deprecated, value not set",
|
||||
env!("CARGO_PKG_NAME"),
|
||||
parameter
|
||||
|
@ -145,14 +145,14 @@ impl<'a, Output: Write> App<'a, Output> {
|
|||
param.update_value(&new_value, &config, self.output)?;
|
||||
}
|
||||
} else {
|
||||
eprintln!(
|
||||
log::error!(
|
||||
"{}: ambiguous parameter name: {}",
|
||||
env!("CARGO_PKG_NAME"),
|
||||
parameter
|
||||
);
|
||||
}
|
||||
} else if write_mode {
|
||||
eprintln!(
|
||||
log::error!(
|
||||
"{}: {:?} must be in the format: name=value",
|
||||
env!("CARGO_PKG_NAME"),
|
||||
parameter
|
||||
|
@ -171,13 +171,13 @@ impl<'a, Output: Write> App<'a, Output> {
|
|||
let lines = stdin.lock().lines();
|
||||
for line in lines {
|
||||
if let Err(e) = self.process_parameter(line?, true, false) {
|
||||
println!("{}: {}", env!("CARGO_PKG_NAME"), e);
|
||||
log::info!("{}: {}", env!("CARGO_PKG_NAME"), e);
|
||||
}
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
if !path.exists() {
|
||||
eprintln!(
|
||||
log::error!(
|
||||
"{}: cannot open {:?}: No such file or directory",
|
||||
env!("CARGO_PKG_NAME"),
|
||||
path
|
||||
|
@ -194,7 +194,7 @@ impl<'a, Output: Write> App<'a, Output> {
|
|||
if !parameter.starts_with('-') {
|
||||
process_result?;
|
||||
} else if let Err(e) = process_result {
|
||||
eprintln!("{}: {}", env!("CARGO_PKG_NAME"), e);
|
||||
log::error!("{}: {}", env!("CARGO_PKG_NAME"), e);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
@ -208,7 +208,7 @@ impl<'a, Output: Write> App<'a, Output> {
|
|||
{
|
||||
if let Ok(glob_walker) = globwalk::glob(preload_path.to_string_lossy()) {
|
||||
for file in glob_walker.filter_map(|v| v.ok()) {
|
||||
println!("* Applying {} ...", file.path().display());
|
||||
log::info!("* Applying {} ...", file.path().display());
|
||||
self.preload_from_file(file.path().to_path_buf())?;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,13 +23,13 @@ pub fn run<Output: Write>(args: Args, output: &mut Output) -> Result<()> {
|
|||
kernel_docs: args.kernel_docs,
|
||||
..Default::default()
|
||||
};
|
||||
config.cli.verbose = args.verbose;
|
||||
config.cli.ignore_errors = args.ignore_errors;
|
||||
config.cli.quiet = args.quiet;
|
||||
config.cli.no_pager = args.no_pager;
|
||||
config.cli.display_type = args.display_type;
|
||||
config.cli.output_type = args.output_type;
|
||||
config.parse(args.config)?;
|
||||
log::trace!("{:?}", config);
|
||||
let mut sysctl = Sysctl::init(config)?;
|
||||
if args.explain {
|
||||
sysctl.update_docs_from_cache(&Cache::init()?)?;
|
||||
|
|
|
@ -1,10 +1,19 @@
|
|||
use env_logger::Builder as LoggerBuilder;
|
||||
use log::LevelFilter;
|
||||
use std::env;
|
||||
use std::io;
|
||||
use std::io::{self, Write};
|
||||
use std::process::{self, Command};
|
||||
use systeroid::args::Args;
|
||||
|
||||
fn main() {
|
||||
if let Some(args) = Args::parse(env::args().collect()) {
|
||||
let mut builder = LoggerBuilder::from_default_env();
|
||||
if args.verbose {
|
||||
builder.filter(None, LevelFilter::Trace);
|
||||
}
|
||||
builder
|
||||
.format(|buf, record| writeln!(buf, "{}", record.args()))
|
||||
.init();
|
||||
if args.show_tui {
|
||||
let bin = format!("{}-tui", env!("CARGO_PKG_NAME"));
|
||||
let mut command = Command::new(&bin);
|
||||
|
@ -17,7 +26,7 @@ fn main() {
|
|||
match command.spawn().map(|mut child| child.wait()) {
|
||||
Ok(_) => process::exit(0),
|
||||
Err(e) => {
|
||||
eprintln!("Cannot run `{bin}` ({e})");
|
||||
log::error!("Cannot run `{bin}` ({e})");
|
||||
process::exit(1)
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +35,7 @@ fn main() {
|
|||
match systeroid::run(args, &mut stdout) {
|
||||
Ok(_) => process::exit(0),
|
||||
Err(e) => {
|
||||
eprintln!("{e}");
|
||||
log::error!("{e}");
|
||||
process::exit(1)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue