Class: Banana::Logger

Inherits:
Object
  • Object
show all
Defined in:
lib/banana/logger.rb

Overview

This class provides a simple logger which maintains and displays the runtime of the logger instance. It is intended to be used with the colorize gem but it brings its own colorization to eliminate a dependency. You should initialize the logger as soon as possible to get an accurate runtime.

Examples:

logger = Banana::Logger.new
logger.log "foo"
logger.prefix = "[a] "
logger.debug "bar"
sleep 2
logger.ensure_prefix("[b] ") { logger.warn "baz" }
logger.log("rab!", :abort)

# Result:
# [00:00:00.000 INFO]     foo
# [00:00:00.000 DEBUG]    [a] bar
# [00:00:02.001 WARN]     [b] baz
# [00:00:02.001 ABORT]    [a] rab!

Constant Summary collapse

COLORMAP =

Foreground color values

{
  black: 30,
  red: 31,
  green: 32,
  yellow: 33,
  blue: 34,
  magenta: 35,
  cyan: 36,
  white: 37,
}

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(scope = nil) ⇒ Logger

TODO:

add option hash

Initializes a new logger instance. The internal runtime measurement starts here!

There are 4 default log levels: info (yellow), warn & abort (red) and debug (blue). All are enabled by default. You propably want to disable(:debug).



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/banana/logger.rb', line 60

def initialize scope = nil
  @startup = Time.now.utc
  @colorize = true
  @prefix = ""
  @enabled = true
  @timestr = true
  @channel = ::Kernel
  @method = :puts
  @logged = 0
  @levels = {
    info: { color: "yellow", enabled: true },
    warn: { color: "red", enabled: true },
    abort: { color: "red", enabled: true },
    debug: { color: "blue", enabled: true },
  }
end

Instance Attribute Details

#channelObject (readonly)



37
38
39
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
69
70
71
72
73
74
75
76
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
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
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
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
255
256
257
# File 'lib/banana/logger.rb', line 37

class Logger
  attr_reader :startup, :channel, :method, :logged
  attr_accessor :colorize, :prefix

  # Foreground color values
  COLORMAP = {
    black: 30,
    red: 31,
    green: 32,
    yellow: 33,
    blue: 34,
    magenta: 35,
    cyan: 36,
    white: 37,
  }

  # Initializes a new logger instance. The internal runtime measurement starts here!
  #
  # There are 4 default log levels: info (yellow), warn & abort (red) and debug (blue).
  # All are enabled by default. You propably want to {#disable disable(:debug)}.
  #
  # @param scope Only for backward compatibility, not used
  # @todo add option hash
  def initialize scope = nil
    @startup = Time.now.utc
    @colorize = true
    @prefix = ""
    @enabled = true
    @timestr = true
    @channel = ::Kernel
    @method = :puts
    @logged = 0
    @levels = {
      info: { color: "yellow", enabled: true },
      warn: { color: "red", enabled: true },
      abort: { color: "red", enabled: true },
      debug: { color: "blue", enabled: true },
    }
  end

  # The default channel is `Kernel` which is Ruby's normal `puts`.
  # Attach it to a open file with write access and it will write into
  # the file. Ensure to close the file in your code.
  #
  # @param channel Object which responds to puts and print
  def attach channel
    @channel = channel
  end

  # Print raw message onto {#channel} using {#method}.
  #
  # @param [String] msg Message to send to {#channel}.
  # @param [Symbol] method Override {#method}.
  def raw msg, method = @method
    @channel.send(method, msg)
  end

  # Add additional log levels which are automatically enabled.
  # @param [Hash] levels Log levels in the format `{ debug: "red" }`
  def log_level levels = {}
    levels.each do |level, color|
      @levels[level.to_sym] ||= { enabled: true }
      @levels[level.to_sym][:color] = color
    end
  end

  # Calls the block with the given prefix and ensures that the prefix
  # will be the same as before.
  #
  # @param [String] prefix Prefix to use for the block
  # @param [Proc] block Block to call
  def ensure_prefix prefix, &block
    old_prefix, @prefix = @prefix, prefix
    block.call
  ensure
    @prefix = old_prefix
  end

  # Calls the block after changing the output method.
  # It also ensures to set back the method to what it was before.
  #
  # @param [Symbol] method Method to call on {#channel}
  def ensure_method method, &block
    old_method, old_logged = @method, @logged
    @method, @logged = method, 0
    block.call
  ensure
    @method = old_method
    @logged += old_logged
  end

  # Calls the block after changing the output method to `:print`.
  # It also ensures to set back the method to what it was before.
  #
  # @param [Boolean] clear If set to true and any message was printed inside the block
  #   a \n newline character will be printed.
  def log_with_print clear = true, &block
    ensure_method :print do
      begin
        block.call
      ensure
        puts if clear && @logged > 0
      end
    end
  end

  # Calls the block after disabling the runtime indicator.
  # It also ensures to set back the old setting after execution.
  def log_without_timestr &block
    timestr, @timestr = @timestr, false
    block.call
  ensure
    @timestr = timestr
  end

  # @return [Boolean] returns true if the log level format :debug is enabled.
  def debug?
    enabled? :debug
  end

  # If a `level` is provided it will return true if this log level is enabled.
  # If no `level` is provided it will return true if the logger is enabled generally.
  #
  # @return [Boolean] returns true if the given log level is enabled
  def enabled? level = nil
    level.nil? ? @enabled : @levels[level.to_sym][:enabled]
  end

  # Same as {#enabled?} just negated.
  def disabled? level = nil
    !enabled?(level)
  end

  # Same as {#enable} just negated.
  #
  # @param [Symbol, String] level Loglevel to disable.
  def disable level = nil
    if level.nil?
      @enabled = false
    else
      @levels[level.to_sym][:enabled] = false
    end
  end

  # Enables the given `level` or the logger generally if no `level` is given.
  # If the logger is disabled no messages will be printed. If it is enabled
  # only messages for enabled log levels will be printed.
  #
  # @param [Symbol, String] level Loglevel to enable.
  def enable level = nil
    if level.nil?
      @enabled = true
    else
      @levels[level.to_sym][:enabled] = true
    end
  end

  # Colorizes the given string with the given color. It uses the build-in
  # colorization feature. You may want to use the colorize gem.
  #
  # @param [String] str The string to colorize
  # @param [Symbol, String] color The color to use (see {COLORMAP})
  # @raise [ArgumentError] if color does not exist in {COLORMAP}.
  def colorize str, color
    ccode = COLORMAP[color.to_sym] || raise(ArgumentError, "Unknown color #{color}!")
    "\e[#{ccode}m#{str}\e[0m"
  end

  def colorize?
    @colorize
  end

  # This method is the only method which sends the message `msg` to `@channel` via `@method`.
  # It also increments the message counter `@logged` by one.
  #
  # This method instantly returns nil if the logger or the given log level `type` is disabled.
  #
  # @param [String] msg The message to send to the channel
  # @param [Symbol] type The log level
  def log msg, type = :info
    return if !@enabled || !@levels[type][:enabled]
    if @levels[type.to_sym] || !@levels.key?(type.to_sym)
      time = Time.at(Time.now.utc - @startup).utc
      timestr = @timestr ? "[#{time.strftime("%H:%M:%S.%L")} #{type.to_s.upcase}]\t" : ""

      if @colorize
        msg = "#{colorize(timestr, @levels[type.to_sym][:color])}" <<
              "#{@prefix}" <<
              "#{colorize(msg, @levels[type.to_sym][:color])}"
      else
        msg = "#{timestr}#{@prefix}#{msg}"
      end
      @logged += 1
      @channel.send(@method, msg)
    end
  end
  alias_method :info, :log

  # Shortcut for {#log #log(msg, :debug)}
  #
  # @param [String] msg The message to send to {#log}.
  def debug msg
    log(msg, :debug)
  end

  # Shortcut for {#log #log(msg, :warn)} but sets channel method to "warn".
  #
  # @param [String] msg The message to send to {#log}.
  def warn msg
    ensure_method(:warn) { log(msg, :warn) }
  end

  # Shortcut for {#log #log(msg, :abort)} but sets channel method to "warn".
  #
  # @param [String] msg The message to send to {#log}.
  # @param [Integer] exit_code Exits with given code or does nothing when falsy.
  def abort msg, exit_code = false
    ensure_method(:warn) { log(msg, :abort) }
    exit(exit_code) if exit_code
  end
end

#colorize(str, color) ⇒ Object

Colorizes the given string with the given color. It uses the build-in colorization feature. You may want to use the colorize gem.

Raises:

  • (ArgumentError)

    if color does not exist in COLORMAP.



37
38
39
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
69
70
71
72
73
74
75
76
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
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
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
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
255
256
257
# File 'lib/banana/logger.rb', line 37

class Logger
  attr_reader :startup, :channel, :method, :logged
  attr_accessor :colorize, :prefix

  # Foreground color values
  COLORMAP = {
    black: 30,
    red: 31,
    green: 32,
    yellow: 33,
    blue: 34,
    magenta: 35,
    cyan: 36,
    white: 37,
  }

  # Initializes a new logger instance. The internal runtime measurement starts here!
  #
  # There are 4 default log levels: info (yellow), warn & abort (red) and debug (blue).
  # All are enabled by default. You propably want to {#disable disable(:debug)}.
  #
  # @param scope Only for backward compatibility, not used
  # @todo add option hash
  def initialize scope = nil
    @startup = Time.now.utc
    @colorize = true
    @prefix = ""
    @enabled = true
    @timestr = true
    @channel = ::Kernel
    @method = :puts
    @logged = 0
    @levels = {
      info: { color: "yellow", enabled: true },
      warn: { color: "red", enabled: true },
      abort: { color: "red", enabled: true },
      debug: { color: "blue", enabled: true },
    }
  end

  # The default channel is `Kernel` which is Ruby's normal `puts`.
  # Attach it to a open file with write access and it will write into
  # the file. Ensure to close the file in your code.
  #
  # @param channel Object which responds to puts and print
  def attach channel
    @channel = channel
  end

  # Print raw message onto {#channel} using {#method}.
  #
  # @param [String] msg Message to send to {#channel}.
  # @param [Symbol] method Override {#method}.
  def raw msg, method = @method
    @channel.send(method, msg)
  end

  # Add additional log levels which are automatically enabled.
  # @param [Hash] levels Log levels in the format `{ debug: "red" }`
  def log_level levels = {}
    levels.each do |level, color|
      @levels[level.to_sym] ||= { enabled: true }
      @levels[level.to_sym][:color] = color
    end
  end

  # Calls the block with the given prefix and ensures that the prefix
  # will be the same as before.
  #
  # @param [String] prefix Prefix to use for the block
  # @param [Proc] block Block to call
  def ensure_prefix prefix, &block
    old_prefix, @prefix = @prefix, prefix
    block.call
  ensure
    @prefix = old_prefix
  end

  # Calls the block after changing the output method.
  # It also ensures to set back the method to what it was before.
  #
  # @param [Symbol] method Method to call on {#channel}
  def ensure_method method, &block
    old_method, old_logged = @method, @logged
    @method, @logged = method, 0
    block.call
  ensure
    @method = old_method
    @logged += old_logged
  end

  # Calls the block after changing the output method to `:print`.
  # It also ensures to set back the method to what it was before.
  #
  # @param [Boolean] clear If set to true and any message was printed inside the block
  #   a \n newline character will be printed.
  def log_with_print clear = true, &block
    ensure_method :print do
      begin
        block.call
      ensure
        puts if clear && @logged > 0
      end
    end
  end

  # Calls the block after disabling the runtime indicator.
  # It also ensures to set back the old setting after execution.
  def log_without_timestr &block
    timestr, @timestr = @timestr, false
    block.call
  ensure
    @timestr = timestr
  end

  # @return [Boolean] returns true if the log level format :debug is enabled.
  def debug?
    enabled? :debug
  end

  # If a `level` is provided it will return true if this log level is enabled.
  # If no `level` is provided it will return true if the logger is enabled generally.
  #
  # @return [Boolean] returns true if the given log level is enabled
  def enabled? level = nil
    level.nil? ? @enabled : @levels[level.to_sym][:enabled]
  end

  # Same as {#enabled?} just negated.
  def disabled? level = nil
    !enabled?(level)
  end

  # Same as {#enable} just negated.
  #
  # @param [Symbol, String] level Loglevel to disable.
  def disable level = nil
    if level.nil?
      @enabled = false
    else
      @levels[level.to_sym][:enabled] = false
    end
  end

  # Enables the given `level` or the logger generally if no `level` is given.
  # If the logger is disabled no messages will be printed. If it is enabled
  # only messages for enabled log levels will be printed.
  #
  # @param [Symbol, String] level Loglevel to enable.
  def enable level = nil
    if level.nil?
      @enabled = true
    else
      @levels[level.to_sym][:enabled] = true
    end
  end

  # Colorizes the given string with the given color. It uses the build-in
  # colorization feature. You may want to use the colorize gem.
  #
  # @param [String] str The string to colorize
  # @param [Symbol, String] color The color to use (see {COLORMAP})
  # @raise [ArgumentError] if color does not exist in {COLORMAP}.
  def colorize str, color
    ccode = COLORMAP[color.to_sym] || raise(ArgumentError, "Unknown color #{color}!")
    "\e[#{ccode}m#{str}\e[0m"
  end

  def colorize?
    @colorize
  end

  # This method is the only method which sends the message `msg` to `@channel` via `@method`.
  # It also increments the message counter `@logged` by one.
  #
  # This method instantly returns nil if the logger or the given log level `type` is disabled.
  #
  # @param [String] msg The message to send to the channel
  # @param [Symbol] type The log level
  def log msg, type = :info
    return if !@enabled || !@levels[type][:enabled]
    if @levels[type.to_sym] || !@levels.key?(type.to_sym)
      time = Time.at(Time.now.utc - @startup).utc
      timestr = @timestr ? "[#{time.strftime("%H:%M:%S.%L")} #{type.to_s.upcase}]\t" : ""

      if @colorize
        msg = "#{colorize(timestr, @levels[type.to_sym][:color])}" <<
              "#{@prefix}" <<
              "#{colorize(msg, @levels[type.to_sym][:color])}"
      else
        msg = "#{timestr}#{@prefix}#{msg}"
      end
      @logged += 1
      @channel.send(@method, msg)
    end
  end
  alias_method :info, :log

  # Shortcut for {#log #log(msg, :debug)}
  #
  # @param [String] msg The message to send to {#log}.
  def debug msg
    log(msg, :debug)
  end

  # Shortcut for {#log #log(msg, :warn)} but sets channel method to "warn".
  #
  # @param [String] msg The message to send to {#log}.
  def warn msg
    ensure_method(:warn) { log(msg, :warn) }
  end

  # Shortcut for {#log #log(msg, :abort)} but sets channel method to "warn".
  #
  # @param [String] msg The message to send to {#log}.
  # @param [Integer] exit_code Exits with given code or does nothing when falsy.
  def abort msg, exit_code = false
    ensure_method(:warn) { log(msg, :abort) }
    exit(exit_code) if exit_code
  end
end

#loggedInteger (readonly)

Note:

This counter starts from 0 in every #ensure_method or #log_with_print block but gets added to the main counter after the call.

Returns Amount of messages send to channel.



37
38
39
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
69
70
71
72
73
74
75
76
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
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
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
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
255
256
257
# File 'lib/banana/logger.rb', line 37

class Logger
  attr_reader :startup, :channel, :method, :logged
  attr_accessor :colorize, :prefix

  # Foreground color values
  COLORMAP = {
    black: 30,
    red: 31,
    green: 32,
    yellow: 33,
    blue: 34,
    magenta: 35,
    cyan: 36,
    white: 37,
  }

  # Initializes a new logger instance. The internal runtime measurement starts here!
  #
  # There are 4 default log levels: info (yellow), warn & abort (red) and debug (blue).
  # All are enabled by default. You propably want to {#disable disable(:debug)}.
  #
  # @param scope Only for backward compatibility, not used
  # @todo add option hash
  def initialize scope = nil
    @startup = Time.now.utc
    @colorize = true
    @prefix = ""
    @enabled = true
    @timestr = true
    @channel = ::Kernel
    @method = :puts
    @logged = 0
    @levels = {
      info: { color: "yellow", enabled: true },
      warn: { color: "red", enabled: true },
      abort: { color: "red", enabled: true },
      debug: { color: "blue", enabled: true },
    }
  end

  # The default channel is `Kernel` which is Ruby's normal `puts`.
  # Attach it to a open file with write access and it will write into
  # the file. Ensure to close the file in your code.
  #
  # @param channel Object which responds to puts and print
  def attach channel
    @channel = channel
  end

  # Print raw message onto {#channel} using {#method}.
  #
  # @param [String] msg Message to send to {#channel}.
  # @param [Symbol] method Override {#method}.
  def raw msg, method = @method
    @channel.send(method, msg)
  end

  # Add additional log levels which are automatically enabled.
  # @param [Hash] levels Log levels in the format `{ debug: "red" }`
  def log_level levels = {}
    levels.each do |level, color|
      @levels[level.to_sym] ||= { enabled: true }
      @levels[level.to_sym][:color] = color
    end
  end

  # Calls the block with the given prefix and ensures that the prefix
  # will be the same as before.
  #
  # @param [String] prefix Prefix to use for the block
  # @param [Proc] block Block to call
  def ensure_prefix prefix, &block
    old_prefix, @prefix = @prefix, prefix
    block.call
  ensure
    @prefix = old_prefix
  end

  # Calls the block after changing the output method.
  # It also ensures to set back the method to what it was before.
  #
  # @param [Symbol] method Method to call on {#channel}
  def ensure_method method, &block
    old_method, old_logged = @method, @logged
    @method, @logged = method, 0
    block.call
  ensure
    @method = old_method
    @logged += old_logged
  end

  # Calls the block after changing the output method to `:print`.
  # It also ensures to set back the method to what it was before.
  #
  # @param [Boolean] clear If set to true and any message was printed inside the block
  #   a \n newline character will be printed.
  def log_with_print clear = true, &block
    ensure_method :print do
      begin
        block.call
      ensure
        puts if clear && @logged > 0
      end
    end
  end

  # Calls the block after disabling the runtime indicator.
  # It also ensures to set back the old setting after execution.
  def log_without_timestr &block
    timestr, @timestr = @timestr, false
    block.call
  ensure
    @timestr = timestr
  end

  # @return [Boolean] returns true if the log level format :debug is enabled.
  def debug?
    enabled? :debug
  end

  # If a `level` is provided it will return true if this log level is enabled.
  # If no `level` is provided it will return true if the logger is enabled generally.
  #
  # @return [Boolean] returns true if the given log level is enabled
  def enabled? level = nil
    level.nil? ? @enabled : @levels[level.to_sym][:enabled]
  end

  # Same as {#enabled?} just negated.
  def disabled? level = nil
    !enabled?(level)
  end

  # Same as {#enable} just negated.
  #
  # @param [Symbol, String] level Loglevel to disable.
  def disable level = nil
    if level.nil?
      @enabled = false
    else
      @levels[level.to_sym][:enabled] = false
    end
  end

  # Enables the given `level` or the logger generally if no `level` is given.
  # If the logger is disabled no messages will be printed. If it is enabled
  # only messages for enabled log levels will be printed.
  #
  # @param [Symbol, String] level Loglevel to enable.
  def enable level = nil
    if level.nil?
      @enabled = true
    else
      @levels[level.to_sym][:enabled] = true
    end
  end

  # Colorizes the given string with the given color. It uses the build-in
  # colorization feature. You may want to use the colorize gem.
  #
  # @param [String] str The string to colorize
  # @param [Symbol, String] color The color to use (see {COLORMAP})
  # @raise [ArgumentError] if color does not exist in {COLORMAP}.
  def colorize str, color
    ccode = COLORMAP[color.to_sym] || raise(ArgumentError, "Unknown color #{color}!")
    "\e[#{ccode}m#{str}\e[0m"
  end

  def colorize?
    @colorize
  end

  # This method is the only method which sends the message `msg` to `@channel` via `@method`.
  # It also increments the message counter `@logged` by one.
  #
  # This method instantly returns nil if the logger or the given log level `type` is disabled.
  #
  # @param [String] msg The message to send to the channel
  # @param [Symbol] type The log level
  def log msg, type = :info
    return if !@enabled || !@levels[type][:enabled]
    if @levels[type.to_sym] || !@levels.key?(type.to_sym)
      time = Time.at(Time.now.utc - @startup).utc
      timestr = @timestr ? "[#{time.strftime("%H:%M:%S.%L")} #{type.to_s.upcase}]\t" : ""

      if @colorize
        msg = "#{colorize(timestr, @levels[type.to_sym][:color])}" <<
              "#{@prefix}" <<
              "#{colorize(msg, @levels[type.to_sym][:color])}"
      else
        msg = "#{timestr}#{@prefix}#{msg}"
      end
      @logged += 1
      @channel.send(@method, msg)
    end
  end
  alias_method :info, :log

  # Shortcut for {#log #log(msg, :debug)}
  #
  # @param [String] msg The message to send to {#log}.
  def debug msg
    log(msg, :debug)
  end

  # Shortcut for {#log #log(msg, :warn)} but sets channel method to "warn".
  #
  # @param [String] msg The message to send to {#log}.
  def warn msg
    ensure_method(:warn) { log(msg, :warn) }
  end

  # Shortcut for {#log #log(msg, :abort)} but sets channel method to "warn".
  #
  # @param [String] msg The message to send to {#log}.
  # @param [Integer] exit_code Exits with given code or does nothing when falsy.
  def abort msg, exit_code = false
    ensure_method(:warn) { log(msg, :abort) }
    exit(exit_code) if exit_code
  end
end

#methodObject (readonly)



37
38
39
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
69
70
71
72
73
74
75
76
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
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
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
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
255
256
257
# File 'lib/banana/logger.rb', line 37

class Logger
  attr_reader :startup, :channel, :method, :logged
  attr_accessor :colorize, :prefix

  # Foreground color values
  COLORMAP = {
    black: 30,
    red: 31,
    green: 32,
    yellow: 33,
    blue: 34,
    magenta: 35,
    cyan: 36,
    white: 37,
  }

  # Initializes a new logger instance. The internal runtime measurement starts here!
  #
  # There are 4 default log levels: info (yellow), warn & abort (red) and debug (blue).
  # All are enabled by default. You propably want to {#disable disable(:debug)}.
  #
  # @param scope Only for backward compatibility, not used
  # @todo add option hash
  def initialize scope = nil
    @startup = Time.now.utc
    @colorize = true
    @prefix = ""
    @enabled = true
    @timestr = true
    @channel = ::Kernel
    @method = :puts
    @logged = 0
    @levels = {
      info: { color: "yellow", enabled: true },
      warn: { color: "red", enabled: true },
      abort: { color: "red", enabled: true },
      debug: { color: "blue", enabled: true },
    }
  end

  # The default channel is `Kernel` which is Ruby's normal `puts`.
  # Attach it to a open file with write access and it will write into
  # the file. Ensure to close the file in your code.
  #
  # @param channel Object which responds to puts and print
  def attach channel
    @channel = channel
  end

  # Print raw message onto {#channel} using {#method}.
  #
  # @param [String] msg Message to send to {#channel}.
  # @param [Symbol] method Override {#method}.
  def raw msg, method = @method
    @channel.send(method, msg)
  end

  # Add additional log levels which are automatically enabled.
  # @param [Hash] levels Log levels in the format `{ debug: "red" }`
  def log_level levels = {}
    levels.each do |level, color|
      @levels[level.to_sym] ||= { enabled: true }
      @levels[level.to_sym][:color] = color
    end
  end

  # Calls the block with the given prefix and ensures that the prefix
  # will be the same as before.
  #
  # @param [String] prefix Prefix to use for the block
  # @param [Proc] block Block to call
  def ensure_prefix prefix, &block
    old_prefix, @prefix = @prefix, prefix
    block.call
  ensure
    @prefix = old_prefix
  end

  # Calls the block after changing the output method.
  # It also ensures to set back the method to what it was before.
  #
  # @param [Symbol] method Method to call on {#channel}
  def ensure_method method, &block
    old_method, old_logged = @method, @logged
    @method, @logged = method, 0
    block.call
  ensure
    @method = old_method
    @logged += old_logged
  end

  # Calls the block after changing the output method to `:print`.
  # It also ensures to set back the method to what it was before.
  #
  # @param [Boolean] clear If set to true and any message was printed inside the block
  #   a \n newline character will be printed.
  def log_with_print clear = true, &block
    ensure_method :print do
      begin
        block.call
      ensure
        puts if clear && @logged > 0
      end
    end
  end

  # Calls the block after disabling the runtime indicator.
  # It also ensures to set back the old setting after execution.
  def log_without_timestr &block
    timestr, @timestr = @timestr, false
    block.call
  ensure
    @timestr = timestr
  end

  # @return [Boolean] returns true if the log level format :debug is enabled.
  def debug?
    enabled? :debug
  end

  # If a `level` is provided it will return true if this log level is enabled.
  # If no `level` is provided it will return true if the logger is enabled generally.
  #
  # @return [Boolean] returns true if the given log level is enabled
  def enabled? level = nil
    level.nil? ? @enabled : @levels[level.to_sym][:enabled]
  end

  # Same as {#enabled?} just negated.
  def disabled? level = nil
    !enabled?(level)
  end

  # Same as {#enable} just negated.
  #
  # @param [Symbol, String] level Loglevel to disable.
  def disable level = nil
    if level.nil?
      @enabled = false
    else
      @levels[level.to_sym][:enabled] = false
    end
  end

  # Enables the given `level` or the logger generally if no `level` is given.
  # If the logger is disabled no messages will be printed. If it is enabled
  # only messages for enabled log levels will be printed.
  #
  # @param [Symbol, String] level Loglevel to enable.
  def enable level = nil
    if level.nil?
      @enabled = true
    else
      @levels[level.to_sym][:enabled] = true
    end
  end

  # Colorizes the given string with the given color. It uses the build-in
  # colorization feature. You may want to use the colorize gem.
  #
  # @param [String] str The string to colorize
  # @param [Symbol, String] color The color to use (see {COLORMAP})
  # @raise [ArgumentError] if color does not exist in {COLORMAP}.
  def colorize str, color
    ccode = COLORMAP[color.to_sym] || raise(ArgumentError, "Unknown color #{color}!")
    "\e[#{ccode}m#{str}\e[0m"
  end

  def colorize?
    @colorize
  end

  # This method is the only method which sends the message `msg` to `@channel` via `@method`.
  # It also increments the message counter `@logged` by one.
  #
  # This method instantly returns nil if the logger or the given log level `type` is disabled.
  #
  # @param [String] msg The message to send to the channel
  # @param [Symbol] type The log level
  def log msg, type = :info
    return if !@enabled || !@levels[type][:enabled]
    if @levels[type.to_sym] || !@levels.key?(type.to_sym)
      time = Time.at(Time.now.utc - @startup).utc
      timestr = @timestr ? "[#{time.strftime("%H:%M:%S.%L")} #{type.to_s.upcase}]\t" : ""

      if @colorize
        msg = "#{colorize(timestr, @levels[type.to_sym][:color])}" <<
              "#{@prefix}" <<
              "#{colorize(msg, @levels[type.to_sym][:color])}"
      else
        msg = "#{timestr}#{@prefix}#{msg}"
      end
      @logged += 1
      @channel.send(@method, msg)
    end
  end
  alias_method :info, :log

  # Shortcut for {#log #log(msg, :debug)}
  #
  # @param [String] msg The message to send to {#log}.
  def debug msg
    log(msg, :debug)
  end

  # Shortcut for {#log #log(msg, :warn)} but sets channel method to "warn".
  #
  # @param [String] msg The message to send to {#log}.
  def warn msg
    ensure_method(:warn) { log(msg, :warn) }
  end

  # Shortcut for {#log #log(msg, :abort)} but sets channel method to "warn".
  #
  # @param [String] msg The message to send to {#log}.
  # @param [Integer] exit_code Exits with given code or does nothing when falsy.
  def abort msg, exit_code = false
    ensure_method(:warn) { log(msg, :abort) }
    exit(exit_code) if exit_code
  end
end

#prefixString



37
38
39
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
69
70
71
72
73
74
75
76
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
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
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
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
255
256
257
# File 'lib/banana/logger.rb', line 37

class Logger
  attr_reader :startup, :channel, :method, :logged
  attr_accessor :colorize, :prefix

  # Foreground color values
  COLORMAP = {
    black: 30,
    red: 31,
    green: 32,
    yellow: 33,
    blue: 34,
    magenta: 35,
    cyan: 36,
    white: 37,
  }

  # Initializes a new logger instance. The internal runtime measurement starts here!
  #
  # There are 4 default log levels: info (yellow), warn & abort (red) and debug (blue).
  # All are enabled by default. You propably want to {#disable disable(:debug)}.
  #
  # @param scope Only for backward compatibility, not used
  # @todo add option hash
  def initialize scope = nil
    @startup = Time.now.utc
    @colorize = true
    @prefix = ""
    @enabled = true
    @timestr = true
    @channel = ::Kernel
    @method = :puts
    @logged = 0
    @levels = {
      info: { color: "yellow", enabled: true },
      warn: { color: "red", enabled: true },
      abort: { color: "red", enabled: true },
      debug: { color: "blue", enabled: true },
    }
  end

  # The default channel is `Kernel` which is Ruby's normal `puts`.
  # Attach it to a open file with write access and it will write into
  # the file. Ensure to close the file in your code.
  #
  # @param channel Object which responds to puts and print
  def attach channel
    @channel = channel
  end

  # Print raw message onto {#channel} using {#method}.
  #
  # @param [String] msg Message to send to {#channel}.
  # @param [Symbol] method Override {#method}.
  def raw msg, method = @method
    @channel.send(method, msg)
  end

  # Add additional log levels which are automatically enabled.
  # @param [Hash] levels Log levels in the format `{ debug: "red" }`
  def log_level levels = {}
    levels.each do |level, color|
      @levels[level.to_sym] ||= { enabled: true }
      @levels[level.to_sym][:color] = color
    end
  end

  # Calls the block with the given prefix and ensures that the prefix
  # will be the same as before.
  #
  # @param [String] prefix Prefix to use for the block
  # @param [Proc] block Block to call
  def ensure_prefix prefix, &block
    old_prefix, @prefix = @prefix, prefix
    block.call
  ensure
    @prefix = old_prefix
  end

  # Calls the block after changing the output method.
  # It also ensures to set back the method to what it was before.
  #
  # @param [Symbol] method Method to call on {#channel}
  def ensure_method method, &block
    old_method, old_logged = @method, @logged
    @method, @logged = method, 0
    block.call
  ensure
    @method = old_method
    @logged += old_logged
  end

  # Calls the block after changing the output method to `:print`.
  # It also ensures to set back the method to what it was before.
  #
  # @param [Boolean] clear If set to true and any message was printed inside the block
  #   a \n newline character will be printed.
  def log_with_print clear = true, &block
    ensure_method :print do
      begin
        block.call
      ensure
        puts if clear && @logged > 0
      end
    end
  end

  # Calls the block after disabling the runtime indicator.
  # It also ensures to set back the old setting after execution.
  def log_without_timestr &block
    timestr, @timestr = @timestr, false
    block.call
  ensure
    @timestr = timestr
  end

  # @return [Boolean] returns true if the log level format :debug is enabled.
  def debug?
    enabled? :debug
  end

  # If a `level` is provided it will return true if this log level is enabled.
  # If no `level` is provided it will return true if the logger is enabled generally.
  #
  # @return [Boolean] returns true if the given log level is enabled
  def enabled? level = nil
    level.nil? ? @enabled : @levels[level.to_sym][:enabled]
  end

  # Same as {#enabled?} just negated.
  def disabled? level = nil
    !enabled?(level)
  end

  # Same as {#enable} just negated.
  #
  # @param [Symbol, String] level Loglevel to disable.
  def disable level = nil
    if level.nil?
      @enabled = false
    else
      @levels[level.to_sym][:enabled] = false
    end
  end

  # Enables the given `level` or the logger generally if no `level` is given.
  # If the logger is disabled no messages will be printed. If it is enabled
  # only messages for enabled log levels will be printed.
  #
  # @param [Symbol, String] level Loglevel to enable.
  def enable level = nil
    if level.nil?
      @enabled = true
    else
      @levels[level.to_sym][:enabled] = true
    end
  end

  # Colorizes the given string with the given color. It uses the build-in
  # colorization feature. You may want to use the colorize gem.
  #
  # @param [String] str The string to colorize
  # @param [Symbol, String] color The color to use (see {COLORMAP})
  # @raise [ArgumentError] if color does not exist in {COLORMAP}.
  def colorize str, color
    ccode = COLORMAP[color.to_sym] || raise(ArgumentError, "Unknown color #{color}!")
    "\e[#{ccode}m#{str}\e[0m"
  end

  def colorize?
    @colorize
  end

  # This method is the only method which sends the message `msg` to `@channel` via `@method`.
  # It also increments the message counter `@logged` by one.
  #
  # This method instantly returns nil if the logger or the given log level `type` is disabled.
  #
  # @param [String] msg The message to send to the channel
  # @param [Symbol] type The log level
  def log msg, type = :info
    return if !@enabled || !@levels[type][:enabled]
    if @levels[type.to_sym] || !@levels.key?(type.to_sym)
      time = Time.at(Time.now.utc - @startup).utc
      timestr = @timestr ? "[#{time.strftime("%H:%M:%S.%L")} #{type.to_s.upcase}]\t" : ""

      if @colorize
        msg = "#{colorize(timestr, @levels[type.to_sym][:color])}" <<
              "#{@prefix}" <<
              "#{colorize(msg, @levels[type.to_sym][:color])}"
      else
        msg = "#{timestr}#{@prefix}#{msg}"
      end
      @logged += 1
      @channel.send(@method, msg)
    end
  end
  alias_method :info, :log

  # Shortcut for {#log #log(msg, :debug)}
  #
  # @param [String] msg The message to send to {#log}.
  def debug msg
    log(msg, :debug)
  end

  # Shortcut for {#log #log(msg, :warn)} but sets channel method to "warn".
  #
  # @param [String] msg The message to send to {#log}.
  def warn msg
    ensure_method(:warn) { log(msg, :warn) }
  end

  # Shortcut for {#log #log(msg, :abort)} but sets channel method to "warn".
  #
  # @param [String] msg The message to send to {#log}.
  # @param [Integer] exit_code Exits with given code or does nothing when falsy.
  def abort msg, exit_code = false
    ensure_method(:warn) { log(msg, :abort) }
    exit(exit_code) if exit_code
  end
end

#startupDateTime (readonly)



37
38
39
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
69
70
71
72
73
74
75
76
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
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
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
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
255
256
257
# File 'lib/banana/logger.rb', line 37

class Logger
  attr_reader :startup, :channel, :method, :logged
  attr_accessor :colorize, :prefix

  # Foreground color values
  COLORMAP = {
    black: 30,
    red: 31,
    green: 32,
    yellow: 33,
    blue: 34,
    magenta: 35,
    cyan: 36,
    white: 37,
  }

  # Initializes a new logger instance. The internal runtime measurement starts here!
  #
  # There are 4 default log levels: info (yellow), warn & abort (red) and debug (blue).
  # All are enabled by default. You propably want to {#disable disable(:debug)}.
  #
  # @param scope Only for backward compatibility, not used
  # @todo add option hash
  def initialize scope = nil
    @startup = Time.now.utc
    @colorize = true
    @prefix = ""
    @enabled = true
    @timestr = true
    @channel = ::Kernel
    @method = :puts
    @logged = 0
    @levels = {
      info: { color: "yellow", enabled: true },
      warn: { color: "red", enabled: true },
      abort: { color: "red", enabled: true },
      debug: { color: "blue", enabled: true },
    }
  end

  # The default channel is `Kernel` which is Ruby's normal `puts`.
  # Attach it to a open file with write access and it will write into
  # the file. Ensure to close the file in your code.
  #
  # @param channel Object which responds to puts and print
  def attach channel
    @channel = channel
  end

  # Print raw message onto {#channel} using {#method}.
  #
  # @param [String] msg Message to send to {#channel}.
  # @param [Symbol] method Override {#method}.
  def raw msg, method = @method
    @channel.send(method, msg)
  end

  # Add additional log levels which are automatically enabled.
  # @param [Hash] levels Log levels in the format `{ debug: "red" }`
  def log_level levels = {}
    levels.each do |level, color|
      @levels[level.to_sym] ||= { enabled: true }
      @levels[level.to_sym][:color] = color
    end
  end

  # Calls the block with the given prefix and ensures that the prefix
  # will be the same as before.
  #
  # @param [String] prefix Prefix to use for the block
  # @param [Proc] block Block to call
  def ensure_prefix prefix, &block
    old_prefix, @prefix = @prefix, prefix
    block.call
  ensure
    @prefix = old_prefix
  end

  # Calls the block after changing the output method.
  # It also ensures to set back the method to what it was before.
  #
  # @param [Symbol] method Method to call on {#channel}
  def ensure_method method, &block
    old_method, old_logged = @method, @logged
    @method, @logged = method, 0
    block.call
  ensure
    @method = old_method
    @logged += old_logged
  end

  # Calls the block after changing the output method to `:print`.
  # It also ensures to set back the method to what it was before.
  #
  # @param [Boolean] clear If set to true and any message was printed inside the block
  #   a \n newline character will be printed.
  def log_with_print clear = true, &block
    ensure_method :print do
      begin
        block.call
      ensure
        puts if clear && @logged > 0
      end
    end
  end

  # Calls the block after disabling the runtime indicator.
  # It also ensures to set back the old setting after execution.
  def log_without_timestr &block
    timestr, @timestr = @timestr, false
    block.call
  ensure
    @timestr = timestr
  end

  # @return [Boolean] returns true if the log level format :debug is enabled.
  def debug?
    enabled? :debug
  end

  # If a `level` is provided it will return true if this log level is enabled.
  # If no `level` is provided it will return true if the logger is enabled generally.
  #
  # @return [Boolean] returns true if the given log level is enabled
  def enabled? level = nil
    level.nil? ? @enabled : @levels[level.to_sym][:enabled]
  end

  # Same as {#enabled?} just negated.
  def disabled? level = nil
    !enabled?(level)
  end

  # Same as {#enable} just negated.
  #
  # @param [Symbol, String] level Loglevel to disable.
  def disable level = nil
    if level.nil?
      @enabled = false
    else
      @levels[level.to_sym][:enabled] = false
    end
  end

  # Enables the given `level` or the logger generally if no `level` is given.
  # If the logger is disabled no messages will be printed. If it is enabled
  # only messages for enabled log levels will be printed.
  #
  # @param [Symbol, String] level Loglevel to enable.
  def enable level = nil
    if level.nil?
      @enabled = true
    else
      @levels[level.to_sym][:enabled] = true
    end
  end

  # Colorizes the given string with the given color. It uses the build-in
  # colorization feature. You may want to use the colorize gem.
  #
  # @param [String] str The string to colorize
  # @param [Symbol, String] color The color to use (see {COLORMAP})
  # @raise [ArgumentError] if color does not exist in {COLORMAP}.
  def colorize str, color
    ccode = COLORMAP[color.to_sym] || raise(ArgumentError, "Unknown color #{color}!")
    "\e[#{ccode}m#{str}\e[0m"
  end

  def colorize?
    @colorize
  end

  # This method is the only method which sends the message `msg` to `@channel` via `@method`.
  # It also increments the message counter `@logged` by one.
  #
  # This method instantly returns nil if the logger or the given log level `type` is disabled.
  #
  # @param [String] msg The message to send to the channel
  # @param [Symbol] type The log level
  def log msg, type = :info
    return if !@enabled || !@levels[type][:enabled]
    if @levels[type.to_sym] || !@levels.key?(type.to_sym)
      time = Time.at(Time.now.utc - @startup).utc
      timestr = @timestr ? "[#{time.strftime("%H:%M:%S.%L")} #{type.to_s.upcase}]\t" : ""

      if @colorize
        msg = "#{colorize(timestr, @levels[type.to_sym][:color])}" <<
              "#{@prefix}" <<
              "#{colorize(msg, @levels[type.to_sym][:color])}"
      else
        msg = "#{timestr}#{@prefix}#{msg}"
      end
      @logged += 1
      @channel.send(@method, msg)
    end
  end
  alias_method :info, :log

  # Shortcut for {#log #log(msg, :debug)}
  #
  # @param [String] msg The message to send to {#log}.
  def debug msg
    log(msg, :debug)
  end

  # Shortcut for {#log #log(msg, :warn)} but sets channel method to "warn".
  #
  # @param [String] msg The message to send to {#log}.
  def warn msg
    ensure_method(:warn) { log(msg, :warn) }
  end

  # Shortcut for {#log #log(msg, :abort)} but sets channel method to "warn".
  #
  # @param [String] msg The message to send to {#log}.
  # @param [Integer] exit_code Exits with given code or does nothing when falsy.
  def abort msg, exit_code = false
    ensure_method(:warn) { log(msg, :abort) }
    exit(exit_code) if exit_code
  end
end

#timestrBoolean



37
38
39
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
69
70
71
72
73
74
75
76
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
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
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
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
255
256
257
# File 'lib/banana/logger.rb', line 37

class Logger
  attr_reader :startup, :channel, :method, :logged
  attr_accessor :colorize, :prefix

  # Foreground color values
  COLORMAP = {
    black: 30,
    red: 31,
    green: 32,
    yellow: 33,
    blue: 34,
    magenta: 35,
    cyan: 36,
    white: 37,
  }

  # Initializes a new logger instance. The internal runtime measurement starts here!
  #
  # There are 4 default log levels: info (yellow), warn & abort (red) and debug (blue).
  # All are enabled by default. You propably want to {#disable disable(:debug)}.
  #
  # @param scope Only for backward compatibility, not used
  # @todo add option hash
  def initialize scope = nil
    @startup = Time.now.utc
    @colorize = true
    @prefix = ""
    @enabled = true
    @timestr = true
    @channel = ::Kernel
    @method = :puts
    @logged = 0
    @levels = {
      info: { color: "yellow", enabled: true },
      warn: { color: "red", enabled: true },
      abort: { color: "red", enabled: true },
      debug: { color: "blue", enabled: true },
    }
  end

  # The default channel is `Kernel` which is Ruby's normal `puts`.
  # Attach it to a open file with write access and it will write into
  # the file. Ensure to close the file in your code.
  #
  # @param channel Object which responds to puts and print
  def attach channel
    @channel = channel
  end

  # Print raw message onto {#channel} using {#method}.
  #
  # @param [String] msg Message to send to {#channel}.
  # @param [Symbol] method Override {#method}.
  def raw msg, method = @method
    @channel.send(method, msg)
  end

  # Add additional log levels which are automatically enabled.
  # @param [Hash] levels Log levels in the format `{ debug: "red" }`
  def log_level levels = {}
    levels.each do |level, color|
      @levels[level.to_sym] ||= { enabled: true }
      @levels[level.to_sym][:color] = color
    end
  end

  # Calls the block with the given prefix and ensures that the prefix
  # will be the same as before.
  #
  # @param [String] prefix Prefix to use for the block
  # @param [Proc] block Block to call
  def ensure_prefix prefix, &block
    old_prefix, @prefix = @prefix, prefix
    block.call
  ensure
    @prefix = old_prefix
  end

  # Calls the block after changing the output method.
  # It also ensures to set back the method to what it was before.
  #
  # @param [Symbol] method Method to call on {#channel}
  def ensure_method method, &block
    old_method, old_logged = @method, @logged
    @method, @logged = method, 0
    block.call
  ensure
    @method = old_method
    @logged += old_logged
  end

  # Calls the block after changing the output method to `:print`.
  # It also ensures to set back the method to what it was before.
  #
  # @param [Boolean] clear If set to true and any message was printed inside the block
  #   a \n newline character will be printed.
  def log_with_print clear = true, &block
    ensure_method :print do
      begin
        block.call
      ensure
        puts if clear && @logged > 0
      end
    end
  end

  # Calls the block after disabling the runtime indicator.
  # It also ensures to set back the old setting after execution.
  def log_without_timestr &block
    timestr, @timestr = @timestr, false
    block.call
  ensure
    @timestr = timestr
  end

  # @return [Boolean] returns true if the log level format :debug is enabled.
  def debug?
    enabled? :debug
  end

  # If a `level` is provided it will return true if this log level is enabled.
  # If no `level` is provided it will return true if the logger is enabled generally.
  #
  # @return [Boolean] returns true if the given log level is enabled
  def enabled? level = nil
    level.nil? ? @enabled : @levels[level.to_sym][:enabled]
  end

  # Same as {#enabled?} just negated.
  def disabled? level = nil
    !enabled?(level)
  end

  # Same as {#enable} just negated.
  #
  # @param [Symbol, String] level Loglevel to disable.
  def disable level = nil
    if level.nil?
      @enabled = false
    else
      @levels[level.to_sym][:enabled] = false
    end
  end

  # Enables the given `level` or the logger generally if no `level` is given.
  # If the logger is disabled no messages will be printed. If it is enabled
  # only messages for enabled log levels will be printed.
  #
  # @param [Symbol, String] level Loglevel to enable.
  def enable level = nil
    if level.nil?
      @enabled = true
    else
      @levels[level.to_sym][:enabled] = true
    end
  end

  # Colorizes the given string with the given color. It uses the build-in
  # colorization feature. You may want to use the colorize gem.
  #
  # @param [String] str The string to colorize
  # @param [Symbol, String] color The color to use (see {COLORMAP})
  # @raise [ArgumentError] if color does not exist in {COLORMAP}.
  def colorize str, color
    ccode = COLORMAP[color.to_sym] || raise(ArgumentError, "Unknown color #{color}!")
    "\e[#{ccode}m#{str}\e[0m"
  end

  def colorize?
    @colorize
  end

  # This method is the only method which sends the message `msg` to `@channel` via `@method`.
  # It also increments the message counter `@logged` by one.
  #
  # This method instantly returns nil if the logger or the given log level `type` is disabled.
  #
  # @param [String] msg The message to send to the channel
  # @param [Symbol] type The log level
  def log msg, type = :info
    return if !@enabled || !@levels[type][:enabled]
    if @levels[type.to_sym] || !@levels.key?(type.to_sym)
      time = Time.at(Time.now.utc - @startup).utc
      timestr = @timestr ? "[#{time.strftime("%H:%M:%S.%L")} #{type.to_s.upcase}]\t" : ""

      if @colorize
        msg = "#{colorize(timestr, @levels[type.to_sym][:color])}" <<
              "#{@prefix}" <<
              "#{colorize(msg, @levels[type.to_sym][:color])}"
      else
        msg = "#{timestr}#{@prefix}#{msg}"
      end
      @logged += 1
      @channel.send(@method, msg)
    end
  end
  alias_method :info, :log

  # Shortcut for {#log #log(msg, :debug)}
  #
  # @param [String] msg The message to send to {#log}.
  def debug msg
    log(msg, :debug)
  end

  # Shortcut for {#log #log(msg, :warn)} but sets channel method to "warn".
  #
  # @param [String] msg The message to send to {#log}.
  def warn msg
    ensure_method(:warn) { log(msg, :warn) }
  end

  # Shortcut for {#log #log(msg, :abort)} but sets channel method to "warn".
  #
  # @param [String] msg The message to send to {#log}.
  # @param [Integer] exit_code Exits with given code or does nothing when falsy.
  def abort msg, exit_code = false
    ensure_method(:warn) { log(msg, :abort) }
    exit(exit_code) if exit_code
  end
end

Instance Method Details

#abort(msg, exit_code = false) ⇒ Object

Shortcut for #log(msg, :abort) but sets channel method to “warn”.



253
254
255
256
# File 'lib/banana/logger.rb', line 253

def abort msg, exit_code = false
  ensure_method(:warn) { log(msg, :abort) }
  exit(exit_code) if exit_code
end

#attach(channel) ⇒ Object

The default channel is ‘Kernel` which is Ruby’s normal ‘puts`. Attach it to a open file with write access and it will write into the file. Ensure to close the file in your code.



82
83
84
# File 'lib/banana/logger.rb', line 82

def attach channel
  @channel = channel
end

#colorize?Boolean



205
206
207
# File 'lib/banana/logger.rb', line 205

def colorize?
  @colorize
end

#debug(msg) ⇒ Object

Shortcut for #log(msg, :debug)



238
239
240
# File 'lib/banana/logger.rb', line 238

def debug msg
  log(msg, :debug)
end

#debug?Boolean



153
154
155
# File 'lib/banana/logger.rb', line 153

def debug?
  enabled? :debug
end

#disable(level = nil) ⇒ Object

Same as #enable just negated.



173
174
175
176
177
178
179
# File 'lib/banana/logger.rb', line 173

def disable level = nil
  if level.nil?
    @enabled = false
  else
    @levels[level.to_sym][:enabled] = false
  end
end

#disabled?(level = nil) ⇒ Boolean

Same as #enabled? just negated.



166
167
168
# File 'lib/banana/logger.rb', line 166

def disabled? level = nil
  !enabled?(level)
end

#enable(level = nil) ⇒ Object

Enables the given ‘level` or the logger generally if no `level` is given. If the logger is disabled no messages will be printed. If it is enabled only messages for enabled log levels will be printed.



186
187
188
189
190
191
192
# File 'lib/banana/logger.rb', line 186

def enable level = nil
  if level.nil?
    @enabled = true
  else
    @levels[level.to_sym][:enabled] = true
  end
end

#enabled?(level = nil) ⇒ Boolean

If a ‘level` is provided it will return true if this log level is enabled. If no `level` is provided it will return true if the logger is enabled generally.



161
162
163
# File 'lib/banana/logger.rb', line 161

def enabled? level = nil
  level.nil? ? @enabled : @levels[level.to_sym][:enabled]
end

#ensure_method(method, &block) ⇒ Object

Calls the block after changing the output method. It also ensures to set back the method to what it was before.



119
120
121
122
123
124
125
126
# File 'lib/banana/logger.rb', line 119

def ensure_method method, &block
  old_method, old_logged = @method, @logged
  @method, @logged = method, 0
  block.call
ensure
  @method = old_method
  @logged += old_logged
end

#ensure_prefix(prefix, &block) ⇒ Object

Calls the block with the given prefix and ensures that the prefix will be the same as before.



108
109
110
111
112
113
# File 'lib/banana/logger.rb', line 108

def ensure_prefix prefix, &block
  old_prefix, @prefix = @prefix, prefix
  block.call
ensure
  @prefix = old_prefix
end

#log(msg, type = :info) ⇒ Object Also known as: info

This method is the only method which sends the message ‘msg` to `@channel` via `@method`. It also increments the message counter `@logged` by one.

This method instantly returns nil if the logger or the given log level ‘type` is disabled.



216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
# File 'lib/banana/logger.rb', line 216

def log msg, type = :info
  return if !@enabled || !@levels[type][:enabled]
  if @levels[type.to_sym] || !@levels.key?(type.to_sym)
    time = Time.at(Time.now.utc - @startup).utc
    timestr = @timestr ? "[#{time.strftime("%H:%M:%S.%L")} #{type.to_s.upcase}]\t" : ""

    if @colorize
      msg = "#{colorize(timestr, @levels[type.to_sym][:color])}" <<
            "#{@prefix}" <<
            "#{colorize(msg, @levels[type.to_sym][:color])}"
    else
      msg = "#{timestr}#{@prefix}#{msg}"
    end
    @logged += 1
    @channel.send(@method, msg)
  end
end

#log_level(levels = {}) ⇒ Object

Add additional log levels which are automatically enabled.



96
97
98
99
100
101
# File 'lib/banana/logger.rb', line 96

def log_level levels = {}
  levels.each do |level, color|
    @levels[level.to_sym] ||= { enabled: true }
    @levels[level.to_sym][:color] = color
  end
end

#log_with_print(clear = true, &block) ⇒ Object

Calls the block after changing the output method to ‘:print`. It also ensures to set back the method to what it was before.



133
134
135
136
137
138
139
140
141
# File 'lib/banana/logger.rb', line 133

def log_with_print clear = true, &block
  ensure_method :print do
    begin
      block.call
    ensure
      puts if clear && @logged > 0
    end
  end
end

#log_without_timestr(&block) ⇒ Object

Calls the block after disabling the runtime indicator. It also ensures to set back the old setting after execution.



145
146
147
148
149
150
# File 'lib/banana/logger.rb', line 145

def log_without_timestr &block
  timestr, @timestr = @timestr, false
  block.call
ensure
  @timestr = timestr
end

#raw(msg, method = @method) ⇒ Object

Print raw message onto #channel using #method.



90
91
92
# File 'lib/banana/logger.rb', line 90

def raw msg, method = @method
  @channel.send(method, msg)
end

#warn(msg) ⇒ Object

Shortcut for #log(msg, :warn) but sets channel method to “warn”.



245
246
247
# File 'lib/banana/logger.rb', line 245

def warn msg
  ensure_method(:warn) { log(msg, :warn) }
end