Class: Console::Filter

Inherits:
Object
  • Object
show all
Defined in:
lib/console/filter.rb

Overview

A log filter which can be used to filter log messages based on severity, subject, and other criteria.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(output, verbose: true, level: nil, **options) ⇒ Filter

Create a new log filter.



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/console/filter.rb', line 77

def initialize(output, verbose: true, level: nil, **options)
  @output = output
  @verbose = verbose
  
  # Set the log level using the behaviour implemented in `level=`:
  if level
    self.level = level
  else
    @level = self.class::DEFAULT_LEVEL
  end
  
  @subjects = {}
  
  @options = options
end

Instance Attribute Details

#levelObject

Returns the value of attribute level.



114
115
116
# File 'lib/console/filter.rb', line 114

def level
  @level
end

#optionsObject

Returns the value of attribute options.



120
121
122
# File 'lib/console/filter.rb', line 120

def options
  @options
end

#outputObject

Returns the value of attribute output.



108
109
110
# File 'lib/console/filter.rb', line 108

def output
  @output
end

#subjectsObject (readonly)

Returns the value of attribute subjects.



117
118
119
# File 'lib/console/filter.rb', line 117

def subjects
  @subjects
end

#The current log level.(currentloglevel.) ⇒ Object (readonly)



114
# File 'lib/console/filter.rb', line 114

attr :level

#The log levels for specific subject (classes).(loglevels) ⇒ Object (readonly)



117
# File 'lib/console/filter.rb', line 117

attr :subjects

#verboseObject (readonly)

Returns the value of attribute verbose.



111
112
113
# File 'lib/console/filter.rb', line 111

def verbose
  @verbose
end

Class Method Details

.[](**levels) ⇒ Object

Create a new log filter with specific log levels.

“‘ruby class MyLogger < Console::Filter[debug: 0, okay: 1, bad: 2, terrible: 3] “`



34
35
36
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
# File 'lib/console/filter.rb', line 34

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)
    
    # The default log level for instances of this filter class.
    # Set to MINIMUM_LEVEL to allow all messages by default.
    const_set(:DEFAULT_LEVEL, minimum_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
        
        return nil
      end
      
      define_immutable_method("#{name}!") do
        @level = level
      end
      
      define_immutable_method("#{name}?") do
        @level <= level
      end
    end
  end
  
  return klass
end

.define_immutable_method(name, &block) ⇒ Object

Define a method.



16
17
18
19
# File 'lib/console/filter.rb', line 16

def self.define_immutable_method(name, &block)
  block = Ractor.make_shareable(block)
  self.define_method(name, &block)
end

Instance Method Details

#Additional options.=(options. = (value)) ⇒ Object



120
# File 'lib/console/filter.rb', line 120

attr_accessor :options

#all!Object

Enable all logging.



147
148
149
# File 'lib/console/filter.rb', line 147

def all!
  @level = self.class::MINIMUM_LEVEL - 1
end

#call(subject, *arguments, **options, &block) ⇒ Object

Log a message with the given severity.

If the severity is not defined in this filter’s LEVELS (e.g., when chaining filters with different severity levels), the message is passed through to the output without filtering. This allows custom filters to be composed together.



222
223
224
225
226
227
228
229
230
231
232
# File 'lib/console/filter.rb', line 222

def call(subject, *arguments, **options, &block)
  severity = options[:severity] || UNKNOWN
  level = self.class::LEVELS[severity]
  
  # If the severity is unknown (level is nil), pass through to output without filtering:
  if level.nil? || self.enabled?(subject, level)
    @output.call(subject, *arguments, **options, &block)
  end
  
  return nil
end

#clear(subject) ⇒ Object

Clear any specific filters for the given class.



203
204
205
206
207
208
209
# File 'lib/console/filter.rb', line 203

def clear(subject)
  unless subject.is_a?(Module)
    raise ArgumentError, "Expected a class, got #{subject.inspect}"
  end
  
  @subjects.delete(subject)
end

#disable(subject) ⇒ Object

Disable logging for the given class.



195
196
197
198
# File 'lib/console/filter.rb', line 195

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

#enable(subject, level = self.class::MINIMUM_LEVEL) ⇒ Object

Enable specific log level for the given class.



187
188
189
190
# File 'lib/console/filter.rb', line 187

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

#enabled?(subject, level = self.class::MINIMUM_LEVEL) ⇒ Boolean

Whether logging is enabled for the given subject and log level.

You can enable and disable logging for classes. This function checks if logging for a given subject is enabled.

Returns:

  • (Boolean)


172
173
174
175
176
177
178
179
180
181
182
# File 'lib/console/filter.rb', line 172

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

#filter(subject, level) ⇒ Object

Filter log messages based on the subject and log level.

You must provide the subject’s class, not an instance of the class.



157
158
159
160
161
162
163
# File 'lib/console/filter.rb', line 157

def filter(subject, level)
  unless subject.is_a?(Module)
    raise ArgumentError, "Expected a class, got #{subject.inspect}"
  end
  
  @subjects[subject] = level
end

#off!Object

Disable all logging.



142
143
144
# File 'lib/console/filter.rb', line 142

def off!
  @level = self.class::MAXIMUM_LEVEL + 1
end

#The output destination.=(outputdestination. = (value)) ⇒ Object



108
# File 'lib/console/filter.rb', line 108

attr_accessor :output

#verbose!(value = true) ⇒ Object

Set verbose output (enable by default with no arguments).



136
137
138
139
# File 'lib/console/filter.rb', line 136

def verbose!(value = true)
  @verbose = value
  @output.verbose!(value)
end

#Whether to enable verbose output.=(toenableverboseoutput. = (value)) ⇒ Object



111
# File 'lib/console/filter.rb', line 111

attr :verbose

#with(level: @level, verbose: @verbose, **options) ⇒ Object

Create a new log filter with the given options, from an existing log filter.



99
100
101
102
103
104
105
# File 'lib/console/filter.rb', line 99

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