module TeeLogger::Filter
Constants
- DEFAULT_FILTER_WORDS
The default words to filter. It's up to each individual filter to decide what to do when they encounter a word, but these are the words the filters should process. Note that they can be strings or regular expressions. Regular expressions should by and large not be anchored to the beginning or end of strings.
- REDACTED_WORD
Word to use in place of original values
Public Instance Methods
apply_filters(*args)
click to toggle source
Applies all registered filters.
# File lib/teelogger/filter.rb, line 106 def apply_filters(*args) # Pre-process filter words: we need to have regular expressions everywhere words = [] filter_words.each do |word| if word.is_a? Regexp words << word else words << Regexp.new(word.to_s) end end # We instanciate each filter once per application, and store the instnaces # in a cache for that duration. filter_cache = {} # Pass state on to apply_filters_internal state = { :words => words, :filter_cache => filter_cache, :filters => self, } return apply_filters_internal(state, *args) end
apply_filters_internal(state, *args)
click to toggle source
Implementation of apply_filters
that doesn't initialize state, but carries it over. Used internally only.
# File lib/teelogger/filter.rb, line 134 def apply_filters_internal(state, *args) filtered_args = args # Iterate through filters registered_filters.each do |window, window_filters| # Determine actual window size window_size = [window, filtered_args.size].min # Process each window so that elements are updated in-place. This # means we'll start at index 0 and process up to window_size elements. idx = 0 while (idx + window_size - 1) < filtered_args.size # We need to use *one* argument to determine whether the filter # type applies. The current strategy is to match the first argument # only, and let the filter cast to other types if necessary. first_arg = filtered_args[idx] window_filters.each do |class_match, type_filters| # We process with these type filters if first_arg matches the # class_match. if not first_arg.is_a? class_match next end # Now process with the given filters. type_filters.each do |filter| # XXX Do not turn this into a one-liner, or we'll instanciate # filters without using them. filter_instance = state[:filter_cache].fetch(filter, nil) if filter_instance.nil? filter_instance = filter.new(state) state[:filter_cache][filter] = filter_instance end # Single item windows need to be processed a bit differently from # multi-item windows. tuple = filtered_args[idx..idx + window_size - 1] filtered = filter_instance.process(*tuple) # Sanity check result if filtered.size != tuple.size raise "Filter #{filter} added or removed items to the log; don't know how to process!" end filtered.each_with_index do |item, offset| filtered_args[idx + offset] = item end end # type_filters.each end # window_filters.each # Advance to the next window idx += 1 end # each window end # all registered filters return filtered_args end
filter_words()
click to toggle source
Filter
words
# File lib/teelogger/filter.rb, line 29 def filter_words @filter_words ||= DEFAULT_FILTER_WORDS return @filter_words end
filter_words=(arg)
click to toggle source
# File lib/teelogger/filter.rb, line 34 def filter_words=(arg) # Coerce into array begin arr = [] arg.each do |item| arr << item end @filter_words = arr rescue NameError, NoMethodError raise "Can't set filter words, not iterable: #{arg}" end end
load_filters(*args)
click to toggle source
Load all built-in filters.
# File lib/teelogger/filter.rb, line 50 def load_filters(*args) require_rel 'filters' ::TeeLogger::Filter.constants.collect {|const_sym| ::TeeLogger::Filter.const_get(const_sym) }.each do |filter| begin register_filter(filter) if not ENV['TEELOGGER_VERBOSE'].nil? and ENV['TEELOGGER_VERBOSE'].to_i > 0 puts "Registered filter #{filter}." end rescue StandardError => err if not ENV['TEELOGGER_VERBOSE'].nil? and ENV['TEELOGGER_VERBOSE'].to_i > 0 puts "Not registering filter: #{err}" end end end end
register_filter(filter)
click to toggle source
Expects a class, registers the class for use by the filter function
# File lib/teelogger/filter.rb, line 78 def register_filter(filter) # Sanity checks/register filter if filter.class != Class raise "Ignoring '#{filter}', not a class." end if not filter < FilterBase raise "Class '#{filter}' is not derived from FilterBase." end begin window = filter::WINDOW_SIZE.to_i window_filters = registered_filters.fetch(window, {}) filter::FILTER_TYPES.each do |type| type_filters = window_filters.fetch(type, []) type_filters.push(filter) unless type_filters.include?(filter) window_filters[type] = type_filters end registered_filters[window] = window_filters rescue NameError, NoMethodError raise "Class '#{filter}' is missing a FILTER_TYPES Array or a WINDOW_SIZE Integer." end end
registered_filters()
click to toggle source
Returns all registered filters.
# File lib/teelogger/filter.rb, line 70 def registered_filters # Initialize if it doesn't exist @filters ||= {} return @filters end