Module: Bolt::Logger

Defined in:
lib/bolt/logger.rb

Constant Summary collapse

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

Class Method Summary collapse

Class Method Details

.analytics=(analytics) ⇒ Object



85
86
87
# File 'lib/bolt/logger.rb', line 85

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

.configure(destinations, color) ⇒ Object



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

def self.configure(destinations, color)
  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
end

.console_layout(color) ⇒ Object



89
90
91
92
93
94
95
# File 'lib/bolt/logger.rb', line 89

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

.default_console_levelObject



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

def self.default_console_level
  :warn
end

.default_file_levelObject



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

def self.default_file_level
  :warn
end

.default_layoutObject



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

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

.deprecation_warning(type, msg) ⇒ Object



135
136
137
138
# File 'lib/bolt/logger.rb', line 135

def self.deprecation_warning(type, msg)
  @analytics&.event('Warn', 'deprecation', label: type)
  warn_once(type, 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.



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/bolt/logger.rb', line 16

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



118
119
120
# File 'lib/bolt/logger.rb', line 118

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.



80
81
82
83
# File 'lib/bolt/logger.rb', line 80

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

.reset_loggingObject



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

def self.reset_logging
  Logging.reset
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)


114
115
116
# File 'lib/bolt/logger.rb', line 114

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

.warn_once(type, msg) ⇒ Object



126
127
128
129
130
131
132
133
# File 'lib/bolt/logger.rb', line 126

def self.warn_once(type, msg)
  @mutex.synchronize do
    @logger ||= Bolt::Logger.logger(self)
    if @warnings.add?(type)
      @logger.warn(msg)
    end
  end
end