class Console::Filter
def self.[] **levels
def self.[] **levels klass = Class.new(self) minimum_level, maximum_level = levels.values.minmax klass.instance_exec do const_set(:LEVELS, levels.freeze) const_set(:MINIMUM_LEVEL, minimum_level) const_set(:MAXIMUM_LEVEL, maximum_level) levels.each do |name, level| const_set(name.to_s.upcase, level) define_immutable_method(name) do |subject = nil, *arguments, **options, &block| if self.enabled?(subject, level) @output.call(subject, *arguments, severity: name, **@options, **options, &block) end end define_immutable_method("#{name}!") do @level = level end define_immutable_method("#{name}?") do @level <= level end end end return klass end
def self.define_immutable_method(name, &block)
def self.define_immutable_method(name, &block) block = Ractor.make_shareable(block) self.define_method(name, &block) end
def self.define_immutable_method(name, &block)
def self.define_immutable_method(name, &block) define_method(name, &block) end
def all!
def all! @level = self.class::MINIMUM_LEVEL - 1 end
def call(subject, *arguments, **options, &block)
def call(subject, *arguments, **options, &block) severity = options[:severity] || UNKNOWN level = self.class::LEVELS[severity] if self.enabled?(subject, level) @output.call(subject, *arguments, **options, &block) end end
def clear(subject)
Clear any specific filters for the given class.
def clear(subject) unless subject.is_a?(Module) raise ArgumentError, "Expected a class, got #{subject.inspect}" end @subjects.delete(subject) end
def disable(subject)
def disable(subject) # Set the filter level of the logging for a given subject which filters all log messages: filter(subject, self.class::MAXIMUM_LEVEL + 1) end
def enable(subject, level = self.class::MINIMUM_LEVEL)
Enable specific log level for the given class.
def enable(subject, level = self.class::MINIMUM_LEVEL) # Set the filter level of logging for a given subject which passes all log messages: filter(subject, level) end
def enabled?(subject, level = self.class::MINIMUM_LEVEL)
-
subject
(Object
) -- the subject to check.
def enabled?(subject, level = self.class::MINIMUM_LEVEL) subject = subject.class unless subject.is_a?(Module) if specific_level = @subjects[subject] return level >= specific_level end if level >= @level return true end end
def filter(subject, level)
def filter(subject, level) unless subject.is_a?(Module) raise ArgumentError, "Expected a class, got #{subject.inspect}" end @subjects[subject] = level end
def initialize(output, verbose: true, level: self.class::DEFAULT_LEVEL, **options)
def initialize(output, verbose: true, level: self.class::DEFAULT_LEVEL, **options) @output = output @verbose = verbose @level = level @subjects = {} @options = options end
def level= level
def level= level if level.is_a? Symbol @level = self.class::LEVELS[level] else @level = level end end
def off!
def off! @level = self.class::MAXIMUM_LEVEL + 1 end
def verbose!(value = true)
def verbose!(value = true) @verbose = value @output.verbose!(value) end
def with(level: @level, verbose: @verbose, **options)
def with(level: @level, verbose: @verbose, **options) dup.tap do |logger| logger.level = level logger.verbose! if verbose logger.options = @options.merge(options) end end