Module: Misc
- Defined in:
- lib/scout/misc.rb,
lib/scout/misc/digest.rb,
lib/scout/misc/format.rb,
lib/scout/misc/helper.rb,
lib/scout/misc/insist.rb,
lib/scout/misc/system.rb,
lib/scout/misc/monitor.rb,
lib/scout/misc/filesystem.rb
Constant Summary collapse
- MAX_ARRAY_DIGEST_LENGTH =
100_000
- COLOR_LIST =
%w(#BC80BD #CCEBC5 #FFED6F #8DD3C7 #FFFFB3 #BEBADA #FB8072 #80B1D3 #FDB462 #B3DE69 #FCCDE5 #D9D9D9)
- CHAR_SENCONDS =
ENV["SCOUT_NOCOLOR"] == "true" ? "sec" : "″"
- MAX_TTY_LINE_WIDTH =
100
Class Method Summary collapse
- .benchmark(repeats = 1, message = nil) ⇒ Object
- .camel_case(string) ⇒ Object
- .camel_case_lower(string) ⇒ Object
- .children(ppid = nil) ⇒ Object
- .colors_for(list) ⇒ Object
- .counts(array) ⇒ Object
- .digest(obj) ⇒ Object
- .digest_str(obj) ⇒ Object
- .env_add(var, value, sep = ":", prepend = true) ⇒ Object
- .exec_time(&block) ⇒ Object
- .file_md5(file) ⇒ Object
- .fixascii(string) ⇒ Object
- .fixutf8(string) ⇒ Object
- .format_definition_list(defs, indent = nil, size = nil, color = :yellow, sep = "\n\n") ⇒ Object
- .format_definition_list_item(dt, dd, indent = nil, size = nil, color = :yellow) ⇒ Object
- .format_paragraph(text, size = nil, indent = nil, offset = nil) ⇒ Object
- .format_seconds(time, extended = false) ⇒ Object
- .format_seconds_short(time) ⇒ Object
- .hostname ⇒ Object
-
.humanize(value, options = {}) ⇒ Object
source: gist.github.com/ekdevdes/2450285 author: Ethan Kramer (github.com/ekdevdes).
- .humanize_list(list) ⇒ Object
- .in_dir(dir) ⇒ Object
- .insist(times = 4, sleep = nil, msg = nil) ⇒ Object
- .intersect_sorted_arrays(a1, a2) ⇒ Object
- .parse_sql_values(txt) ⇒ Object
- .path_relative_to(basedir, path) ⇒ Object
- .pid_alive?(pid) ⇒ Boolean
- .processors ⇒ Object
- .profile(options = {}) ⇒ Object
- .snake_case(string) ⇒ Object
- .to_utf8(string) ⇒ Object
- .update_git(gem_name = 'scout-gear') ⇒ Object
- .wait_for_interrupt ⇒ Object
- .with_env(var, value, &block) ⇒ Object
Class Method Details
.benchmark(repeats = 1, message = nil) ⇒ Object
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
# File 'lib/scout/misc/monitor.rb', line 6 def self.benchmark(repeats = 1, = nil) require 'benchmark' res = nil begin measure = Benchmark.measure do repeats.times do |i| res = yield i end end if puts "#{ }: #{ repeats } repeats" else puts "Benchmark for #{ repeats } repeats (#{caller.first})" end puts measure rescue Exception puts "Benchmark aborted" raise $! end res end |
.camel_case(string) ⇒ Object
114 115 116 117 118 119 |
# File 'lib/scout/misc/format.rb', line 114 def self.camel_case(string) return string if string !~ /_/ && string =~ /[A-Z]+.*/ string.split(/_|(\d+)/).map{|e| (e =~ /^[A-Z]{2,}$/ ? e : e.capitalize) }.join end |
.camel_case_lower(string) ⇒ Object
121 122 123 124 125 |
# File 'lib/scout/misc/format.rb', line 121 def self.camel_case_lower(string) string.split('_').inject([]){ |buffer,e| buffer.push(buffer.empty? ? e.downcase : (e =~ /^[A-Z]{2,}$/ ? e : e.capitalize)) }.join end |
.children(ppid = nil) ⇒ Object
9 10 11 12 13 14 |
# File 'lib/scout/misc/system.rb', line 9 def self.children(ppid = nil) require 'sys/proctable' ppid ||= Process.pid Sys::ProcTable.ps.select{ |pe| pe.ppid == ppid } end |
.colors_for(list) ⇒ Object
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
# File 'lib/scout/misc/format.rb', line 4 def self.colors_for(list) unused = COLOR_LIST.dup used = {} colors = list.collect do |elem| if used.include? elem used[elem] else color = unused.shift used[elem]=color color end end [colors, used] end |
.counts(array) ⇒ Object
21 22 23 24 25 26 27 28 29 |
# File 'lib/scout/misc/helper.rb', line 21 def self.counts(array) counts = {} array.each do |e| counts[e] ||= 0 counts[e] += 1 end counts end |
.digest(obj) ⇒ Object
52 53 54 55 |
# File 'lib/scout/misc/digest.rb', line 52 def self.digest(obj) str = String === obj ? obj : Misc.digest_str(obj) Digest::MD5.hexdigest(str) end |
.digest_str(obj) ⇒ Object
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
# File 'lib/scout/misc/digest.rb', line 3 def self.digest_str(obj) if obj.respond_to?(:digest_str) obj.digest_str else case obj when String #'\'' << obj << '\'' if Path === obj || ! Open.exists?(obj) '\'' << obj << '\'' elsif File.directory?(obj) "Directory MD5: #{digest_str(Dir.glob(File.join(obj, "*")))}" else "File MD5: #{Misc.file_md5(obj)}" end when Integer, Symbol obj.to_s when Array if obj.length > MAX_ARRAY_DIGEST_LENGTH length = obj.length mid = length/2 sample_pos = [1, 2, mid, length-2, length-1] "[#{length}:" << obj.values_at(*sample_pos).inject(""){|acc,o| acc.empty? ? Misc.digest_str(o) : acc << ', ' << Misc.digest_str(o) } << ']' else '[' << obj.inject(""){|acc,o| acc.empty? ? Misc.digest_str(o) : acc << ', ' << Misc.digest_str(o) } << ']' end when Hash '{' << obj.inject(""){|acc,p| s = Misc.digest_str(p.first) << "=" << Misc.digest_str(p.last); acc.empty? ? s : acc << ', ' << s } << '}' when Integer obj.to_s when Float if obj % 1 == 0 obj.to_i.to_s elsif obj.abs > 10 "%.1f" % obj elsif obj.abs > 1 "%.3f" % obj else "%.6f" % obj end when TrueClass "true" when FalseClass "false" else obj.inspect end end end |
.env_add(var, value, sep = ":", prepend = true) ⇒ Object
16 17 18 19 20 21 22 23 24 25 26 27 28 |
# File 'lib/scout/misc/system.rb', line 16 def self.env_add(var, value, sep = ":", prepend = true) if ENV[var].nil? ENV[var] = value elsif ENV[var] =~ /(#{sep}|^)#{Regexp.quote value}(#{sep}|$)/ return else if prepend ENV[var] = value + sep + ENV[var] else ENV[var] += sep + value end end end |
.exec_time(&block) ⇒ Object
46 47 48 49 50 51 52 53 54 55 |
# File 'lib/scout/misc/monitor.rb', line 46 def self.exec_time(&block) start = Time.now eend = nil begin yield ensure eend = Time.now end eend - start end |
.file_md5(file) ⇒ Object
57 58 59 60 61 62 63 64 |
# File 'lib/scout/misc/digest.rb', line 57 def self.file_md5(file) file = file.find if Path === file file = File.(file) #md5file = file + '.md5' Persist.persist("MD5:#{file}", :string) do Digest::MD5.file(file).hexdigest end end |
.fixascii(string) ⇒ Object
181 182 183 184 185 186 187 |
# File 'lib/scout/misc/format.rb', line 181 def self.fixascii(string) if string.respond_to?(:encode) self.fixutf8(string).encode("ASCII-8BIT") else string end end |
.fixutf8(string) ⇒ Object
193 194 195 196 197 198 199 200 201 202 203 204 205 |
# File 'lib/scout/misc/format.rb', line 193 def self.fixutf8(string) return nil if string.nil? return string if string.respond_to?(:encoding) && string.encoding.to_s == "UTF-8" && (string.respond_to?(:valid_encoding?) && string.valid_encoding?) || (string.respond_to?(:valid_encoding) && string.valid_encoding) if string.respond_to?(:encode) string.encode('UTF-8', 'binary', invalid: :replace, undef: :replace, replace: '') else require 'iconv' @@ic ||= Iconv.new('UTF-8//IGNORE', 'UTF-8') @@ic.iconv(string) end end |
.format_definition_list(defs, indent = nil, size = nil, color = :yellow, sep = "\n\n") ⇒ Object
103 104 105 106 107 108 109 110 111 112 |
# File 'lib/scout/misc/format.rb', line 103 def self.format_definition_list(defs, indent = nil, size = nil, color = :yellow, sep = "\n\n") indent ||= 30 size ||= (Log.tty_size || MAX_TTY_LINE_WIDTH) - indent entries = [] defs.each do |dt,dd| text = format_definition_list_item(dt,dd,indent, size,color) entries << text end entries * sep end |
.format_definition_list_item(dt, dd, indent = nil, size = nil, color = :yellow) ⇒ Object
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
# File 'lib/scout/misc/format.rb', line 77 def self.format_definition_list_item(dt, dd, indent = nil, size = nil, color = :yellow) if size.nil? base_size = MAX_TTY_LINE_WIDTH base_indent = indent || (base_size / 3) size = base_size - base_indent end indent ||= base_indent || size / 3 dd = "" if dd.nil? dt = Log.color color, dt if color dt = dt.to_s unless dd.empty? len = Log.uncolor(dt).length if indent < 0 text = format_paragraph(dd, size, indent.abs-1, 0) text = dt << "\n" << text else offset = len - indent offset = 0 if offset < 0 text = format_paragraph(dd, size, indent.abs+1, offset) text[0..len-1] = dt end text end |
.format_paragraph(text, size = nil, indent = nil, offset = nil) ⇒ Object
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
# File 'lib/scout/misc/format.rb', line 42 def self.format_paragraph(text, size = nil, indent = nil, offset = nil) size ||= Log.tty_size || MAX_TTY_LINE_WIDTH size = MAX_TTY_LINE_WIDTH if size > MAX_TTY_LINE_WIDTH indent ||= 0 offset ||= 0 i = 0 size = size + offset + indent re = /((?:\n\s*\n\s*)|(?:\n\s*(?=\*)))/ text.split(re).collect do |paragraph| i += 1 str = if i % 2 == 1 words = paragraph.gsub(/\s+/, "\s").split(" ") lines = [] line = " "*offset word = words.shift while word word = word[0..size-indent-offset-4] + '...' if word.length >= size - indent - offset while word and Log.uncolor(line).length + Log.uncolor(word).length <= size - indent line << word << " " word = words.shift end offset = 0 lines << ((" " * indent) << line[0..-2]) line = "" end (lines * "\n") else paragraph end offset = 0 str end*"" end |
.format_seconds(time, extended = false) ⇒ Object
21 22 23 24 25 26 |
# File 'lib/scout/misc/format.rb', line 21 def self.format_seconds(time, extended = false) seconds = time.to_i str = [seconds/3600, seconds/60 % 60, seconds % 60].map{|t| "%02i" % t }.join(':') str << ".%02i" % ((time - seconds) * 100) if extended str end |
.format_seconds_short(time) ⇒ Object
29 30 31 32 33 34 35 36 37 |
# File 'lib/scout/misc/format.rb', line 29 def self.format_seconds_short(time) if time < 0.0001 "%.5g" % time + CHAR_SENCONDS elsif time < 60 "%.2g" % time + CHAR_SENCONDS else format_seconds(time) end end |
.hostname ⇒ Object
3 4 5 6 7 |
# File 'lib/scout/misc/system.rb', line 3 def self.hostname @@hostname ||= begin `hostname`.strip end end |
.humanize(value, options = {}) ⇒ Object
source: gist.github.com/ekdevdes/2450285 author: Ethan Kramer (github.com/ekdevdes)
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 |
# File 'lib/scout/misc/format.rb', line 139 def self.humanize(value, = {}) if .empty? [:format] = :sentence end values = value.to_s.split('_') values.each_index do |index| # lower case each item in array # Miguel Vazquez edit: Except for acronyms values[index].downcase! unless values[index].match(/[a-zA-Z][A-Z]/) end if [:format] == :allcaps values.each do |value| value.capitalize! end if .empty? [:seperator] = " " end return values.join " " end if [:format] == :class values.each do |value| value.capitalize! end return values.join "" end if [:format] == :sentence values[0].capitalize! unless values[0].match(/[a-zA-Z][A-Z]/) return values.join " " end if [:format] == :nocaps return values.join " " end end |
.humanize_list(list) ⇒ Object
207 208 209 210 211 212 213 214 |
# File 'lib/scout/misc/format.rb', line 207 def self.humanize_list(list) return "" if list.empty? if list.length == 1 list.first else list[0..-2].collect{|e| e.to_s} * ", " << " and " << list[-1].to_s end end |
.in_dir(dir) ⇒ Object
2 3 4 5 6 7 8 9 10 11 |
# File 'lib/scout/misc/filesystem.rb', line 2 def self.in_dir(dir) old_pwd = FileUtils.pwd begin FileUtils.mkdir_p dir unless File.exist?(dir) FileUtils.cd dir yield ensure FileUtils.cd old_pwd end end |
.insist(times = 4, sleep = nil, msg = nil) ⇒ Object
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/scout/misc/insist.rb', line 2 def self.insist(times = 4, sleep = nil, msg = nil) sleep_array = nil try = 0 begin begin yield rescue Exception if Array === times sleep_array = times times = sleep_array.length sleep = sleep_array.shift end if sleep.nil? sleep_array = ([0] + [0.001, 0.01, 0.1, 0.5] * (times / 3)).sort[0..times-1] sleep = sleep_array.shift end raise $! end rescue TryAgain sleep sleep retry rescue StopInsist raise $!.exception rescue Aborted, Interrupt if msg Log.warn("Not Insisting after Aborted: #{$!.} -- #{msg}") else Log.warn("Not Insisting after Aborted: #{$!.}") end raise $! rescue Exception Log.exception $! if ENV["SCOUT_LOG_INSIST"] == 'true' if msg Log.warn("Insisting after exception: #{$!.class} #{$!.} -- #{msg}") elsif FalseClass === msg nil else Log.warn("Insisting after exception: #{$!.class} #{$!.}") end if sleep and try > 0 sleep sleep sleep = sleep_array.shift || sleep if sleep_array else Thread.pass end try += 1 retry if try < times raise $! end end |
.intersect_sorted_arrays(a1, a2) ⇒ Object
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
# File 'lib/scout/misc/helper.rb', line 2 def self.intersect_sorted_arrays(a1, a2) e1, e2 = a1.shift, a2.shift intersect = [] while true break if e1.nil? or e2.nil? case e1 <=> e2 when 0 intersect << e1 e1, e2 = a1.shift, a2.shift when -1 e1 = a1.shift while not e1.nil? and e1 < e2 when 1 e2 = a2.shift e2 = a2.shift while not e2.nil? and e2 < e1 end end intersect end |
.parse_sql_values(txt) ⇒ Object
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 |
# File 'lib/scout/misc/format.rb', line 216 def self.parse_sql_values(txt) io = StringIO.new txt.strip values = [] fields = [] current = nil quoted = false while c = io.getc if quoted if c == "'" quoted = false else current << c end else case c when "(" current = "" when ")" fields << current values << fields fields = [] current = nil when ',' if not current.nil? fields << current current = "" end when "'" quoted = true when ";" break else current << c end end end values end |
.path_relative_to(basedir, path) ⇒ Object
13 14 15 16 17 18 19 20 21 22 23 24 |
# File 'lib/scout/misc/filesystem.rb', line 13 def self.path_relative_to(basedir, path) path = File.(path) unless path.slice(0,1) == "/" basedir = File.(basedir) unless basedir.slice(0,1) == "/" basedir += "/" unless basedir.slice(-2,-1) == "/" if path.start_with?(basedir) return path.slice(basedir.length, basedir.length) else return nil end end |
.pid_alive?(pid) ⇒ Boolean
2 3 4 |
# File 'lib/scout/misc/monitor.rb', line 2 def self.pid_alive?(pid) !! Process.kill(0, pid) rescue false end |
.processors ⇒ Object
70 71 72 |
# File 'lib/scout/misc/system.rb', line 70 def self.processors Etc.nprocessors end |
.profile(options = {}) ⇒ Object
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/scout/misc/monitor.rb', line 28 def self.profile( = {}) require 'ruby-prof' profiler = RubyProf::Profile.new profiler.start begin res = yield rescue Exception puts "Profiling aborted" raise $! ensure result = profiler.stop printer = RubyProf::FlatPrinter.new(result) printer.print(STDOUT, ) end res end |
.snake_case(string) ⇒ Object
127 128 129 130 131 132 133 134 135 |
# File 'lib/scout/misc/format.rb', line 127 def self.snake_case(string) return nil if string.nil? string = string.to_s if Symbol === string string. gsub(/([A-Z]{2,})([A-Z][a-z])/,'\1_\2'). gsub(/([a-z])([A-Z])/,'\1_\2'). gsub(/\s/,'_').gsub(/[^\w]/, ''). split("_").collect{|p| p.match(/[A-Z]{2,}/) ? p : p.downcase } * "_" end |
.to_utf8(string) ⇒ Object
189 190 191 |
# File 'lib/scout/misc/format.rb', line 189 def self.to_utf8(string) string.encode("UTF-16BE", :invalid => :replace, :undef => :replace, :replace => "?").encode('UTF-8') end |
.update_git(gem_name = 'scout-gear') ⇒ Object
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
# File 'lib/scout/misc/system.rb', line 40 def self.update_git(gem_name = 'scout-gear') gem_name = 'scout-gear' if gem_name.nil? dir = File.join(__dir__, '../../../../', gem_name) return unless Open.exist?(dir) Misc.in_dir dir do begin begin CMD.cmd_log('git pull') rescue raise "Could not update #{gem_name}" end begin CMD.cmd_log('git submodule update') rescue raise "Could not update #{gem_name} submodules" end begin CMD.cmd_log('rake install') rescue raise "Could not install updated #{gem_name}" end rescue Log.warn $!. end end end |
.wait_for_interrupt ⇒ Object
57 58 59 60 61 62 63 64 65 |
# File 'lib/scout/misc/monitor.rb', line 57 def self.wait_for_interrupt while true begin sleep 1 rescue Interrupt break end end end |
.with_env(var, value, &block) ⇒ Object
30 31 32 33 34 35 36 37 38 |
# File 'lib/scout/misc/system.rb', line 30 def self.with_env(var, value, &block) old_value = ENV[var] begin ENV[var] = value yield ensure ENV[var] = old_value end end |