Filtering
Filtering is useful to reduce log output for excessive log messages. It is can be used for example where a Library is logging messages and we do not want to modify that library.
Additionally a filter can be used to filter out or in specific log messages to certain appenders. For example, only log messages from specific classes or with specific content to a specific appender.
Appender specific log filtering
Filters can be supplied to most appenders on the initializer, or can be setup
by using the accessors. A filter is either a regular expression matching what
messages to include, or is a Proc (Block of code) that returns true
to allow the
message to be logged, or false
indicating the message should not be logged.
When using a Proc, it is passed the entire Log Struct
.
For the format of the Log Struct
, see Log Struct
Example. Using a regular expression filter, log everything to one file, log only messages from a particular class to the second file:
require "semantic_logger"
# Log everything to development.log
SemanticLogger.add_appender(file_name: "development.log")
# Log everything except any messages from "MyClass" to summary.log
appender = SemanticLogger.add_appender(
file_name: "my_class.log",
# Filter out log entries where the class name is "MyClass"
filter: /MyClass/
)
logger1 = SemanticLogger["MyClass"]
logger1.info "This will _only_ be logged to "my_class.log""
logger2 = SemanticLogger["OtherClass"]
logger2.info "This will be logged to development.log and 'my_class.log'"
Example Using a Proc filter, log everything to one file, log everything except messages from a particular class to the second file:
require "semantic_logger"
# Log everything to development.log
SemanticLogger.add_appender(file_name: "development.log")
# Log all messages from "MyClass" to summary.log
appender = SemanticLogger.add_appender(
file_name: "my_class.log",
# Filter out log entries where the class name is _not_ "MyClass"
filter: -> log { log.name != "MyClass" }
)
logger1 = SemanticLogger["MyClass"]
logger1.info "This will _not_ be logged to summary.log"
logger2 = SemanticLogger["OtherClass"]
logger2.info "This will be logged to summary.log"
Example using filter to change log messages.
Resque logs the entire job payload which may contain private information. Strip out the job data since from the following log messages:
- log “got: #{job.inspect}”
- log “done: #{job.inspect}”
Resque.logger.filter = -> log do
if (log.name == "Resque") && (match = log.message.to_s.match(/\A(got|done): /))
log.message = match[1]
end
# After the message has been modified, make sure it is logged:
true
end
Logger specific filtering
Filtering can be applied at the logger level, allowing the filtering to only apply to users of that specific logger instance. This is useful to reduce logging from a library when it allows its logger to be replaced.
For example, filter out all the *** Checking
log messages from Resque:
logger = SemanticLogger[Resque]
# Filter out all messages containing the text beginning with "*** Checking"
logger.filter = Proc.new {|log| log.message !~ /\A\*\*\* Checking/ }
# Give Resque its own logger with the custom filter applied to reduce its verbosity
# when logging to all registered appenders
Resque.logger = logger