🌲 Timber - Log Better. Solve Problems Faster.

ISC License CircleCI Code Climate View docs

Overview

Timber for Ruby is an optional upgrade you can install for Ruby apps on the Timber.io logging platform. Instead of completely replacing your log messages, Timber automatically augments your logs with JSON metadata. Essentially turning them into rich events with context. This preserves the readability of your logs while still dramatically improving the quality of your data. The end result: better logging and faster problem solving.

How it works

For example, Timber turns this familiar raw text log:

Sent 200 in 45.ms

Into a rich http_server_response event.

Sent 200 in 45.2ms  {"dt": "2017-02-02T01:33:21.154345Z", "level": "info", "context": {"user": {"id": 1, "name": "Ben Johnson"}, "http": {"method": "GET", "host": "timber.io", "path": "/path", "request_id": "abcd1234"}}, "event": {"http_server_response": {"status": 200, "time_ms": 45.2}}}

In the Timber console simply click the line to view this metdata. Moreover, this data allows you to run powerful queries like:

  1. context.request_id:abcd1234 - View all logs generated for a specific request.
  2. context.user.id:1 - View logs generated by a specific user.
  3. type:http_server_response - View specific events (exceptions, sql queries, etc)
  4. http_server_response.time_ms:>=1000 - View slow responses with the ability to zoom out and view them in context (request, user, etc).
  5. level:info - Levels in your logs!

For a complete overview, see the Timber for Ruby docs.

Installation

  1. In Gemfile, add the timber gem:

    gem 'timber', '~> 2.0'
    
  2. In your shell, run bundle install

  3. In your shell, run bundle exec timber install

Configuration

All configuration options can be seen in the Timber::Config docs. Here are a few popular options:

  1. config.timber.format =
* `:default` - This is the default. It's the original, default, unchanged log messages.

* `:lograge` - Works exactly like [lograge](https://github.com/roidrage/lograge), except Timber's
  additional context and  is also appended. Lograge++.

Usage

Basic logging

Use Logger as normal:

logger.info("My log message")

# => My log message @metadata {"level": "info", "context": {...}}

Timber will never deviate from the public ::Logger interface in any way.


Custom events

Custom events allow you to extend beyond events already defined in the Timber::Events namespace.

Logger.warn "Payment rejected", payment_rejected: {customer_id: "abcd1234", amount: 100, reason: "Card expired"}

# => Payment rejected @metadata {"level": "warn", "event": {"payment_rejected": {"customer_id": "abcd1234", "amount": 100, "reason": "Card expired"}}, "context": {...}}
  • Notice the :payment_rejected root key. Timber will classify this event as such.
  • In the Timber console use the query: type:payment_rejected or payment_rejected.amount:>100.
  • See more details on our custom events docs page

Custom contexts

Context is additional data shared across log lines. Think of it like log join data. Custom contexts allow you to extend beyond contexts already defined in the Timber::Contexts namespace.

Timber::CurrentContext.with({build: {version: "1.0.0"}}) do
  logger.info("My log message")
end

# => My log message @metadata {"level": "info", "context": {"build": {"version": "1.0.0"}}}

Metrics

Logging metrics is accomplished by logging custom events. Please see our metrics docs page for a more detailed explanation with examples.

Jibber-Jabber

Which log events does Timber structure for me?

Out of the box you get everything in the Timber::Events namespace.

We also add context to every log, everything in the Timber::Contexts namespace. Context is structured data representing the current environment when the log line was written. It is included in every log line. Think of it like join data for your logs.


What about my current log statements?

They'll continue to work as expected. Timber adheres to the default Logger interface. Your previous logger calls will work as they always do.

In fact, traditional log statements for non-meaningful events, debug statements, etc, are encouraged. In cases where the data is meaningful, consider logging a custom event.

How is Timber different?

  1. It's just better logging. Nothing beats well structured raw data. And that's exactly what Timber aims to provide. There are no agents, special APIs, or proprietary data sets that you can't access.
  2. Improved log data quality. Instead of relying on parsing alone, Timber ships libraries that structure and augment your logs from within your application. Improving your log data at the source.
  3. Human readability. Timber augments your logs without sacrificing human readability. For example: log message @metadata {...}. And when you view your logs in the Timber console, you'll see the human friendly messages with the ability to view the associated metadata.
  4. Long retention. Logging is notoriously expensive with low retention. Timber offers 6 months of retention by default with sane prices.
  5. Normalized schema. Have multiple apps? All of Timber's libraries adhere to our JSON schema. This means queries, alerts, and graphs for your ruby app can also be applied to your elixir app (for example).