scout-gear 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,240 @@
1
+ require 'yaml'
2
+ module Log
3
+ class ProgressBar
4
+ def print(io, str)
5
+ return if Log.no_bar
6
+ STDERR.print str
7
+ Log.logfile.puts str unless Log.logfile.nil?
8
+ Log::LAST.replace "progress"
9
+ end
10
+
11
+ attr_accessor :history, :mean_max, :max_history
12
+ def thr_msg
13
+ if @history.nil?
14
+ @history ||= [[0, @start], [@ticks, Time.now] ]
15
+ elsif @last_ticks != @ticks
16
+ @history << [@ticks, Time.now]
17
+ max_history ||= begin
18
+ max_history = case
19
+ when @ticks > 20
20
+ count = @ticks - @last_count
21
+ count = 1 if count == 0
22
+ if @max
23
+ times = @max / count
24
+ num = times / 20
25
+ num = 2 if num < 2
26
+ else
27
+ num = 10
28
+ end
29
+ count * num
30
+ else
31
+ 20
32
+ end
33
+ max_history = 30 if max_history > 30
34
+ max_history
35
+ end
36
+ @history.shift if @history.length > max_history
37
+ end
38
+
39
+ @last_ticks = @ticks
40
+
41
+ @mean_max ||= 0
42
+ if @history.length > 3
43
+
44
+ sticks, stime = @history.first
45
+ ssticks, sstime = @history[-3]
46
+ lticks, ltime = @history.last
47
+
48
+
49
+ mean = @mean = (lticks - sticks).to_f / (ltime - stime)
50
+ short_mean = (lticks - ssticks).to_f / (ltime - sstime)
51
+
52
+ @mean_max = mean if mean > @mean_max
53
+ end
54
+
55
+ if short_mean
56
+ thr = short_mean
57
+ else
58
+ thr = begin
59
+ (@ticks || 1) / (Time.now - @start)
60
+ rescue
61
+ 1
62
+ end
63
+ end
64
+
65
+ thr = 0.0000001 if thr == 0
66
+
67
+ if mean.nil? or mean.to_i > 2
68
+ str = "#{ Log.color :blue, thr.to_i.to_s } per sec."
69
+ #str << " #{ Log.color :yellow, mean.to_i.to_s } avg. #{Log.color :yellow, @mean_max.to_i.to_s} max." if @mean_max > 0
70
+ else
71
+ if 1.0/thr < 1
72
+ str = "#{ Log.color :blue, (1.0/thr).round(2).to_s } secs each"
73
+ elsif 1.0/thr < 2
74
+ str = "#{ Log.color :blue, (1.0/thr).round(1).to_s } secs each"
75
+ else
76
+ str = "#{ Log.color :blue, (1/thr).ceil.to_s } secs each"
77
+ end
78
+ #str << " #{ Log.color :yellow, (1/mean).ceil.to_s } avg. #{Log.color :yellow, (1/@mean_max).ceil.to_s} min." if @mean_max > 0
79
+ end
80
+
81
+ str
82
+ end
83
+
84
+
85
+ def eta_msg
86
+ percent = self.percent
87
+ time = Time.now
88
+
89
+ indicator = ""
90
+ 10.times{|i|
91
+ if i < percent / 10 then
92
+ indicator << Log.color(:yellow, ".")
93
+ else
94
+ indicator << " "
95
+ end
96
+ }
97
+
98
+ indicator << " #{Log.color(:blue, percent.to_s << "%")}"
99
+
100
+ used = time - @start
101
+ if @mean_max and @mean_max > 0 and @mean > 0
102
+ eta = (@max - @ticks) / @mean
103
+ else
104
+ eta = (@max - @ticks) / (@ticks/used)
105
+ end
106
+
107
+ used = Misc.format_seconds(used)
108
+ eta = [eta/3600, eta/60 % 60, eta % 60].map{|t| "%02i" % t }.join(':')
109
+
110
+ #indicator << " #{Log.color :yellow, used} used #{Log.color :yellow, eta} left - #{Log.color :yellow, ticks.to_s} of #{Log.color :yellow, @max.to_s} #{bytes ? 'bytes' : 'items'}"
111
+ indicator << " #{Log.color :yellow, eta} => #{Log.color :yellow, used} - #{Log.color :yellow, ticks.to_s} of #{Log.color :yellow, @max.to_s} #{bytes ? 'bytes' : 'items'}"
112
+
113
+ indicator
114
+ end
115
+
116
+ def report_msg
117
+ str = Log.color(:magenta, "·")
118
+ if @ticks == 0
119
+ if @max
120
+ return str << " " << Log.color(:magenta, "waiting on #{@max} #{bytes ? 'bytes' : 'items'}") << Log.color(:magenta, " · " << desc)
121
+ else
122
+ return str << " " << Log.color(:magenta, "waiting - PID: #{Process.pid}") << Log.color(:magenta, " · " << desc)
123
+ end
124
+ end
125
+ str << " " << thr_msg
126
+ if max
127
+ str << Log.color(:blue, " -- ") << eta_msg
128
+ else
129
+ str << Log.color(:blue, " -- ") << ticks.to_s << " #{bytes ? 'bytes' : 'items'}"
130
+ end
131
+ str << Log.color(:magenta, " · " << desc)
132
+ str
133
+ end
134
+
135
+ def load(info)
136
+ info.each do |key, value|
137
+ case key.to_sym
138
+ when :start
139
+ @start = value
140
+ when :last_time
141
+ @last_time = value
142
+ when :last_count
143
+ @last_count = value
144
+ when :last_percent
145
+ @last_percent = value
146
+ when :desc
147
+ @desc = value
148
+ when :ticks
149
+ @ticks = value
150
+ when :max
151
+ @max = value
152
+ when :mean
153
+ @mean = value
154
+ end
155
+ end
156
+ end
157
+
158
+ def save
159
+ info = {:start => @start, :last_time => @last_time, :last_count => @last_count, :last_percent => @last_percent, :desc => @desc, :ticks => @ticks, :max => @max, :mean => @mean}
160
+ info.delete_if{|k,v| v.nil?}
161
+ File.write(file, info.to_yaml)
162
+ end
163
+
164
+ def report(io = STDERR)
165
+ if Log::LAST != "progress"
166
+ bars = BARS
167
+ if Log::LAST == "new_bar"
168
+ Log::LAST.replace "progress"
169
+ bar = bars.sort_by{|b| b.depth }.first
170
+ print(io, Log.color(:magenta ,bar.report_msg) << "\n")
171
+ else
172
+ length = Log::ProgressBar.cleanup_bars
173
+ print(io, Log.color(:magenta, "···Progress\n"))
174
+ bars.sort_by{|b| b.depth }.reverse.each do |bar|
175
+ if SILENCED.include? bar
176
+ print(io, Log.color(:magenta, "·\n"))
177
+ else
178
+ print(io, Log.color(:magenta ,bar.report_msg) << "\n")
179
+ end
180
+ end
181
+ end
182
+ else
183
+ bars = BARS
184
+ end
185
+ bars << self unless BARS.include? self
186
+
187
+ print(io, Log.up_lines(bars.length) << Log.color(:magenta, "···Progress\n") << Log.down_lines(bars.length+1)) if Log::ProgressBar.offset == 0
188
+ print(io, Log.up_lines(@depth) << report_msg << "\n" << Log.down_lines(@depth - 1))
189
+ @last_time = Time.now
190
+ @last_count = ticks
191
+ @last_percent = percent if max and max > 0
192
+ Log::LAST.replace "progress"
193
+ save if file
194
+ end
195
+
196
+ def done(io = STDERR)
197
+ done_msg = Log.color(:magenta, "· ") << Log.color(:green, "done")
198
+ if @start
199
+ ellapsed = (Time.now - @start).to_i
200
+ else
201
+ ellapsed = 0
202
+ end
203
+ ellapsed = [ellapsed/3600, ellapsed/60 % 60, ellapsed % 60].map{|t| "%02i" % t }.join(':')
204
+ done_msg << " " << Log.color(:blue, (@ticks).to_s) << " #{bytes ? 'bytes' : 'items'} in " << Log.color(:green, ellapsed)
205
+ @last_count = 0
206
+ @last_time = @start
207
+ done_msg << " - " << thr_msg
208
+ done_msg << Log.color(:magenta, " · " << desc)
209
+ print(io, Log.up_lines(@depth) << done_msg << Log.down_lines(@depth))
210
+
211
+ FileUtils.rm file if file and File.exists?(file)
212
+
213
+ @callback.call self if @callback
214
+ end
215
+
216
+ def error(io = STDERR)
217
+ done_msg = Log.color(:magenta, "· ") << Log.color(:red, "error")
218
+ if @start
219
+ ellapsed = (Time.now - @start).to_i
220
+ else
221
+ ellapsed = 0
222
+ end
223
+ ellapsed = [ellapsed/3600, ellapsed/60 % 60, ellapsed % 60].map{|t| "%02i" % t }.join(':')
224
+ done_msg << " " << Log.color(:blue, (@ticks).to_s) << " in " << Log.color(:green, ellapsed)
225
+ @last_count = 0
226
+ @last_time = @start
227
+ done_msg << " - " << thr_msg
228
+ done_msg << Log.color(:magenta, " · " << desc)
229
+ print(io, Log.up_lines(@depth) << done_msg << Log.down_lines(@depth))
230
+
231
+ File.rm file if file and File.exist?(file)
232
+
233
+ begin
234
+ @callback.call self
235
+ rescue
236
+ Log.debug "Callback failed for filed progress bar: #{$!.message}"
237
+ end if @callback
238
+ end
239
+ end
240
+ end
@@ -0,0 +1,100 @@
1
+ require_relative '../../exceptions'
2
+ module Log
3
+ class ProgressBar
4
+ BAR_MUTEX = Mutex.new
5
+ BARS = []
6
+ REMOVE = []
7
+ SILENCED = []
8
+
9
+ def self.add_offset(value = 1)
10
+ value = 1 if TrueClass === value
11
+ @@offset = offset + value.to_i
12
+ @@offset = 0 if @@offset < 0
13
+ @@offset
14
+ end
15
+
16
+ def self.remove_offset(value = 1)
17
+ value = 1 if TrueClass === value
18
+ @@offset = offset - value.to_i
19
+ @@offset = 0 if @@offset < 0
20
+ @@offset
21
+ end
22
+
23
+
24
+ def self.offset
25
+ @@offset ||= 0
26
+ @@offset = 0 if @@offset < 0
27
+ @@offset
28
+ end
29
+
30
+ def self.new_bar(max, options = {})
31
+ cleanup_bars
32
+ BAR_MUTEX.synchronize do
33
+ Log::LAST.replace "new_bar" if Log::LAST == "progress"
34
+ options = IndiferentHash.add_defaults options, :depth => BARS.length + Log::ProgressBar.offset
35
+ BARS << (bar = ProgressBar.new(max, options))
36
+ bar
37
+ end
38
+ end
39
+
40
+ def self.cleanup_bars
41
+ BAR_MUTEX.synchronize do
42
+ REMOVE.each do |bar|
43
+ index = BARS.index bar
44
+ if index
45
+ BARS.delete_at index
46
+ BARS.each_with_index do |bar,i|
47
+ bar.depth = i
48
+ end
49
+ end
50
+ index = SILENCED.index bar
51
+ if index
52
+ SILENCED.delete_at index
53
+ SILENCED.each_with_index do |bar,i|
54
+ bar.depth = i
55
+ end
56
+ end
57
+ end
58
+ REMOVE.clear
59
+ BARS.length
60
+ end
61
+ end
62
+
63
+ def self.remove_bar(bar, error = false)
64
+ BAR_MUTEX.synchronize do
65
+ return if REMOVE.include? bar
66
+ end
67
+ if error
68
+ bar.error if bar.respond_to? :error
69
+ else
70
+ bar.done if bar.respond_to? :done
71
+ end
72
+ BAR_MUTEX.synchronize do
73
+ REMOVE << bar
74
+ end
75
+ Log::LAST.replace "remove_bar" if Log::LAST == "progress"
76
+ end
77
+
78
+ def remove(error = false)
79
+ Log::ProgressBar.remove_bar self, error
80
+ end
81
+
82
+ def self.with_bar(max, options = {})
83
+ bar = new_bar(max, options)
84
+ res = nil
85
+ begin
86
+ error = false
87
+ keep = false
88
+ yield bar
89
+ rescue KeepBar
90
+ keep = true
91
+ rescue
92
+ error = true
93
+ raise $!
94
+ ensure
95
+ remove_bar(bar, error) if bar
96
+ end
97
+ end
98
+ end
99
+ end
100
+
@@ -0,0 +1,102 @@
1
+ require_relative 'progress/util'
2
+ require_relative 'progress/report'
3
+ module Log
4
+
5
+ def self.no_bar=(value)
6
+ @@no_bar = value
7
+ end
8
+
9
+ def self.no_bar
10
+ @@no_bar = false unless defined?(@@no_bar)
11
+ @@no_bar || ENV["RBBT_NO_PROGRESS"] == "true"
12
+ end
13
+
14
+ class ProgressBar
15
+
16
+ class << self
17
+ attr_accessor :default_file
18
+ end
19
+
20
+ attr_accessor :max, :ticks, :frequency, :depth, :desc, :file, :bytes, :process, :callback
21
+
22
+ def initialize(max = nil, options = {})
23
+ depth, num_reports, desc, io, severity, file, bytes, frequency, process, callback =
24
+ IndiferentHash.process_options options, :depth, :num_reports, :desc, :io, :severity, :file, :bytes, :frequency, :process, :callback,
25
+ :depth => 0, :num_reports => 100, :io => STDERR, :severity => Log.severity, :frequency => 2
26
+
27
+ @max = max
28
+ @ticks = 0
29
+ @frequency = frequency
30
+ @last_time = nil
31
+ @last_count = nil
32
+ @last_percent = nil
33
+ @depth = depth
34
+ @desc = desc.nil? ? "" : desc.gsub(/\n/,' ')
35
+ @file = file
36
+ @bytes = bytes
37
+ @process = process
38
+ @callback = callback
39
+ end
40
+
41
+ def percent
42
+ return 0 if @ticks == 0
43
+ return 100 if @max == 0
44
+ (@ticks * 100) / @max
45
+ end
46
+
47
+ def file
48
+ @file || ProgressBar.default_file
49
+ end
50
+
51
+ def init
52
+ @ticks, @bytes = 0
53
+ @last_time = @last_count = @last_percent = nil
54
+ @history, @mean_max, @max_history = nil
55
+ @start = @last_time = Time.now
56
+ @last_count = 0
57
+ report
58
+ end
59
+
60
+ def tick(step = 1)
61
+ return if Log.no_bar
62
+ @ticks += step
63
+
64
+ time = Time.now
65
+ if @last_time.nil?
66
+ @last_time = time
67
+ @last_count = @ticks
68
+ @start = time
69
+ return
70
+ end
71
+
72
+ diff = time - @last_time
73
+ report and return if diff >= @frequency
74
+ return unless max and max > 0
75
+
76
+ percent = self.percent
77
+ if @last_percent.nil?
78
+ @last_percent = percent
79
+ return
80
+ end
81
+ report && return if percent > @last_percent and diff > 0.3
82
+ end
83
+
84
+ def pos(pos)
85
+ step = pos - (@ticks || 0)
86
+ tick(step)
87
+ end
88
+
89
+ def process(elem)
90
+ case res = @process.call(elem)
91
+ when FalseClass
92
+ nil
93
+ when TrueClass
94
+ tick
95
+ when Integer
96
+ pos(res)
97
+ when Float
98
+ pos(res * max)
99
+ end
100
+ end
101
+ end
102
+ end