Class: Doing::Logger
Overview
Log adapter
Constant Summary collapse
- TOPIC_WIDTH =
12
- LOG_LEVELS =
{ debug: ::Logger::DEBUG, info: ::Logger::INFO, warn: ::Logger::WARN, error: ::Logger::ERROR }.freeze
- COUNT_KEYS =
%i[ added added_tags archived autotag completed completed_archived deleted moved removed_tags rotated skipped updated exported ].freeze
Instance Attribute Summary collapse
-
#level ⇒ Object
readonly
Returns the current log level (debug, info, warn, error).
-
#logdev ⇒ Object
writeonly
Sets the log device.
-
#max_length ⇒ Object
writeonly
Max length of log messages (truncate in middle).
-
#messages ⇒ Object
readonly
Returns the value of attribute messages.
-
#results ⇒ Object
readonly
Returns the value of attribute results.
Instance Method Summary collapse
-
#abort_with(topic, message = nil, &block) ⇒ Object
Print an error message and immediately abort the process.
- #adjust_verbosity(options = {}) ⇒ Object
- #benchmark(key, state) ⇒ Object
- #count(key, level: :info, count: 1, tag: nil, message: nil) ⇒ Object
-
#debug(topic, message = nil, &block) ⇒ Object
Print a debug message.
-
#error(topic, message = nil, &block) ⇒ Object
Print an error message.
-
#formatted_topic(topic, colon: false) ⇒ Object
Format the topic.
-
#info(topic, message = nil, &block) ⇒ Object
Print a message.
-
#initialize(level = :info) ⇒ Logger
constructor
Create a new instance of a log writer.
- #log_benchmarks ⇒ Object
- #log_change(tags_added: [], tags_removed: [], count: 1, item: nil, single: false) ⇒ Object
-
#log_level=(level = 'info') ⇒ Object
Set the log level on the writer.
-
#log_now(level, topic, message = nil, &block) ⇒ Object
Log to console immediately instead of writing messages on exit.
-
#output_results ⇒ Object
Output registers based on log level.
-
#restore_level ⇒ Object
Restore temporary level.
-
#temp_level(level) ⇒ Object
Set log level temporarily.
-
#warn(topic, message = nil, &block) ⇒ Object
Print a message.
-
#write(level_of_message, topic, message = nil, &block) ⇒ Boolean
Log a message.
Constructor Details
#initialize(level = :info) ⇒ Logger
Create a new instance of a log writer
49 50 51 52 53 54 55 56 57 58 |
# File 'lib/doing/logger.rb', line 49 def initialize(level = :info) @messages = [] @counters = {} COUNT_KEYS.each { |key| @counters[key] = { tag: [], count: 0 } } @results = [] @logdev = $stderr @max_length = TTY::Screen.columns - 5 || 85 self.log_level = level @prev_level = level end |
Instance Attribute Details
#level ⇒ Object (readonly)
Returns the current log level (debug, info, warn, error)
15 16 17 |
# File 'lib/doing/logger.rb', line 15 def level @level end |
#logdev=(value) ⇒ Object (writeonly)
Sets the log device
9 10 11 |
# File 'lib/doing/logger.rb', line 9 def logdev=(value) @logdev = value end |
#max_length=(value) ⇒ Object (writeonly)
Max length of log messages (truncate in middle)
12 13 14 |
# File 'lib/doing/logger.rb', line 12 def max_length=(value) @max_length = value end |
#messages ⇒ Object (readonly)
Returns the value of attribute messages.
17 18 19 |
# File 'lib/doing/logger.rb', line 17 def @messages end |
#results ⇒ Object (readonly)
Returns the value of attribute results.
17 18 19 |
# File 'lib/doing/logger.rb', line 17 def results @results end |
Instance Method Details
#abort_with(topic, message = nil, &block) ⇒ Object
Print an error message and immediately abort the process
187 188 189 190 |
# File 'lib/doing/logger.rb', line 187 def abort_with(topic, = nil, &block) error(topic, , &block) abort end |
#adjust_verbosity(options = {}) ⇒ Object
100 101 102 103 104 105 106 107 108 109 110 |
# File 'lib/doing/logger.rb', line 100 def adjust_verbosity( = {}) if [:log_level] self.log_level = [:log_level].to_sym elsif [:quiet] self.log_level = :error elsif [:verbose] || [:debug] self.log_level = :debug end log_now :debug, 'Logging at level:', @level.to_s # log_now :debug, 'Doing Version:', Doing::VERSION end |
#benchmark(key, state) ⇒ Object
270 271 272 273 274 275 276 |
# File 'lib/doing/logger.rb', line 270 def benchmark(key, state) return unless ENV['DOING_BENCHMARK'] @benchmarks ||= {} @benchmarks[key] ||= { start: nil, finish: nil } @benchmarks[key][state] = Process.clock_gettime(Process::CLOCK_MONOTONIC) end |
#count(key, level: :info, count: 1, tag: nil, message: nil) ⇒ Object
112 113 114 115 116 117 118 119 |
# File 'lib/doing/logger.rb', line 112 def count(key, level: :info, count: 1, tag: nil, message: nil) raise ArgumentError, 'invalid counter key' unless COUNT_KEYS.include?(key) @counters[key][:count] += count @counters[key][:tag].concat(tag).sort.uniq unless tag.nil? @counters[key][:level] ||= level @counters[key][:message] ||= end |
#debug(topic, message = nil, &block) ⇒ Object
Print a debug message
129 130 131 |
# File 'lib/doing/logger.rb', line 129 def debug(topic, = nil, &block) write(:debug, topic, , &block) end |
#error(topic, message = nil, &block) ⇒ Object
Print an error message
171 172 173 |
# File 'lib/doing/logger.rb', line 171 def error(topic, = nil, &block) write(:error, topic, , &block) end |
#formatted_topic(topic, colon: false) ⇒ Object
Format the topic
202 203 204 205 206 207 208 209 210 |
# File 'lib/doing/logger.rb', line 202 def formatted_topic(topic, colon: false) if colon "#{topic}: ".rjust(TOPIC_WIDTH) elsif topic =~ /:$/ "#{topic} ".rjust(TOPIC_WIDTH) else "#{topic} " end end |
#info(topic, message = nil, &block) ⇒ Object
Print a message
143 144 145 |
# File 'lib/doing/logger.rb', line 143 def info(topic, = nil, &block) write(:info, topic, , &block) end |
#log_benchmarks ⇒ Object
278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 |
# File 'lib/doing/logger.rb', line 278 def log_benchmarks if ENV['DOING_BENCHMARK'] output = [] beginning = @benchmarks[:total][:start] ending = @benchmarks[:total][:finish] total = ending - beginning factor = TTY::Screen.columns / total cols = Array.new(TTY::Screen.columns) colors = %w[bgred bggreen bgyellow bgblue bgmagenta bgcyan bgwhite boldbgred boldbggreen boldbgyellow boldbgblue boldbgwhite] idx = 0 # @benchmarks.delete(:total) @benchmarks.sort_by { |_, timers| [timers[:start], timers[:finish]] }.each do |k, timers| if timers[:finish] && timers[:start] color = colors[idx % colors.count] fg = if idx < 7 Color.boldblack else Color.boldwhite end color = Color.send(color) + fg start = ((timers[:start] - beginning) * factor).floor finish = ((timers[:finish] - beginning) * factor).ceil cols.fill("#{color}-", start..finish) cols[start] = "#{color}|" cols[finish] = "#{color}|" output << "#{color}#{k}#{Color.default}: #{timers[:finish] - timers[:start]}" else output << "#{k}: error" end idx += 1 end output.each do |msg| $stdout.puts (:debug, 'Benchmark:', msg) end $stdout.puts (:debug, 'Benchmark:', "Total: #{total}") $stdout.puts cols[0..TTY::Screen.columns-1].join + Color.reset end end |
#log_change(tags_added: [], tags_removed: [], count: 1, item: nil, single: false) ⇒ Object
327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 |
# File 'lib/doing/logger.rb', line 327 def log_change(tags_added: [], tags_removed: [], count: 1, item: nil, single: false) if .empty? && .empty? count(:skipped, level: :debug, message: '%count %items with no change', count: count) else if .empty? count(:skipped, level: :debug, message: 'no tags added to %count %items') elsif single && item elapsed = if item && .include?('done') item.interval ? " (#{item.interval&.time_string(format: :dhm)})" : '' else '' end added = . info('Tagged:', %(added #{.count == 1 ? 'tag' : 'tags'} #{added}#{elapsed} to #{item.title})) else count(:added_tags, level: :info, tag: , message: '%tags added to %count %items') end if .empty? count(:skipped, level: :debug, message: 'no tags removed from %count %items') elsif single && item removed = . info('Untagged:', %(removed #{.count == 1 ? 'tag' : 'tags'} #{removed} from #{item.title})) else count(:removed_tags, level: :info, tag: , message: '%tags removed from %count %items') end end end |
#log_level=(level = 'info') ⇒ Object
Set the log level on the writer
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/doing/logger.rb', line 67 def log_level=(level = 'info') level = level.to_s level = case level when /^[e0]/i :error when /^[w1]/i :warn when /^[d3]/i :debug else :info end @level = level end |
#log_now(level, topic, message = nil, &block) ⇒ Object
Log to console immediately instead of writing messages on exit
241 242 243 244 245 246 247 248 249 |
# File 'lib/doing/logger.rb', line 241 def log_now(level, topic, = nil, &block) return false unless (level) if @logdev == $stdout @logdev.puts (topic, , &block) else @logdev.puts (level, topic, , &block) end end |
#output_results ⇒ Object
Output registers based on log level
256 257 258 259 260 261 262 263 264 265 266 267 268 |
# File 'lib/doing/logger.rb', line 256 def output_results total_counters results = @results.select { |msg| (msg[:level]) }.uniq if @logdev == $stdout $stdout.print results.map { |res| res[:message].uncolor }.join("\n") $stdout.puts else results.each do |msg| @logdev.puts (msg[:level], msg[:message]) end end end |
#restore_level ⇒ Object
Restore temporary level
93 94 95 96 97 98 |
# File 'lib/doing/logger.rb', line 93 def restore_level return if @prev_level.nil? || @prev_level == @log_level self.log_level = @prev_level @prev_level = nil end |
#temp_level(level) ⇒ Object
Set log level temporarily
85 86 87 88 89 90 |
# File 'lib/doing/logger.rb', line 85 def temp_level(level) return if level.nil? || level.to_sym == @log_level @prev_level = log_level.dup @log_level = level.to_sym end |
#warn(topic, message = nil, &block) ⇒ Object
Print a message
157 158 159 |
# File 'lib/doing/logger.rb', line 157 def warn(topic, = nil, &block) write(:warn, topic, , &block) end |
#write(level_of_message, topic, message = nil, &block) ⇒ Boolean
Log a message.
228 229 230 231 |
# File 'lib/doing/logger.rb', line 228 def write(, topic, = nil, &block) @results << { level: , message: (topic, , &block) } true end |