History

implement progress trait for logs with throttling

Sebastian Thiel committed 6 years ago

Commit 287eca91 parent e82e63f5 files · +121 −6Browse files

Unified · Split

5 files
  1. Cargo.lock +10 −0
  2. Cargo.toml +1 −1
  3. git-features/Cargo.toml +4 −0
  4. git-features/src/progress.rs +103 −5
  5. tasks.md +3 −0
Cargo.lock+10−0
@@ -290,6 +290,7 @@ dependencies = [ · 289 unmodified lines
290290 "crossbeam-utils",
291291 "flume",
292292 "git-object",
293+ "log",
293294 "num_cpus",
294295 "sha-1",
295296 "sha1",
@@ -401,6 +402,15 @@ version = "0.2.71" · 105 unmodified lines
401402 source = "registry+https://github.com/rust-lang/crates.io-index"
402403 checksum = "9457b06509d27052635f90d6466700c65095fdf75409b3fbdd903e988b886f49"
403404
405+[[package]]
406+name = "log"
407+version = "0.4.8"
408+source = "registry+https://github.com/rust-lang/crates.io-index"
409+checksum = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
410+dependencies = [
411+ "cfg-if",
412+]
413+
404414 [[package]]
405415 name = "maybe-uninit"
406416 version = "2.0.0"
Cargo.toml+1−1
@@ -23,7 +23,7 @@ doctest = false · 22 unmodified lines
2323 default = ["fast", "pretty-cli"]
2424 fast = ["git-features/parallel", "git-features/fast-sha1"]
2525 pretty-cli = ["structopt"]
26−lean-cli = ["argh"]
26+lean-cli = ["argh", "git-features/progress-log"]
2727
2828 [dependencies]
2929 anyhow = "1.0.31"
git-features/Cargo.toml+4−0
@@ -14,6 +14,7 @@ test = false · 13 unmodified lines
1414 [features]
1515 parallel = ["flume", "crossbeam-utils", "crossbeam-channel", "num_cpus"]
1616 fast-sha1 = ["fastsha1"]
17+progress-log = ["log"]
1718
1819 [dependencies]
1920 # 'parallel' feature
@@ -27,3 +28,6 @@ sha1 = "0.6.0" · 7 unmodified lines
2728 crc = "1.8.1"
2829 git-object = { version = "0.1.0", path = "../git-object" }
2930 fastsha1 = { package = "sha-1", version = "0.9.1", optional = true }
31+
32+# progress
33+log = { version = "0.4.8", optional = true }
git-features/src/progress.rs+103−5
@@ -1,8 +1,21 @@
1+/// The severity of a message
2+#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
3+pub enum MessageLevel {
4+ /// Rarely sent information related to the progress, not to be confused with the progress itself
5+ Info,
6+ /// Used to indicate that a task has failed, along with the reason
7+ Failure,
8+ /// Indicates a task was completed successfully
9+ Success,
10+}
11+
112 pub trait Progress {
13+ type SubProgress: Progress;
14+
215 /// Adds a new child, whose parent is this instance, with the given name.
316 ///
417 /// This will make the child progress to appear contained in the parent progress.
5− fn add_child(&self, name: impl Into<String>) -> Self;
18+ fn add_child(&mut self, name: impl Into<String>) -> Self::SubProgress;
619
720 /// Initialize the Item for receiving progress information.
821 ///
@@ -19,15 +32,100 @@ pub trait Progress { · 10 unmodified lines
1932 /// **Note** that this method can be called multiple times, changing the bounded-ness and unit at will.
2033 fn init(&mut self, max: Option<u32>, unit: Option<&'static str>);
2134
22− /// Set the current progress to the given `step`.
35+ /// Set the current progress to the given `step`. The cost of this call is negligible,
36+ /// making manual throttling *not* necessary.
2337 ///
2438 /// **Note**: that this call has no effect unless `init(…)` was called before.
2539 fn set(&mut self, step: u32);
2640
41+ /// Create a `message` of the given `level` and store it with the progress tree.
42+ ///
43+ /// Use this to provide additional,human-readable information about the progress
44+ /// made, including indicating success or failure.
45+ fn message(&self, level: MessageLevel, message: impl Into<String>);
46+
2747 /// Create a message providing additional information about the progress thus far.
28− fn info(&self, name: impl Into<String>) -> Self;
48+ fn info(&self, message: impl Into<String>) {
49+ self.message(MessageLevel::Info, message)
50+ }
2951 /// Create a message indicating the task is done successfully
30− fn done(&self, name: impl Into<String>) -> Self;
52+ fn done(&self, message: impl Into<String>) {
53+ self.message(MessageLevel::Success, message)
54+ }
3155 /// Create a message indicating the task failed
32− fn fail(&self, name: impl Into<String>) -> Self;
56+ fn fail(&self, message: impl Into<String>) {
57+ self.message(MessageLevel::Failure, message)
58+ }
59+}
60+
61+#[cfg(feature = "progress-log")]
62+mod log {
63+ use crate::progress::{MessageLevel, Progress};
64+ use std::time::Duration;
65+
66+ pub struct LogProgress {
67+ name: String,
68+ max: Option<u32>,
69+ unit: Option<&'static str>,
70+ last_set: Option<std::time::SystemTime>,
71+ }
72+
73+ const EMIT_LOG_EVERY_S: f32 = 0.5;
74+
75+ impl LogProgress {
76+ pub fn new(name: impl Into<String>) -> Self {
77+ LogProgress {
78+ name: name.into(),
79+ max: None,
80+ unit: None,
81+ last_set: None,
82+ }
83+ }
84+ }
85+
86+ impl Progress for LogProgress {
87+ type SubProgress = LogProgress;
88+
89+ fn add_child(&mut self, name: impl Into<String>) -> Self::SubProgress {
90+ LogProgress::new(format!("{}::{}", self.name, Into::<String>::into(name)))
91+ }
92+
93+ fn init(&mut self, max: Option<u32>, unit: Option<&'static str>) {
94+ self.max = max;
95+ self.unit = unit;
96+ }
97+
98+ fn set(&mut self, step: u32) {
99+ let now = std::time::SystemTime::now();
100+ let last = self.last_set.unwrap_or(now);
101+ if now
102+ .duration_since(last)
103+ .unwrap_or_else(|_| Duration::default())
104+ .as_secs_f32()
105+ > EMIT_LOG_EVERY_S
106+ {
107+ match (self.max, self.unit) {
108+ (Some(max), Some(unit)) => {
109+ log::info!("{} → {} / {} {}", self.name, step, max, unit)
110+ }
111+ (None, Some(unit)) => log::info!("{} → {} {}", self.name, step, unit),
112+ (Some(max), None) => log::info!("{} → {} / {}", self.name, step, max),
113+ (None, None) => log::info!("{} → {}", self.name, step),
114+ }
115+ }
116+ self.last_set = Some(now);
117+ }
118+
119+ fn message(&self, level: MessageLevel, message: impl Into<String>) {
120+ let message: String = message.into();
121+ match level {
122+ MessageLevel::Info => log::info!("ℹ{} → {}", self.name, message),
123+ MessageLevel::Failure => log::error!("𐄂{} → {}", self.name, message),
124+ MessageLevel::Success => log::info!("✓{} → {}", self.name, message),
125+ }
126+ }
127+ }
33128 }
129+
130+#[cfg(feature = "progress-log")]
131+pub use self::log::LogProgress;
tasks.md+3−0
@@ -29,4 +29,7 @@ · 28 unmodified lines
2929 * [ ] a verbose mode to list each object in a pack, similar to existing git-verify-pack
3030 * **stress**
3131 * [ ] first stress test for validation of a big repository, linux maybe, or something smaller but big enough
32+* **unrelated**
33+ * [ ] Use `argh` in cargo-diet to reduce build times
34+ * [ ] Use `argh` in prodash dashboard example to reduce build times
3235