Peter Marton
Backend Engineer @ SSP
And why do we need it?
core ruby Logger
Logging
Log4r
Cabin
severity, datetime, progname, msg
require 'logger'
log = Logger.new(STDOUT)
log.level = Logger::WARN
log.info("Program started")
begin
unless line =~ /^(\w+) = (.*)$/
log.error("Line in wrong format: #{line}")
end
rescue => err
log.fatal("Caught exception; exiting")
log.fatal(err)
end
# [2016-06-26T19:55:03.317327 #16323] ERROR -- : Line in wrong format: nyehh
Supports multiple locations (appenders)
class FirstClass
def initialize
@logger = Logging.logger[self]
@logger.add_appenders(Logging.appenders.stdout, Logging.appenders.file('example.log'))
end
def some_method
@logger.debug "some method was called on #{self.inspect}"
end
end
Custom levels from configuration
Somewhat more advanced than Logging, but similar
XML and YAML configuration
Far less advanced than log4j
"I want context and structured data because logging with printf makes it hard to read later."
API encourages tracking metrics, latencies, etc
It's self-described as an experiment and does not feel prod ready
The whole API feels a little cumbersome and "too different"
Very similar premise to what we were trying to achieve
Poorly documented too
@logger = Cabin::Channel.new
rubylog = Logger.new(STDOUT) # ruby's stlib logger
@logger.subscribe(rubylog)
context = @logger.context()
context[:foo] = "Hello"
context[:example] = 100
@logger.info("Bar")
context.clear()
# [2011-10-11T01:00:57.993200 #1209] INFO -- :
{:timestamp="2011-10-11T01:00:57.992353-0700", :foo="Hello",
:example=100, :message="Bar", :level=:info}
Builds on top of core ruby Logger
Block support as in core ruby Logger
Outputs JSON
A machine friendly logging library for ruby
Support for events and metrics
{
"timestamp":"2015-11-16 16:47:42 UTC",
"level":"INFO",
"logger":"your-logger-name",
"event":{
"name":"event-name",
"arbitrary":"context",
"add_what":"you_need",
"monitored":true,
"title":"Title of the event",
"text":"A longer description."},
"metrics":[
{
"name":"metric-name",
"value":34.35,
"type":"counter"
},
{
"name":"loglines",
"value":1234535,
"type":"counter"
}],
"message":"Human readable old-school logline"
}
require 'logr'
class YourClass
def self.logger
@logger ||= Logr::Logger.new('your-logger-name')
end
.
.
.
# A complex event that you want to monitor and has metrics associated
YourClass.logger.event('event-name', arbitrary: 'context', add_what: 'you_need')
.monitored('Title of the event', 'A longer description.')
.metric('metric-name', 34.35)
.metric('loglines', 1234535, type: 'counter')
.info('Human readable old-school logline')
# A simple logline
YourClass.logger.warn('Oh-oh something is fishy!')
end
http://www.codeproject.com/Articles/42354/The-Art-of-Logging
https://github.com/sspinc/logr