Awesome
DEPRECATED: Stripe no longer support Chalk::Log
Chalk::Log
Chalk::Log
adds a logger object to any class, which can be used for
unstructured or semi-structured logging. Use it as follows:
class A
include Chalk::Log
end
A.log.info('hello', key: 'value')
#=> [2013-06-18 22:18:28.314756] [64682] hello: key="value"
The output is both human-digestable and easily parsed by log indexing systems such as Splunk or Logstash.
It can also pretty-print exceptions for you:
module A
include Chalk::Log
end
begin
raise "hi"
rescue => e
end
A.log.error('Something went wrong', e)
#=> Something went wrong: hi (RuntimeError)
# (irb):8:in `irb_binding'
# /Users/gdb/.rbenv/versions/1.9.3-p362/lib/ruby/1.9.1/irb/workspace.rb:80:in `eval# /Users/gdb/.rbenv/versions/1.9.3-p362/lib/ruby/1.9.1/irb/workspace.rb:80:in `evaluate'
# /Users/gdb/.rbenv/versions/1.9.3-p362/lib/ruby/1.9.1/irb/context.rb:254:in `evaluate'
# /Users/gdb/.rbenv/versions/1.9.3-p362/lib/ruby/1.9.1/irb.rb:159:in `block (2 levels) in eval_input'
# [...]
The log methods accept a message and/or an exception and/or an info hash (if multiple are passed, they must be provided in that order). The log methods will never throw an exception, but will instead print an log message indicating they had a fault.
Overview
Including Chalk::Log
creates a log
method as both a class an
instance method, which returns a class-specific logger.
By default, it tags loglines with auxiliary information: a microsecond-granularity timestamp, the PID, and an action_id (which should tie together all lines for a single logical action in your system, such as a web request).
You can turn off tagging, or just turn off timestamping, through appropriate configatron settings (see config.yaml).
There are also two LSpace
dynamic settings available:
LSpace[:action_id]
: Set the action_id dynamically for this action. (This is used automatically by things likeChalk::Web
which have a well-defined action.)LSpace[:'chalk.log.disabled']
: Disable all logging.
You can use LSpace
settings as follows:
class A; include Chalk::Log; end
foo = A.new
LSpace.with(action_id: 'request-123') do
foo.log.info('Test')
#=> [2014-05-26 01:12:28.485822] [47325|request-123] Test
end
Log methods
Chalk::Log
provides five log levels:
debug, info, warn, error, fatal
Inheritance
Chalk::Log
makes a heroic effort to ensure that inclusion chaining
works, so you can do things like:
module A
include Chalk::Log
end
module B
include A
end
class C
include B
end
and still have C.log
and C.new.log
work. (Normally you'd expect
for the class-method version to be left behind.)
Best practices
- You should never use string interpolation in your log message. Instead, always use the structured logging keys. So for example:
# Bad
log.info("Just printed #{lines.length} lines")
# Good
log.info("Printed", lines: lines.length)
-
Don't end messages with a punctuation --
Chalk::Log
will automatically add a colon if an info hash is provided; if not, it's fine to just end without trailing punctutaion. Case in point -
In most projects, you'll find most of your classes start including
Chalk::Log
-- it's pretty cheap to add it, and it's quite lightweight to use. (In contrast, there's no good way to autoinclude it, since that would likely break many classes which aren't expecting a magicallog
method to appear.)
Limitations
Chalk::Log
is not very configurable. Our usage at Stripe tends to be
fairly opinionated, so there hasn't been much demand for increased
configurability. We would be open to making it less rigid,
however. (In any case, under the hood Chalk::Log
is just using the
logging
gem, so if the need arises it wouldn't be hard to acquire
the full flexibility of logging
.)
Contributors
- Greg Brockman
- Andreas Fuchs
- Andy Brody
- Anurag Goel
- Evan Broder
- Nelson Elhage
- Brian Krausz
- Christian Anderson
- Jeff Balogh
- Jeremy Hoon
- Julia Evans
- Russell Davis
- Steven Noble