Module: Bolt::Logger

Defined in:
lib/bolt/logger.rb

Constant Summary collapse

LEVELS =
%w[trace debug info warn error fatal].freeze

Class Method Summary collapse

Class Method Details

.analytics=(analytics) ⇒ Object



109
110
111
# File 'lib/bolt/logger.rb', line 109

def self.analytics=(analytics)
  @analytics = analytics
end

.configure(destinations, color, disable_warnings = nil) ⇒ Object



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
# File 'lib/bolt/logger.rb', line 45

def self.configure(destinations, color, disable_warnings = nil)
  root_logger = Bolt::Logger.logger(:root)

  root_logger.add_appenders Logging.appenders.stderr(
    'console',
    layout: console_layout(color),
    level: default_console_level
  )

  # We set the root logger's level so that it logs everything but we do
  # limit what's actually logged in every appender individually.
  root_logger.level = :all

  destinations.each_pair do |name, params|
    appender = Logging.appenders[name]
    if appender.nil?
      unless name.start_with?('file:')
        raise Bolt::Error.new("Unexpected log: #{name}", 'bolt/internal-error')
      end

      begin
        appender = Logging.appenders.file(
          name,
          filename: name[5..-1], # strip the "file:" prefix
          truncate: (params[:append] == false),
          layout: default_layout,
          level: default_file_level
        )
      rescue ArgumentError => e
        raise Bolt::Error.new("Failed to open log #{name}: #{e.message}", 'bolt/log-error')
      end

      root_logger.add_appenders appender
    end

    appender.level = params[:level] if params[:level]
  end

  # Set the list of disabled warnings and mark the logger as configured.
  # Log all messages in the message queue and flush the queue.
  if disable_warnings
    @mutex.synchronize { @disable_warnings = disable_warnings }
  end
end

.configured?Boolean

Returns:

  • (Boolean)


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

def self.configured?
  Logging.logger[:root].appenders.any?
end

.console_layout(color) ⇒ Object



113
114
115
116
117
118
119
# File 'lib/bolt/logger.rb', line 113

def self.console_layout(color)
  color_scheme = :bolt if color
  Logging.layouts.pattern(
    pattern: '%m\e[0m\n',
    color_scheme: color_scheme
  )
end

.debug(msg) ⇒ Object



174
175
176
# File 'lib/bolt/logger.rb', line 174

def self.debug(msg)
  log(type: :debug, msg: msg)
end

.default_console_levelObject



128
129
130
# File 'lib/bolt/logger.rb', line 128

def self.default_console_level
  :warn
end

.default_file_levelObject



132
133
134
# File 'lib/bolt/logger.rb', line 132

def self.default_file_level
  :warn
end

.default_layoutObject



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

def self.default_layout
  Logging.layouts.pattern(
    pattern: '%d %-6l [%T] [%c] %m\n',
    date_pattern: '%Y-%m-%dT%H:%M:%S.%6N'
  )
end

.deprecate(id, msg) ⇒ Object



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

def self.deprecate(id, msg)
  log(type: :deprecate, msg: "#{msg} [ID: #{id}]", id: id)
end

.deprecate_once(id, msg) ⇒ Object



170
171
172
# File 'lib/bolt/logger.rb', line 170

def self.deprecate_once(id, msg)
  log(type: :deprecate_once, msg: "#{msg} [ID: #{id}]", id: id)
end

.flush_queueObject

Logs all messages in the message queue and then flushes the queue.



203
204
205
206
207
208
209
210
211
# File 'lib/bolt/logger.rb', line 203

def self.flush_queue
  @mutex.synchronize do
    @message_queue.each do |message|
      log_message(**message)
    end

    @message_queue.clear
  end
end

.info(msg) ⇒ Object



178
179
180
# File 'lib/bolt/logger.rb', line 178

def self.info(msg)
  log(type: :info, msg: msg)
end

.initialize_loggingObject

This method provides a single point-of-entry to setup logging for both the CLI and for tests. This is necessary because we define custom log levels which create corresponding methods on the logger instances; without first initializing the Logging system, calls to those methods will fail.



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/bolt/logger.rb', line 22

def self.initialize_logging
  # Initialization isn't idempotent and will result in warnings about const
  # redefs, so skip it if the log levels we expect are present. If it's
  # already been initialized with an insufficient set of levels, go ahead
  # and call init anyway or we'll have failures when calling log methods
  # for missing levels.
  unless levels & LEVELS == LEVELS
    Logging.init(*LEVELS)
  end

  # As above, only create the color scheme if we haven't already created it.
  unless Logging.color_scheme('bolt')
    Logging.color_scheme(
      'bolt',
      lines: {
        warn: :yellow,
        error: :red,
        fatal: %i[white on_red]
      }
    )
  end
end

.levelsObject



142
143
144
# File 'lib/bolt/logger.rb', line 142

def self.levels
  Logging::LNAMES.map(&:downcase)
end

.logger(name) ⇒ Object

A helper to ensure the Logging library is always initialized with our custom log levels before retrieving a Logger instance.



104
105
106
107
# File 'lib/bolt/logger.rb', line 104

def self.logger(name)
  initialize_logging
  Logging.logger[name]
end

.reset_loggingObject



146
147
148
# File 'lib/bolt/logger.rb', line 146

def self.reset_logging
  Logging.reset
end

.streamObject



94
95
96
# File 'lib/bolt/logger.rb', line 94

def self.stream
  @stream
end

.stream=(stream) ⇒ Object



98
99
100
# File 'lib/bolt/logger.rb', line 98

def self.stream=(stream)
  @stream = stream
end

.valid_level?(level) ⇒ Boolean

Explicitly check the log level names instead of the log level number, as levels that are stringified integers (e.g. “level” => “42”) will return a truthy value

Returns:

  • (Boolean)


138
139
140
# File 'lib/bolt/logger.rb', line 138

def self.valid_level?(level)
  Logging::LEVELS.include?(Logging.levelify(level))
end

.warn(id, msg) ⇒ Object

The following methods are used in place of the Logging.logger methods of the same name when logging warning messages or logging any messages prior to the logger being configured. If the logger is not configured when any of these methods are called, the message will be added to a queue, otherwise they are logged immediately. The message queue is flushed by calling #flush_queue, which is called from Bolt::CLI after configuring the logger.



158
159
160
# File 'lib/bolt/logger.rb', line 158

def self.warn(id, msg)
  log(type: :warn, msg: "#{msg} [ID: #{id}]", id: id)
end

.warn_once(id, msg) ⇒ Object



162
163
164
# File 'lib/bolt/logger.rb', line 162

def self.warn_once(id, msg)
  log(type: :warn_once, msg: "#{msg} [ID: #{id}]", id: id)
end