Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package erldash for openSUSE:Factory checked in at 2023-10-19 22:49:38 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/erldash (Old) and /work/SRC/openSUSE:Factory/.erldash.new.1945 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "erldash" Thu Oct 19 22:49:38 2023 rev:5 rq:1118838 version:0.1.5~0 Changes: -------- --- /work/SRC/openSUSE:Factory/erldash/erldash.changes 2023-09-20 13:33:14.479354719 +0200 +++ /work/SRC/openSUSE:Factory/.erldash.new.1945/erldash.changes 2023-10-19 22:52:02.232698607 +0200 @@ -1,0 +2,7 @@ +Thu Oct 19 07:46:43 UTC 2023 - Michael Vetter <jub...@iodoru.org> + +- Update to 0.1.5: + * Update dependencies and remove ordered-float crate #5 + * Add --record and --replay options #6 + +------------------------------------------------------------------- Old: ---- erldash-0.1.3~0.tar.xz New: ---- erldash-0.1.5~0.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ erldash.spec ++++++ --- /var/tmp/diff_new_pack.248QbE/_old 2023-10-19 22:52:03.952760992 +0200 +++ /var/tmp/diff_new_pack.248QbE/_new 2023-10-19 22:52:03.968761573 +0200 @@ -17,7 +17,7 @@ Name: erldash -Version: 0.1.3~0 +Version: 0.1.5~0 Release: 0 Summary: A simple, terminal-based Erlang dashboard License: (Apache-2.0 OR MIT) AND MIT AND Apache-2.0 WITH LLVM-exception AND MPL-2.0 ++++++ _service ++++++ --- /var/tmp/diff_new_pack.248QbE/_old 2023-10-19 22:52:04.300773614 +0200 +++ /var/tmp/diff_new_pack.248QbE/_new 2023-10-19 22:52:04.340775065 +0200 @@ -3,7 +3,7 @@ <param name="url">https://github.com/sile/erldash.git</param> <param name="versionformat">@PARENT_TAG@~@TAG_OFFSET@</param> <param name="scm">git</param> - <param name="revision">0.1.3</param> + <param name="revision">0.1.5</param> <param name="match-tag">*</param> <param name="versionrewrite-pattern">v(\d+\.\d+\.\d+)</param> <param name="versionrewrite-replacement">\1</param> ++++++ erldash-0.1.3~0.tar.xz -> erldash-0.1.5~0.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/erldash-0.1.3~0/Cargo.lock new/erldash-0.1.5~0/Cargo.lock --- old/erldash-0.1.3~0/Cargo.lock 2023-08-08 13:43:08.000000000 +0200 +++ new/erldash-0.1.5~0/Cargo.lock 2023-10-19 04:24:59.000000000 +0200 @@ -10,30 +10,29 @@ [[package]] name = "anstream" -version = "0.3.2" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163" +checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", - "is-terminal", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.1" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a30da5c5f2d5e72842e00bcb57657162cdabef0931f40e2deb9b4140440cecd" +checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" [[package]] name = "anstyle-parse" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333" +checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140" dependencies = [ "utf8parse", ] @@ -49,9 +48,9 @@ [[package]] name = "anstyle-wincon" -version = "1.0.1" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188" +checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" dependencies = [ "anstyle", "windows-sys", @@ -59,9 +58,9 @@ [[package]] name = "anyhow" -version = "1.0.72" +version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854" +checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" [[package]] name = "async-channel" @@ -70,20 +69,20 @@ checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" dependencies = [ "concurrent-queue", - "event-listener", + "event-listener 2.5.3", "futures-core", ] [[package]] name = "async-executor" -version = "1.5.1" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fa3dc5f2a8564f07759c008b9109dc0d39de92a88d5588b8a5036d286383afb" +checksum = "4b0c4a4f319e45986f347ee47fef8bf5e81c9abc3f6f58dc2391439f30df65f0" dependencies = [ "async-lock", "async-task", "concurrent-queue", - "fastrand", + "fastrand 2.0.1", "futures-lite", "slab", ] @@ -114,7 +113,7 @@ "log", "parking", "polling", - "rustix 0.37.23", + "rustix 0.37.25", "slab", "socket2", "waker-fn", @@ -122,54 +121,70 @@ [[package]] name = "async-lock" -version = "2.7.0" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa24f727524730b077666307f2734b4a1a1c57acb79193127dcc8914d5242dd7" +checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" dependencies = [ - "event-listener", + "event-listener 2.5.3", ] [[package]] name = "async-net" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4051e67316bc7eff608fe723df5d32ed639946adcd69e07df41fd42a7b411f1f" +checksum = "0434b1ed18ce1cf5769b8ac540e33f01fa9471058b5e89da9e06f3c882a8c12f" dependencies = [ "async-io", - "autocfg", "blocking", "futures-lite", ] [[package]] name = "async-process" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a9d28b1d97e08915212e2e45310d47854eafa69600756fc735fb788f75199c9" +checksum = "ea6438ba0a08d81529c69b36700fa2f95837bfe3e776ab39cde9c14d9149da88" dependencies = [ "async-io", "async-lock", - "autocfg", + "async-signal", "blocking", "cfg-if", - "event-listener", + "event-listener 3.0.0", "futures-lite", - "rustix 0.37.23", - "signal-hook", + "rustix 0.38.19", + "windows-sys", +] + +[[package]] +name = "async-signal" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2a5415b7abcdc9cd7d63d6badba5288b2ca017e3fbd4173b8f405449f1a2399" +dependencies = [ + "async-io", + "async-lock", + "atomic-waker", + "cfg-if", + "futures-core", + "futures-io", + "rustix 0.38.19", + "signal-hook-registry", + "slab", "windows-sys", ] [[package]] name = "async-task" -version = "4.4.0" +version = "4.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc7ab41815b3c653ccd2978ec3255c81349336702dfdf62ee6f7069b12a3aae" +checksum = "b4eb2cdb97421e01129ccb49169d8279ed21e829929144f4a22a6e54ac549ca1" [[package]] name = "atomic-waker" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1181e1e0d1fce796a03db1ae795d67167da795f9cf4a39c37589e85ef57f26d3" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "autocfg" @@ -185,30 +200,31 @@ [[package]] name = "bitflags" -version = "2.3.3" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" [[package]] name = "blocking" -version = "1.3.1" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77231a1c8f801696fc0123ec6150ce92cffb8e164a02afb9c8ddee0e9b65ad65" +checksum = "8c36a4d0d48574b3dd360b4b7d95cc651d2b6557b6402848a27d4b228a473e2a" dependencies = [ "async-channel", "async-lock", "async-task", - "atomic-waker", - "fastrand", + "fastrand 2.0.1", + "futures-io", "futures-lite", - "log", + "piper", + "tracing", ] [[package]] name = "byteorder" -version = "1.4.3" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "cassowary" @@ -217,15 +233,6 @@ checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53" [[package]] -name = "cc" -version = "1.0.82" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "305fe645edc1442a0fa8b6726ba61d422798d37a52e12eaecf4b022ebbb88f01" -dependencies = [ - "libc", -] - -[[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -233,20 +240,19 @@ [[package]] name = "clap" -version = "4.3.21" +version = "4.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c27cdf28c0f604ba3f512b0c9a409f8de8513e4816705deb0498b627e7c3a3fd" +checksum = "d04704f56c2cde07f43e8e2c154b43f216dc5c92fc98ada720177362f953b956" dependencies = [ "clap_builder", "clap_derive", - "once_cell", ] [[package]] name = "clap_builder" -version = "4.3.21" +version = "4.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08a9f1ab5e9f01a9b81f202e8562eb9a10de70abf9eaeac1be465c28b75aa4aa" +checksum = "0e231faeaca65ebd1ea3c737966bf858971cd38c3849107aa3ea7de90a804e45" dependencies = [ "anstream", "anstyle", @@ -256,9 +262,9 @@ [[package]] name = "clap_derive" -version = "4.3.12" +version = "4.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54a9bb5758fc5dfe728d1019941681eccaf0cf8a4189b692a0ee2f2ecf90a050" +checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873" dependencies = [ "heck", "proc-macro2", @@ -268,9 +274,9 @@ [[package]] name = "clap_lex" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" +checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961" [[package]] name = "colorchoice" @@ -280,9 +286,9 @@ [[package]] name = "concurrent-queue" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62ec6771ecfa0762d24683ee5a32ad78487a3d3afdc0fb8cae19d2c5deb50b7c" +checksum = "f057a694a54f12365049b0958a1685bb52d567f5593b355fbf685838e873d400" dependencies = [ "crossbeam-utils", ] @@ -327,7 +333,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df" dependencies = [ - "bitflags 2.3.3", + "bitflags 2.4.1", "crossterm_winapi", "libc", "mio", @@ -348,9 +354,12 @@ [[package]] name = "deranged" -version = "0.3.7" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7684a49fb1af197853ef7b2ee694bc1f5b4179556f1e5710e1760c5db6f5e929" +checksum = "0f32d04922c60427da6f9fef14d042d9edddef64cb9d4ce0d64d0685fbeb1fd3" +dependencies = [ + "powerfmt", +] [[package]] name = "dirs" @@ -382,7 +391,7 @@ "byteorder", "libflate", "num", - "ordered-float 2.10.0", + "ordered-float", "thiserror", ] @@ -416,7 +425,7 @@ [[package]] name = "erldash" -version = "0.1.3" +version = "0.1.5" dependencies = [ "anyhow", "clap", @@ -426,7 +435,8 @@ "erl_rpc", "futures", "log", - "ordered-float 3.7.0", + "serde", + "serde_json", "simplelog", "smol", "tui", @@ -434,30 +444,30 @@ [[package]] name = "errno" -version = "0.3.2" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b30f669a7961ef1631673d2766cc92f52d64f7ef354d4fe0ddfd30ed52f0f4f" +checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860" dependencies = [ - "errno-dragonfly", "libc", "windows-sys", ] [[package]] -name = "errno-dragonfly" -version = "0.1.2" +name = "event-listener" +version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" -dependencies = [ - "cc", - "libc", -] +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "event-listener" -version = "2.5.3" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" +checksum = "29e56284f00d94c1bc7fd3c77027b4623c88c1f53d8d2394c6199f2921dea325" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] [[package]] name = "fastrand" @@ -469,6 +479,12 @@ ] [[package]] +name = "fastrand" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" + +[[package]] name = "futures" version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -522,7 +538,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" dependencies = [ - "fastrand", + "fastrand 1.9.0", "futures-core", "futures-io", "memchr", @@ -591,9 +607,9 @@ [[package]] name = "hermit-abi" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" +checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" [[package]] name = "instant" @@ -616,17 +632,6 @@ ] [[package]] -name = "is-terminal" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" -dependencies = [ - "hermit-abi", - "rustix 0.38.7", - "windows-sys", -] - -[[package]] name = "itoa" version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -634,9 +639,9 @@ [[package]] name = "libc" -version = "0.2.147" +version = "0.2.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" +checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" [[package]] name = "libflate" @@ -666,15 +671,15 @@ [[package]] name = "linux-raw-sys" -version = "0.4.5" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503" +checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f" [[package]] name = "lock_api" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" dependencies = [ "autocfg", "scopeguard", @@ -682,9 +687,9 @@ [[package]] name = "log" -version = "0.4.19" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "md5" @@ -694,9 +699,9 @@ [[package]] name = "memchr" -version = "2.5.0" +version = "2.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" [[package]] name = "mio" @@ -726,9 +731,9 @@ [[package]] name = "num-bigint" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" +checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" dependencies = [ "autocfg", "num-integer", @@ -737,9 +742,9 @@ [[package]] name = "num-complex" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02e0d21255c828d6f128a1e41534206671e8c3ea0c62f32291e808dc82cff17d" +checksum = "1ba157ca0885411de85d6ca030ba7e2a83a28636056c7c699b07c8b6f7383214" dependencies = [ "num-traits", ] @@ -779,9 +784,9 @@ [[package]] name = "num-traits" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" +checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" dependencies = [ "autocfg", ] @@ -796,12 +801,6 @@ ] [[package]] -name = "once_cell" -version = "1.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" - -[[package]] name = "option-ext" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -809,27 +808,18 @@ [[package]] name = "ordered-float" -version = "2.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7940cf2ca942593318d07fcf2596cdca60a85c9e7fab408a5e21a4f9dcd40d87" -dependencies = [ - "num-traits", -] - -[[package]] -name = "ordered-float" -version = "3.7.0" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fc2dbde8f8a79f2102cc474ceb0ad68e3b80b85289ea62389b60e66777e4213" +checksum = "68f19d67e5a2795c94e73e0bb1cc1a7edeb2e28efd39e2e1c9b7a40c1108b11c" dependencies = [ "num-traits", ] [[package]] name = "parking" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14f2252c834a40ed9bb5422029649578e63aa341ac401f74e719dd1afda8394e" +checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" [[package]] name = "parking_lot" @@ -843,22 +833,22 @@ [[package]] name = "parking_lot_core" -version = "0.9.8" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.3.5", + "redox_syscall 0.4.1", "smallvec", "windows-targets", ] [[package]] name = "pin-project-lite" -version = "0.2.11" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c516611246607d0c04186886dbb3a754368ef82c79e9827a802c6d836dd111c" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" [[package]] name = "pin-utils" @@ -867,6 +857,17 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] +name = "piper" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "668d31b1c4eba19242f2088b2bf3316b82ca31082a8335764db4e083db7485d4" +dependencies = [ + "atomic-waker", + "fastrand 2.0.1", + "futures-io", +] + +[[package]] name = "polling" version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -883,6 +884,12 @@ ] [[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] name = "ppv-lite86" version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -890,18 +897,18 @@ [[package]] name = "proc-macro2" -version = "1.0.66" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.32" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" dependencies = [ "proc-macro2", ] @@ -947,9 +954,9 @@ [[package]] name = "redox_syscall" -version = "0.3.5" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" dependencies = [ "bitflags 1.3.2", ] @@ -973,9 +980,9 @@ [[package]] name = "rustix" -version = "0.37.23" +version = "0.37.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06" +checksum = "d4eb579851244c2c03e7c24f501c3432bed80b8f720af1d6e5b0e0f01555a035" dependencies = [ "bitflags 1.3.2", "errno", @@ -987,18 +994,24 @@ [[package]] name = "rustix" -version = "0.38.7" +version = "0.38.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "172891ebdceb05aa0005f533a6cbfca599ddd7d966f6f5d4d9b2e70478e70399" +checksum = "745ecfa778e66b2b63c88a61cb36e0eea109e803b0b86bf9879fbc77c70e86ed" dependencies = [ - "bitflags 2.3.3", + "bitflags 2.4.1", "errno", "libc", - "linux-raw-sys 0.4.5", + "linux-raw-sys 0.4.10", "windows-sys", ] [[package]] +name = "ryu" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" + +[[package]] name = "scopeguard" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1006,9 +1019,34 @@ [[package]] name = "serde" -version = "1.0.183" +version = "1.0.189" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32ac8da02677876d532745a130fc9d8e6edfa81a269b107c5b00829b91d8eb3c" +checksum = "8e422a44e74ad4001bdc8eede9a4570ab52f71190e9c076d14369f38b9200537" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.189" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e48d1f918009ce3145511378cf68d613e3b3d9137d67272562080d68a2b32d5" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" +dependencies = [ + "itoa", + "ryu", + "serde", +] [[package]] name = "signal-hook" @@ -1053,18 +1091,18 @@ [[package]] name = "slab" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" dependencies = [ "autocfg", ] [[package]] name = "smallvec" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" +checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" [[package]] name = "smol" @@ -1101,9 +1139,9 @@ [[package]] name = "syn" -version = "2.0.28" +version = "2.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567" +checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" dependencies = [ "proc-macro2", "quote", @@ -1121,18 +1159,18 @@ [[package]] name = "thiserror" -version = "1.0.44" +version = "1.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "611040a08a0439f8248d1990b111c95baa9c704c805fa1f62104b39655fd7f90" +checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.44" +version = "1.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96" +checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc" dependencies = [ "proc-macro2", "quote", @@ -1141,14 +1179,15 @@ [[package]] name = "time" -version = "0.3.25" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fdd63d58b18d663fbdf70e049f00a22c8e42be082203be7f26589213cd75ea" +checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5" dependencies = [ "deranged", "itoa", "libc", "num_threads", + "powerfmt", "serde", "time-core", "time-macros", @@ -1156,20 +1195,36 @@ [[package]] name = "time-core" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.11" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb71511c991639bb078fd5bf97757e03914361c48100d52878b8e52b46fb92cd" +checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20" dependencies = [ "time-core", ] [[package]] +name = "tracing" +version = "0.1.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee2ef2af84856a50c1d430afce2fdded0a4ec7eda868db86409b4543df0797f9" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" + +[[package]] name = "tui" version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1184,9 +1239,9 @@ [[package]] name = "unicode-ident" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-segmentation" @@ -1196,9 +1251,9 @@ [[package]] name = "unicode-width" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" +checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" [[package]] name = "utf8parse" @@ -1208,9 +1263,9 @@ [[package]] name = "waker-fn" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" +checksum = "f3c4517f54858c779bbcbf228f4fca63d121bf85fbecb2dc578cdf4a39395690" [[package]] name = "wasi" @@ -1236,9 +1291,9 @@ [[package]] name = "winapi-util" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" dependencies = [ "winapi", ] @@ -1260,9 +1315,9 @@ [[package]] name = "windows-targets" -version = "0.48.1" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", @@ -1275,42 +1330,42 @@ [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_i686_gnu" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_x86_64_gnu" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/erldash-0.1.3~0/Cargo.toml new/erldash-0.1.5~0/Cargo.toml --- old/erldash-0.1.3~0/Cargo.toml 2023-08-08 13:43:08.000000000 +0200 +++ new/erldash-0.1.5~0/Cargo.toml 2023-10-19 04:24:59.000000000 +0200 @@ -1,6 +1,6 @@ [package] name = "erldash" -version = "0.1.3" +version = "0.1.5" edition = "2021" authors = ["Takeru Ohta <phjgt...@gmail.com>"] license = "MIT OR Apache-2.0" @@ -20,7 +20,8 @@ erl_rpc = "0.2" futures = "0.3" log = "0.4" -ordered-float = "3" +serde = { version = "1.0.189", features = ["derive"] } +serde_json = "1.0.107" simplelog = "0.12" smol = "1" tui = "0.19" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/erldash-0.1.3~0/src/erlang.rs new/erldash-0.1.5~0/src/erlang.rs --- old/erldash-0.1.3~0/src/erlang.rs 2023-08-08 13:43:08.000000000 +0200 +++ new/erldash-0.1.5~0/src/erlang.rs 2023-10-19 04:24:59.000000000 +0200 @@ -1,8 +1,9 @@ use erl_dist::node::NodeName; use erl_dist::term::{Atom, List, Map, Term, Tuple}; +use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct SystemVersion(String); impl SystemVersion { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/erldash-0.1.3~0/src/lib.rs new/erldash-0.1.5~0/src/lib.rs --- old/erldash-0.1.3~0/src/lib.rs 2023-08-08 13:43:08.000000000 +0200 +++ new/erldash-0.1.5~0/src/lib.rs 2023-10-19 04:24:59.000000000 +0200 @@ -1,4 +1,5 @@ //! A simple, terminal-based Erlang dashboard. +use std::path::PathBuf; pub mod erlang; pub mod metrics; pub mod ui; @@ -17,6 +18,14 @@ /// By default, the content of the `$HOME/.erlang.cookie` file is used. #[clap(long, short = 'c')] pub cookie: Option<String>, + + /// If specified, the collected metrics will be recorded to the given file and can be replayed later. + #[clap(long, value_name = "FILE")] + pub record: Option<PathBuf>, + + /// If specified, the recorded metrics will be replayed. + #[clap(long, requires = "record")] + pub replay: bool, } impl Options { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/erldash-0.1.3~0/src/metrics.rs new/erldash-0.1.5~0/src/metrics.rs --- old/erldash-0.1.3~0/src/metrics.rs 2023-08-08 13:43:08.000000000 +0200 +++ new/erldash-0.1.5~0/src/metrics.rs 2023-10-19 04:24:59.000000000 +0200 @@ -1,22 +1,27 @@ use crate::erlang::{MSAccThread, RpcClient, SystemVersion}; use crate::Options; +use anyhow::Context; +use serde::{Deserialize, Serialize}; +use smol::fs::File; +use smol::io::AsyncWriteExt; use std::collections::BTreeMap; +use std::io::BufRead; use std::sync::mpsc; use std::time::{Duration, Instant}; type MetricsReceiver = mpsc::Receiver<Metrics>; type MetricsSender = mpsc::Sender<Metrics>; -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct Metrics { - pub timestamp: Instant, + pub timestamp: Duration, pub items: BTreeMap<String, MetricValue>, } impl Metrics { - fn new() -> Self { + fn new(start: Instant) -> Self { Self { - timestamp: Instant::now(), + timestamp: start.elapsed(), items: BTreeMap::new(), } } @@ -65,7 +70,7 @@ } } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub enum MetricValue { Gauge { value: u64, @@ -230,20 +235,121 @@ } #[derive(Debug)] -pub struct MetricsPoller { - pub rx: MetricsReceiver, - pub system_version: SystemVersion, - rpc_client: RpcClient, - old_microstate_accounting_flag: bool, +pub enum MetricsPoller { + Realtime(RealtimeMetricsPoller), + Replay(ReplayMetricsPoller), } impl MetricsPoller { pub fn start_thread(options: Options) -> anyhow::Result<Self> { + if options.replay { + ReplayMetricsPoller::new(options).map(Self::Replay) + } else { + RealtimeMetricsPoller::start_thread(options).map(Self::Realtime) + } + } + + pub fn is_replay(&self) -> bool { + matches!(self, Self::Replay(_)) + } + + pub fn system_version(&self) -> &SystemVersion { + match self { + Self::Realtime(poller) => &poller.system_version, + Self::Replay(poller) => &poller.system_version, + } + } + + pub fn poll_metrics(&self, timeout: Duration) -> Result<Metrics, mpsc::RecvTimeoutError> { + match self { + Self::Realtime(poller) => poller.rx.recv_timeout(timeout), + Self::Replay(_) => { + unreachable!() + } + } + } + + pub fn replay_last_time(&self) -> Duration { + match self { + Self::Realtime(_) => Duration::from_secs(0), + Self::Replay(poller) => poller + .metrics_log + .last() + .map(|m| m.timestamp) + .unwrap_or_default(), + } + } + + pub fn get_metrics_range( + &self, + start_time: Duration, + end_time: Duration, + ) -> anyhow::Result<impl '_ + Iterator<Item = &Metrics>> { + let Self::Replay(poller) = self else { + anyhow::bail!("`get_metrics_range()` is only available in replay mode"); + }; + Ok(poller.metrics_log.iter().filter(move |metrics| { + let time = metrics.timestamp; + start_time <= time && time <= end_time + })) + } +} + +#[derive(Debug)] +pub struct ReplayMetricsPoller { + system_version: SystemVersion, + metrics_log: Vec<Metrics>, +} + +impl ReplayMetricsPoller { + fn new(options: Options) -> anyhow::Result<Self> { + let Some(record_file_path) = options.record else { + anyhow::bail!("`--record` is required for replay mode"); + }; + let file = std::fs::File::open(&record_file_path).with_context(|| { + format!("failed to open record file: {}", record_file_path.display()) + })?; + let reader = std::io::BufReader::new(file); + + let mut system_version = None; + let mut metrics_log = Vec::new(); + for (i, line) in reader.lines().enumerate() { + let line = line?; + if i == 0 { + system_version = Some( + serde_json::from_str(&line) + .with_context(|| format!("failed to parse record file: line={}", i + 1))?, + ); + continue; + } + let metrics = serde_json::from_str(&line) + .with_context(|| format!("failed to parse record file: line={}", i + 1))?; + metrics_log.push(metrics); + } + let system_version = + system_version.ok_or_else(|| anyhow::anyhow!("record file is empty"))?; + Ok(Self { + system_version, + metrics_log, + }) + } +} + +#[derive(Debug)] +pub struct RealtimeMetricsPoller { + rx: MetricsReceiver, + system_version: SystemVersion, + rpc_client: RpcClient, + old_microstate_accounting_flag: bool, +} + +impl RealtimeMetricsPoller { + fn start_thread(options: Options) -> anyhow::Result<Self> { MetricsPollerThread::start_thread(options) } } -impl Drop for MetricsPoller { +impl Drop for RealtimeMetricsPoller { fn drop(&mut self) { if !self.old_microstate_accounting_flag { if let Err(e) = smol::block_on( @@ -264,10 +370,13 @@ rpc_client: RpcClient, tx: MetricsSender, prev_metrics: Metrics, + start: Instant, + system_version: SystemVersion, + record_file: Option<File>, } impl MetricsPollerThread { - fn start_thread(options: Options) -> anyhow::Result<MetricsPoller> { + fn start_thread(options: Options) -> anyhow::Result<RealtimeMetricsPoller> { let (tx, rx) = mpsc::channel(); let rpc_client: RpcClient = smol::block_on(async { @@ -282,28 +391,56 @@ "enabled microstate accounting (old flag state is {old_microstate_accounting_flag})" ); - let poller = MetricsPoller { + let poller = RealtimeMetricsPoller { rx, - system_version, + system_version: system_version.clone(), rpc_client: rpc_client.clone(), old_microstate_accounting_flag, }; + let record_file = if let Some(path) = &options.record { + Some(File::from(std::fs::File::create(path).with_context( + || format!("failed to record file {}", path.display()), + )?)) + } else { + None + }; + std::thread::spawn(|| { + let start = Instant::now(); Self { options, rpc_client, tx, - prev_metrics: Metrics::new(), + prev_metrics: Metrics::new(start), + start, + system_version, + record_file, } .run() }); Ok(poller) } + async fn write_json_line(&mut self, value: &impl serde::Serialize) -> anyhow::Result<()> { + if let Some(file) = &mut self.record_file { + let mut bytes = serde_json::to_vec(value)?; + bytes.push(b'\n'); + file.write_all(&bytes).await?; + file.flush().await?; + } + Ok(()) + } + fn run(mut self) { let interval = Duration::from_secs(self.options.polling_interval.get() as u64); + let mut next_time = Duration::from_secs(0); smol::block_on(async { + if let Err(e) = self.write_json_line(&self.system_version.clone()).await { + log::error!("faild to write record file: {e}"); + return; + } + loop { match self.poll_once().await { Err(e) => { @@ -311,12 +448,20 @@ break; } Ok(metrics) => { - let elapsed = metrics.timestamp.elapsed(); + let elapsed = metrics.timestamp; + + if let Err(e) = self.write_json_line(&metrics).await { + log::error!("faild to write record file: {e}"); + break; + } + if self.tx.send(metrics).is_err() { log::debug!("the main thread has terminated"); break; } - if let Some(sleep_duration) = interval.checked_sub(elapsed) { + + next_time += interval; + if let Some(sleep_duration) = next_time.checked_sub(elapsed) { std::thread::sleep(sleep_duration); } } @@ -379,7 +524,7 @@ } async fn poll_once(&mut self) -> anyhow::Result<Metrics> { - let mut metrics = Metrics::new(); + let mut metrics = Metrics::new(self.start); let msacc = self .rpc_client @@ -476,7 +621,7 @@ log::debug!( "MetricsPoller::poll_once(): elapsed={:?}", - metrics.timestamp.elapsed() + metrics.timestamp ); metrics.calc_delta(&self.prev_metrics); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/erldash-0.1.3~0/src/ui.rs new/erldash-0.1.5~0/src/ui.rs --- old/erldash-0.1.3~0/src/ui.rs 2023-08-08 13:43:08.000000000 +0200 +++ new/erldash-0.1.5~0/src/ui.rs 2023-10-19 04:24:59.000000000 +0200 @@ -1,7 +1,6 @@ use crate::erlang::SystemVersion; use crate::metrics::{format_u64, MetricValue, Metrics, MetricsPoller}; use crossterm::event::{KeyCode, KeyEvent}; -use ordered_float::OrderedFloat; use std::collections::{BTreeMap, VecDeque}; use std::sync::mpsc; use std::time::{Duration, Instant}; @@ -24,6 +23,7 @@ terminal: Terminal, poller: MetricsPoller, ui: UiState, + replay_cursor_time: Duration, } impl App { @@ -31,20 +31,23 @@ let terminal = Self::setup_terminal()?; log::debug!("setup terminal"); - let system_version = poller.system_version.clone(); + let replay_mode = poller.is_replay(); + let system_version = poller.system_version().clone(); Ok(Self { terminal, poller, - ui: UiState::new(system_version), + ui: UiState::new(system_version, replay_mode), + replay_cursor_time: Duration::default(), }) } pub fn run(mut self) -> anyhow::Result<()> { + self.render_replay_ui_if_need()?; loop { if self.handle_event()? { break; } - if self.ui.pause { + if self.ui.pause || self.ui.replay_mode { std::thread::sleep(POLL_TIMEOUT); } else { self.handle_poll()?; @@ -54,7 +57,7 @@ } fn handle_poll(&mut self) -> anyhow::Result<()> { - match self.poller.rx.recv_timeout(POLL_TIMEOUT) { + match self.poller.poll_metrics(POLL_TIMEOUT) { Err(mpsc::RecvTimeoutError::Disconnected) => { anyhow::bail!("Erlang metrics polling thread terminated unexpectedly"); } @@ -120,6 +123,20 @@ KeyCode::Char('p') => { self.ui.pause = !self.ui.pause; } + KeyCode::Char('h') => { + self.replay_cursor_time = self + .replay_cursor_time + .saturating_sub(Duration::from_secs(1)); + self.render_replay_ui_if_need()?; + } + KeyCode::Char('l') => { + if (self.replay_cursor_time + Duration::from_secs(1)) + < self.poller.replay_last_time() + { + self.replay_cursor_time += Duration::from_secs(1); + self.render_replay_ui_if_need()?; + } + } KeyCode::Left => { self.ui.focus = Focus::Main; } @@ -161,6 +178,41 @@ Ok(()) } + fn render_replay_ui_if_need(&mut self) -> anyhow::Result<()> { + if !self.ui.replay_mode { + return Ok(()); + } + + let time = self.replay_cursor_time; + + self.ui.history.clear(); + for metrics in self + .poller + .get_metrics_range(time, time + Duration::from_secs(CHART_DURATION))? + { + self.ui.history.push_back(metrics.clone()); + } + + self.ui.averages.clear(); + for metrics in self.poller.get_metrics_range( + time.saturating_sub(Duration::from_secs(CHART_DURATION)), + time, + )? { + for (name, item) in &metrics.items { + if let Some(avg) = self.ui.averages.get_mut(name) { + avg.add(item.clone()); + } else { + self.ui + .averages + .insert(name.clone(), AvgValue::new(item.clone())); + } + } + } + + self.render_ui()?; + Ok(()) + } + fn setup_terminal() -> anyhow::Result<Terminal> { crossterm::terminal::enable_raw_mode()?; let mut stdout = std::io::stdout(); @@ -201,10 +253,11 @@ focus: Focus, metrics_table_state: TableState, detail_table_state: TableState, + replay_mode: bool, } impl UiState { - fn new(system_version: SystemVersion) -> Self { + fn new(system_version: SystemVersion, replay_mode: bool) -> Self { Self { start: Instant::now(), system_version, @@ -214,6 +267,7 @@ focus: Focus::Main, metrics_table_state: TableState::default(), detail_table_state: TableState::default(), + replay_mode, } } @@ -254,7 +308,9 @@ } fn render_metrics(&mut self, f: &mut Frame, area: Rect) { - let block = if self.pause { + let block = if self.replay_mode { + self.make_block("Metrics (REPLAY)") + } else if self.pause { self.make_block("Metrics (PAUSED)") } else { self.make_block("Metrics") @@ -329,11 +385,19 @@ } fn render_help(&mut self, f: &mut Frame, area: Rect) { - let paragraph = Paragraph::new(vec![ - Spans::from("Quit: 'q' key"), - Spans::from("Pause / Resume: 'p' key"), - Spans::from("Move: UP / DOWN / LEFT / RIGHT keys"), - ]) + let paragraph = if self.replay_mode { + Paragraph::new(vec![ + Spans::from("Quit: 'q' key"), + Spans::from("Prev / Next: 'h' / 'l' keys"), + Spans::from("Move: UP / DOWN / LEFT / RIGHT keys"), + ]) + } else { + Paragraph::new(vec![ + Spans::from("Quit: 'q' key"), + Spans::from("Pause / Resume: 'p' key"), + Spans::from("Move: UP / DOWN / LEFT / RIGHT keys"), + ]) + } .block(self.make_block("Help")) .alignment(Alignment::Left); f.render_widget(paragraph, area); @@ -384,16 +448,14 @@ let lower_bound = data .iter() - .map(|(_, y)| OrderedFloat(*y)) - .min() - .map(|y| y.0) + .map(|(_, y)| *y) + .min_by(|a, b| a.total_cmp(b)) .expect("unreachable") .floor(); let mut upper_bound = data .iter() - .map(|(_, y)| OrderedFloat(*y)) - .max() - .map(|y| y.0) + .map(|(_, y)| *y) + .max_by(|a, b| a.total_cmp(b)) .expect("unreachable") .ceil(); let is_constant = lower_bound == upper_bound; ++++++ vendor.tar.xz ++++++ /work/SRC/openSUSE:Factory/erldash/vendor.tar.xz /work/SRC/openSUSE:Factory/.erldash.new.1945/vendor.tar.xz differ: char 26, line 1