Class: Doing::LogAdapter

Inherits:
Object
  • Object
show all
Defined in:
lib/doing/log_adapter.rb

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

Instance Method Summary collapse

Constructor Details

#initialize(level = :info) ⇒ LogAdapter

Create a new instance of a log writer

Parameters:

  • level (optional, symbol) (defaults to: :info)

    the log level



49
50
51
52
53
54
55
56
57
58
# File 'lib/doing/log_adapter.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

#levelObject (readonly)

Returns the current log level (debug, info, warn, error)



15
16
17
# File 'lib/doing/log_adapter.rb', line 15

def level
  @level
end

#logdev=(value) ⇒ Object (writeonly)

Sets the log device



9
10
11
# File 'lib/doing/log_adapter.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/log_adapter.rb', line 12

def max_length=(value)
  @max_length = value
end

#messagesObject (readonly)

Returns the value of attribute messages.



17
18
19
# File 'lib/doing/log_adapter.rb', line 17

def messages
  @messages
end

#resultsObject (readonly)

Returns the value of attribute results.



17
18
19
# File 'lib/doing/log_adapter.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

Parameters:

  • topic

    the topic of the message, e.g. "Configuration file", "Deprecation", etc.

  • message (defaults to: nil)

    the message detail (can be omitted)

Returns:

  • nothing



187
188
189
190
# File 'lib/doing/log_adapter.rb', line 187

def abort_with(topic, message = nil, &block)
  error(topic, message, &block)
  abort
end

#adjust_verbosity(options = {}) ⇒ Object



100
101
102
103
104
105
106
107
108
109
110
# File 'lib/doing/log_adapter.rb', line 100

def adjust_verbosity(options = {})
  if options[:log_level]
    self.log_level = options[:log_level].to_sym
  elsif options[:quiet]
    self.log_level = :error
  elsif options[:verbose] || options[: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/log_adapter.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

Raises:

  • (ArgumentError)


112
113
114
115
116
117
118
119
# File 'lib/doing/log_adapter.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] ||= message
end

#debug(topic, message = nil, &block) ⇒ Object

Print a debug message

Parameters:

  • topic

    the topic of the message

  • message (defaults to: nil)

    the message detail

Returns:

  • nothing



129
130
131
# File 'lib/doing/log_adapter.rb', line 129

def debug(topic, message = nil, &block)
  write(:debug, topic, message, &block)
end

#error(topic, message = nil, &block) ⇒ Object

Print an error message

Parameters:

  • topic

    the topic of the message, e.g. "Configuration file", "Deprecation", etc.

  • message (defaults to: nil)

    the message detail

Returns:

  • nothing



171
172
173
# File 'lib/doing/log_adapter.rb', line 171

def error(topic, message = nil, &block)
  write(:error, topic, message, &block)
end

#formatted_topic(topic, colon: false) ⇒ Object

Format the topic

Parameters:

  • topic

    the topic of the message, e.g. "Configuration file", "Deprecation", etc.

  • colon (defaults to: false)

    Separate with a colon?

Returns:

  • the formatted topic statement



202
203
204
205
206
207
208
209
210
# File 'lib/doing/log_adapter.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

Parameters:

  • topic

    the topic of the message, e.g. "Configuration file", "Deprecation", etc.

  • message (defaults to: nil)

    the message detail

Returns:

  • nothing



143
144
145
# File 'lib/doing/log_adapter.rb', line 143

def info(topic, message = nil, &block)
  write(:info, topic, message, &block)
end

#log_benchmarksObject



278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
# File 'lib/doing/log_adapter.rb', line 278

def log_benchmarks
  if ENV['DOING_BENCHMARK']
    output = []
    @benchmarks.each do |k, timers|
      if timers[:finish] && timers[:start]
        output << "#{k}: #{timers[:finish] - timers[:start]}"
      else
        output << "#{k}: error"
      end
    end
    output.each do |msg|
      $stdout.puts color_message(:debug, 'Benchmark:', msg)
    end
  end
end

#log_change(tags_added: [], tags_removed: [], count: 1, item: nil, single: false) ⇒ Object



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
# File 'lib/doing/log_adapter.rb', line 295

def log_change(tags_added: [], tags_removed: [], count: 1, item: nil, single: false)
  if tags_added.empty? && tags_removed.empty?
    count(:skipped, level: :debug, message: '%count %items with no change', count: count)
  else
    if tags_added.empty?
      count(:skipped, level: :debug, message: 'no tags added to %count %items')
    elsif single && item
      added = tags_added.log_tags
      info('Tagged:',
           %(added #{tags_added.count == 1 ? 'tag' : 'tags'} #{added} to #{item.title}))
    else
      count(:added_tags, level: :info, tag: tags_added, message: '%tags added to %count %items')
    end

    if tags_removed.empty?
      count(:skipped, level: :debug, message: 'no tags removed from %count %items')
    elsif single && item
      added = tags_added.log_tags
      info('Untagged:',
           %(removed #{tags_removed.count == 1 ? 'tag' : 'tags'} #{added} from #{item.title}))
    else
      count(:removed_tags, level: :info, tag: tags_removed, message: '%tags removed from %count %items')
    end
  end
end

#log_level=(level = 'info') ⇒ Object

Set the log level on the writer

Parameters:

  • level (symbol) (defaults to: 'info')

    the log level

Returns:

  • nothing



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/doing/log_adapter.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

Parameters:

  • level (Symbol)

    The level

  • topic (String)

    The topic or full message

  • message (String) (defaults to: nil)

    The message (optional)

  • block

    a block containing the message (optional)



241
242
243
244
245
246
247
248
249
# File 'lib/doing/log_adapter.rb', line 241

def log_now(level, topic, message = nil, &block)
  return false unless write_message?(level)

  if @logdev == $stdout
    @logdev.puts message(topic, message, &block)
  else
    @logdev.puts color_message(level, topic, message, &block)
  end
end

#output_resultsObject

Output registers based on log level

Returns:

  • nothing



256
257
258
259
260
261
262
263
264
265
266
267
268
# File 'lib/doing/log_adapter.rb', line 256

def output_results
  total_counters
  results = @results.select { |msg| write_message?(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 color_message(msg[:level], msg[:message])
    end
  end
end

#restore_levelObject

Restore temporary level



93
94
95
96
97
98
# File 'lib/doing/log_adapter.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/log_adapter.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

Parameters:

  • topic

    the topic of the message, e.g. "Configuration file", "Deprecation", etc.

  • message (defaults to: nil)

    the message detail

Returns:

  • nothing



157
158
159
# File 'lib/doing/log_adapter.rb', line 157

def warn(topic, message = nil, &block)
  write(:warn, topic, message, &block)
end

#write(level_of_message, topic, message = nil, &block) ⇒ Boolean

Log a message.

Parameters:

  • level_of_message (Symbol)

    the Symbol level of message, one of :debug, :info, :warn, :error

  • topic (String)

    the String topic or full message

  • message (String) (defaults to: nil)

    the String message (optional)

  • block

    a block containing the message (optional)

Returns:

  • (Boolean)

    false if the message was not written



228
229
230
231
# File 'lib/doing/log_adapter.rb', line 228

def write(level_of_message, topic, message = nil, &block)
  @results << { level: level_of_message, message: message(topic, message, &block) }
  true
end