Class: TTY::Logger
- Inherits:
-
Object
- Object
- TTY::Logger
- Includes:
- Levels
- Defined in:
- lib/tty/logger.rb,
lib/tty/logger/event.rb,
lib/tty/logger/config.rb,
lib/tty/logger/levels.rb,
lib/tty/logger/version.rb,
lib/tty/logger/data_filter.rb,
lib/tty/logger/handlers/base.rb,
lib/tty/logger/handlers/null.rb,
lib/tty/logger/formatters/json.rb,
lib/tty/logger/formatters/text.rb,
lib/tty/logger/handlers/stream.rb,
lib/tty/logger/handlers/console.rb
Defined Under Namespace
Modules: Formatters, Handlers, Levels Classes: Config, DataFilter, Error, Event
Constant Summary collapse
- LOG_TYPES =
{ debug: { level: :debug }, info: { level: :info }, warn: { level: :warn }, error: { level: :error }, fatal: { level: :fatal }, success: { level: :info }, wait: { level: :info } }.freeze
- VERSION =
"0.6.0"
Constants included from Levels
Levels::DEBUG_LEVEL, Levels::ERROR_LEVEL, Levels::FATAL_LEVEL, Levels::INFO_LEVEL, Levels::LEVEL_NAMES, Levels::WARN_LEVEL
Class Method Summary collapse
-
.config ⇒ Object
Logger configuration instance.
-
.configure {|config| ... } ⇒ Object
Global logger configuration.
-
.define_level(name, log_level = nil) ⇒ Object
private
Macro to dynamically define log types.
Instance Method Summary collapse
-
#add_handler(handler, **options) ⇒ Object
Add handler for logging messages.
-
#add_type(name, log_level) ⇒ Object
private
Add new log type.
-
#coerce_handler(name) ⇒ Class
private
Coerce handler name into object.
-
#configure {|@config| ... } ⇒ Object
Instance logger configuration.
-
#copy(new_fields) ⇒ TTY::Logger
Copy this logger.
-
#copy_error(error, message, backtrace = nil) ⇒ Exception
private
Create a new error instance copy.
-
#filter(*objects) ⇒ Array[String]
private
Filter message parts for any sensitive information and replace with placeholder.
-
#initialize(output: nil, fields: {}) ⇒ Logger
constructor
Create a logger instance.
-
#log(current_level, *msg) ⇒ Object
Log a message given the severtiy level.
-
#log?(level, other_level) ⇒ Symbol
Check current level against another.
-
#log_at(tmp_level, &block) ⇒ Object
Change current log level for the duration of the block.
-
#raise_handler_error ⇒ Object
private
Raise error when unknown handler name.
-
#remove_handler(handler) ⇒ Object
Remove log events handler.
-
#swap_filtered(obj) ⇒ Object
private
Swap string content for filtered content.
-
#write(*msg) ⇒ Object
(also: #<<)
Logs streaming output.
Methods included from Levels
#compare_levels, #level_names, #level_to_number, #number_to_level
Constructor Details
#initialize(output: nil, fields: {}) ⇒ Logger
Create a logger instance
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 |
# File 'lib/tty/logger.rb', line 91 def initialize(output: nil, fields: {}) @fields = fields @config = if block_given? conf = Config.new yield(conf) conf else self.class.config end @level = @config.level @handlers = @config.handlers @output = output || @config.output @ready_handlers = [] @data_filter = DataFilter.new(@config.filters.data, mask: @config.filters.mask) @types = LOG_TYPES.dup @config.types.each do |name, log_level| add_type(name, log_level) end @handlers.each do |handler| add_handler(handler) end end |
Class Method Details
.config ⇒ Object
Logger configuration instance
61 62 63 |
# File 'lib/tty/logger.rb', line 61 def self.config @config ||= Config.new end |
.configure {|config| ... } ⇒ Object
Global logger configuration
68 69 70 |
# File 'lib/tty/logger.rb', line 68 def self.configure yield config end |
.define_level(name, log_level = nil) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Macro to dynamically define log types
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/tty/logger.rb', line 34 def self.define_level(name, log_level = nil) const_level = (LOG_TYPES[name.to_sym] || log_level)[:level] loc = caller_locations(0, 1)[0] if loc file, line = loc.path, loc.lineno + 7 else file, line = __FILE__, __LINE__ + 3 end class_eval(<<-EOL, file, line) def #{name}(*msg, &block) log(:#{const_level}, *msg, &block) end EOL end |
Instance Method Details
#add_handler(handler, **options) ⇒ Object
Add handler for logging messages
147 148 149 150 151 152 153 154 |
# File 'lib/tty/logger.rb', line 147 def add_handler(handler, **) h, h_opts = *(handler.is_a?(Array) ? handler : [handler, ]) handler_type = coerce_handler(h) global_opts = { output: @output, config: @config } opts = global_opts.merge(h_opts) ready_handler = handler_type.new(**opts) @ready_handlers << ready_handler end |
#add_type(name, log_level) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Add new log type
123 124 125 126 127 128 129 130 |
# File 'lib/tty/logger.rb', line 123 def add_type(name, log_level) if @types.include?(name) raise Error, "Already defined log type #{name.inspect}" end @types[name.to_sym] = log_level self.class.define_level(name, log_level) end |
#coerce_handler(name) ⇒ Class
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Coerce handler name into object
178 179 180 181 182 183 184 185 186 187 188 189 |
# File 'lib/tty/logger.rb', line 178 def coerce_handler(name) case name when String, Symbol Handlers.const_get(name.capitalize) when Class name else raise_handler_error end rescue NameError raise_handler_error end |
#configure {|@config| ... } ⇒ Object
Instance logger configuration
75 76 77 |
# File 'lib/tty/logger.rb', line 75 def configure yield @config end |
#copy(new_fields) ⇒ TTY::Logger
Copy this logger
209 210 211 212 213 214 215 216 |
# File 'lib/tty/logger.rb', line 209 def copy(new_fields) new_config = @config.to_proc.call(Config.new) if block_given? yield(new_config) end self.class.new(fields: @fields.merge(new_fields), output: @output, &new_config) end |
#copy_error(error, message, backtrace = nil) ⇒ Exception
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Create a new error instance copy
333 334 335 336 337 |
# File 'lib/tty/logger.rb', line 333 def copy_error(error, , backtrace = nil) new_error = error.exception() new_error.set_backtrace(backtrace) new_error end |
#filter(*objects) ⇒ Array[String]
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Filter message parts for any sensitive information and replace with placeholder.
312 313 314 315 316 317 318 319 320 321 322 |
# File 'lib/tty/logger.rb', line 312 def filter(*objects) objects.map do |obj| case obj when Exception backtrace = Array(obj.backtrace).map { |line| swap_filtered(line) } copy_error(obj, swap_filtered(obj.), backtrace) else swap_filtered(obj.to_s) end end end |
#log(current_level, *msg) ⇒ Object
Log a message given the severtiy level
253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 |
# File 'lib/tty/logger.rb', line 253 def log(current_level, *msg) scoped_fields = msg.last.is_a?(::Hash) ? msg.pop : {} fields_copy = scoped_fields.dup if msg.empty? && block_given? msg = [] Array[yield].flatten(1).each do |el| el.is_a?(::Hash) ? fields_copy.merge!(el) : msg << el end end top_caller = caller_locations(1, 1)[0] loc = caller_locations(2, 1)[0] || top_caller label = top_caller.label = { level: current_level, time: Time.now, pid: Process.pid, name: @types.include?(label.to_sym) ? label : current_level, path: loc.path, lineno: loc.lineno, method: loc.base_label } event = Event.new(filter(*msg), @data_filter.filter(@fields.merge(fields_copy)), ) @ready_handlers.each do |handler| level = handler.respond_to?(:level) ? handler.level : @config.level handler.(event) if log?(level, current_level) end self end |
#log?(level, other_level) ⇒ Symbol
Check current level against another
223 224 225 |
# File 'lib/tty/logger.rb', line 223 def log?(level, other_level) compare_levels(level, other_level) != :gt end |
#log_at(tmp_level, &block) ⇒ Object
Change current log level for the duration of the block
296 297 298 299 300 |
# File 'lib/tty/logger.rb', line 296 def log_at(tmp_level, &block) @ready_handlers.each do |handler| handler.log_at(tmp_level, &block) end end |
#raise_handler_error ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Raise error when unknown handler name
194 195 196 |
# File 'lib/tty/logger.rb', line 194 def raise_handler_error raise Error, "Handler needs to be a class name or a symbol name" end |
#remove_handler(handler) ⇒ Object
Remove log events handler
162 163 164 165 |
# File 'lib/tty/logger.rb', line 162 def remove_handler(handler) handler_type = coerce_handler(handler) @ready_handlers.delete_if { |_handler| _handler.is_a?(handler_type) } end |
#swap_filtered(obj) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Swap string content for filtered content
344 345 346 347 348 349 350 |
# File 'lib/tty/logger.rb', line 344 def swap_filtered(obj) obj.dup.tap do |obj_copy| @config.filters..each do |text| obj_copy.gsub!(text, @config.filters.mask) end end end |