To write your own log appender it should meet the following requirements:
- Inherit from
- In the initializer connect to the resource being logged to
- Implement #log(log) which needs to write to the relevant resource
- Implement #flush if the resource can be flushed
- Write a test for the new appender
The #log method takes the
Log Struct as a parameter.
For the format of the
Log Struct, see Log Struct
Basic outline for an Appender:
require "semantic_logger" class SimpleAppender < SemanticLogger::Subscriber def initialize(level=nil, &block) # Set the log level and formatter if supplied super(level, &block) end # Display the log struct and the text formatted output def log(log) # Ensure minimum log level is met, and check filter return false if (level_index > (log.level_index || 0)) || !include_message?(log) # Display the raw log structure p log # Display the formatted output puts formatter.call(log) end # Optional def flush puts "Flush :)" end end
Sample program calling the above appender:
SemanticLogger.default_level = :trace # Log to file dev.log SemanticLogger.add_appender(file_name: "dev.log") # Also log the above sample appender SemanticLogger.add_appender(appender: SimpleAppender.new) logger = SemanticLogger["Hello"] logger.info "Hello World"
Look at the existing appenders for good examples
To have your custom appender included in the standard list of appenders, submit it along with complete working tests. See the Graylog Appender Test for an example.
This section introduces the internal design of Semantic Logger, which will be helpful for anyone that wants to contribute changes for others in the community to take advantage of.
Log message flow diagram
Shows how log messages events are emitted from the various log instances, placed in the in-memory queue, and then written to one or more appenders on a separate thread.