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).

Parameters:

  • scope (defaults to: nil)

    Only for backward compatibility, not used



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)

Returns The object where messages are getting send to.

Returns:

  • (Object)

    The object where messages are getting send to.



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.

Parameters:

  • str (String)

    The string to colorize

  • color (Symbol, String)

    The color to use (see COLORMAP)

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.

Returns:

  • (Integer)

    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)

Returns The method used to send messages to #channel.

Returns:

  • (Object)

    The method used to send messages 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

#prefixString

Returns Current prefix string for logged messages.

Returns:

  • (String)

    Current prefix string for logged messages.



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)

Returns Point of time where the logger was initiated.

Returns:

  • (DateTime)

    Point of time where the logger was initiated.



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

Returns Set to false if the runtime indicator should not be printed (default: true).

Returns:

  • (Boolean)

    Set to false if the runtime indicator should not be printed (default: true).



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”.

Parameters:

  • msg (String)

    The message to send to #log.

  • exit_code (Integer) (defaults to: false)

    Exits with given code or does nothing when falsy.



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.

Parameters:

  • channel

    Object which responds to puts and print



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

def attach channel
  @channel = channel
end

#colorize?Boolean

Returns:

  • (Boolean)


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

def colorize?
  @colorize
end

#debug(msg) ⇒ Object

Shortcut for #log(msg, :debug)

Parameters:

  • msg (String)

    The message to send to #log.



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

def debug msg
  log(msg, :debug)
end

#debug?Boolean

Returns true if the log level format :debug is enabled.

Returns:

  • (Boolean)

    returns true if the log level format :debug is enabled.



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

def debug?
  enabled? :debug
end

#disable(level = nil) ⇒ Object

Same as #enable just negated.

Parameters:

  • level (Symbol, String) (defaults to: nil)

    Loglevel to disable.



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.

Returns:

  • (Boolean)


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.

Parameters:

  • level (Symbol, String) (defaults to: nil)

    Loglevel to enable.



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.

Returns:

  • (Boolean)

    returns true if the given log level is enabled



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.

Parameters:

  • method (Symbol)

    Method to call on #channel



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.

Parameters:

  • prefix (String)

    Prefix to use for the block

  • block (Proc)

    Block to call



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.

Parameters:

  • msg (String)

    The message to send to the channel

  • type (Symbol) (defaults to: :info)

    The log level



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.

Parameters:

  • levels (Hash) (defaults to: {})

    Log levels in the format ‘{ debug: “red” }`



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.

Parameters:

  • clear (Boolean) (defaults to: true)

    If set to true and any message was printed inside the block a n newline character will be printed.



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.

Parameters:

  • msg (String)

    Message to send to #channel.

  • method (Symbol) (defaults to: @method)

    Override #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”.

Parameters:

  • msg (String)

    The message to send to #log.



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

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