README.md in timber-2.1.1 vs README.md in timber-2.1.2
- old
+ new
@@ -1,147 +1,44 @@
-# 🌲 Timber - Simple Ruby Structured Logging
+# 🌲 Timber - Log Better. Solve Problems Faster.
[![ISC License](https://img.shields.io/badge/license-ISC-ff69b4.svg)](LICENSE.md)
+[![Hex.pm](https://img.shields.io/hexpm/v/timber.svg?maxAge=18000=plastic)](https://hex.pm/packages/timber)
+[![Documentation](https://img.shields.io/badge/hexdocs-latest-blue.svg)](https://hexdocs.pm/timber/index.html)
[![Build Status](https://travis-ci.org/timberio/timber-ruby.svg?branch=master)](https://travis-ci.org/timberio/timber-ruby)
-[![Code Climate](https://codeclimate.com/github/timberio/timber-ruby/badges/gpa.svg)](https://codeclimate.com/github/timberio/timber-ruby)
-[![View docs](https://img.shields.io/badge/docs-viewdocs-blue.svg?style=flat-square "Viewdocs")](http://www.rubydoc.info/github/timberio/timber-ruby)
-* [Timber website](https://timber.io)
-* [Timber docs](https://timber.io/docs)
-* [Library docs](http://www.rubydoc.info/github/timberio/timber-ruby)
-* [Support](mailto:support@timber.io)
-
-
## Overview
-Timber solves ruby structured logging so you don't have to. Go from raw text logs to rich
-structured events in seconds. Spend more time focusing on your app and less time
-focusing on logging.
+[Timber](https://timber.io) is a logging platform with one major difference: Instead of parsing,
+which relies on unreadable, unpredictable, hard to use text logs, Timber integrates directly with
+your application, producing rich structured events containing metadata and context you couldn't
+capture otherwise. It fundamentally changes the way you use your logs.
-1. **Easy setup.** - `bundle exec timber install`, [get setup in seconds](#installation).
+1. [**Easy setup** - `mix timber.install`](#installation)
+2. [**Seamlessly integrates with popular libraries and frameworks**](#jibber-jabber)
+3. [**Modern fast console, designed specifically for your application**](#the-timber-console)
-2. **Automatically structures yours logs.** - Third-party and in-app logs are all structured
- in a consistent format. See [how it works](#how-it-works) below.
-3. **Seamlessly integrates with popular libraries and frameworks.** - Rails, Rack, Devise,
- Omniauth, etc. [Automatically captures user context, HTTP context, and event data.](#third-party-integrations)
-
-4. **Pairs with a modern structured-logging console.** - Designed specifically for structured data,
- hosted, instantly usable, tail users, trace requests.
- [Checkout the docs](https://timber.io/docs/app/tutorials/).
-
-
## Installation
-1. In `Gemfile`, add the `timber` gem:
+1. In your `Gemfile`, add the `timber` gem:
```ruby
- gem 'timber', '~> 2.0'
+ gem 'timber', '~> 2.1'
```
2. In your `shell`, run `bundle install`
3. In your `shell`, run `bundle exec timber install`
-## How it works
-
-Let's start with an example. Timber turns this production log line:
-
-```
-I, [2017-06-04T18:04:53.653812 #42348] INFO -- : [my.host.com] [df88dbaa-50fd-4178-85d7-d66279ea33b6] [192.32.23.12] [bfa8242cd9733bf0211e334be203f0d0] Sent 200 in 45.2ms
-```
-
-Into a structured [`http_server_response` event](https://timber.io/docs/ruby/events-and-context/http-server-response-event/).
-
-```
-Sent 200 in 45.2ms @metadata {"dt": "2017-02-02T01:33:21.154345Z", "level": "info", "context": {"http": {"method": "GET", "path": "/path", "remote_addr": "192.32.23.12", "request_id": "df88dbaa-50fd-4178-85d7-d66279ea33b6"}, "session": {"id": "bfa8242cd9733bf0211e334be203f0d0"}, "system": {"hostname": "my.host.com", "pid": "254354"}, "user": {"id": 1, "name": "Ben Johnson", "email": "bens@email.com"}}, "event": {"http_server_response": {"status": 200, "time_ms": 45.2}}}
-```
-
-Notice that instead of completely replacing your log messages,
-Timber _augments_ your logs with structured metadata. Turning them into
-[rich events with context](https://timber.io/docs/ruby/events-and-context) without sacrificing
-readability. And you have [complete control over which data is captured](#configuration).
-
-This is all accomplished by using the
-[Timber::Logger](http://www.rubydoc.info/github/timberio/timber-ruby/Timber/Logger):
-
-```ruby
-logger = Timber::Logger.new(STDOUT)
-logger.info("Sent 200 in 45.2ms")
-```
-
-Here's a better look at the metadata:
-
-```js
-{
- "dt": "2017-02-02T01:33:21.154345Z",
- "level": "info",
- "context": {
- "http": {
- "method": "GET",
- "path": "/path",
- "remote_addr": "192.32.23.12",
- "request_id": "abcd1234"
- },
- "session": {
- "id": "bfa8242cd9733bf0211e334be203f0d0"
- },
- "system": {
- "hostname": "1.server.com",
- "pid": "254354"
- },
- "user": { // user identifiable logs :O
- "id": 1,
- "name": "Ben Johnson",
- "email": "bens@email.com"
- },
- },
- "event": {
- "http_server_response": {
- "status": 200,
- "time_ms": 45.2
- }
- }
-}
-```
-
-This structure isn't arbitrary either, it follows the
-[simple log event JSON schema](https://github.com/timberio/log-event-json-schema), which
-formalizes the data structure, creates a contract with downstream consumers, and
-improves stability.
-
-So what can you do with this data?
-
-1. [**Tail a user** - `user.id:1`](https://timber.io/docs/app/tutorials/tail-a-user/)
-2. [**Trace a request** - `http.request_id:abcd1234`](https://timber.io/docs/app/tutorials/view-in-request-context/)
-3. **Narrow by host** - `system.hostname:1.server.com`
-4. **View slow responses** - `http_server_response.time_ms:>=1000`
-5. **Filter by log level** - `level:error`
-6. **Quickly find exceptions** - `is:exception`
-
-For a complete overview, see the [Timber for Ruby docs](https://timber.io/docs/ruby/overview/).
-
-
-## Third-party integrations
-
-1. **Rails**: Structures ([HTTP requests](https://timber.io/docs/ruby/events-and-context/http-server-request-event/), [HTTP respones](https://timber.io/docs/ruby/events-and-context/http-server-response-event/), [controller calls](https://timber.io/docs/ruby/events-and-context/controller-call-event/), [template renders](https://timber.io/docs/ruby/events-and-context/template-render-event/), and [sql queries](https://timber.io/docs/ruby/events-and-context/sql-query-event/)).
-2. **Rack**: Structures [exceptions](https://timber.io/docs/ruby/events-and-context/exception-event/), captures [HTTP context](https://timber.io/docs/ruby/events-and-context/http-context/), captures [user context](https://timber.io/docs/ruby/events-and-context/user-context/), captures [session context](https://timber.io/docs/ruby/events-and-context/session-context/).
-3. **Devise, Omniauth, Clearance**: captures [user context](https://timber.io/docs/ruby/events-and-context/user-context/)
-5. **Heroku**: Captures [release context](https://timber.io/docs/ruby/events-and-context/release-context/) via [Heroku dyno metadata](https://devcenter.heroku.com/articles/dyno-metadata).
-
-...and more. Timber will continue to evolve and support more libraries.
-
-
## Usage
<details><summary><strong>Basic logging</strong></summary><p>
Use the `Timber::Logger` just like you would `::Logger`:
```ruby
-logger = Timber::Logger.new(STDOUT)
logger.info("My log message") # use warn, error, debug, etc.
# => My log message @metadata {"level": "info", "context": {...}}
```
@@ -153,19 +50,18 @@
Custom events allow you to extend beyond events already defined in
the [`Timber::Events`](lib/timber/events) namespace.
```ruby
-logger = Timber::Logger.new(STDOUT)
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](https://app.timber.io) use the query: `type:payment_rejected` or `payment_rejected.amount:>100`.
-* See more details on our [custom events docs page](https://timber.io/docs/ruby/custom-events/)
+* See more details on our [custom events docs page](https://timber.io/docs/ruby/usage/custom-events/)
---
</p></details>
@@ -175,21 +71,20 @@
This is how a query like `context.user.id:1` can show you all logs generated by that user.
Custom contexts allow you to extend beyond contexts already defined in
the [`Timber::Contexts`](lib/timber/contexts) namespace.
```ruby
-logger = Timber::Logger.new(STDOUT)
logger.with_context(build: {version: "1.0.0"}) do
logger.info("My log message")
end
# => My log message @metadata {"level": "info", "context": {"build": {"version": "1.0.0"}}}
```
* Notice the `:build` root key. Timber will classify this context as such.
* In the [Timber console](https://app.timber.io) use queries like: `build.version:1.0.0`
-* See more details on our [custom contexts docs page](https://timber.io/docs/ruby/custom-contexts/)
+* See more details on our [custom contexts docs page](https://timber.io/docs/ruby/usage/custom-contexts/)
---
</p></details>
@@ -202,11 +97,10 @@
Here's a timing example. Notice how Timber automatically calculates the time and adds the timing
to the message.
```ruby
-logger = Timber::Logger.new(STDOUT)
timer = Timber::Timer.start
# ... code to time ...
logger.info("Processed background job", background_job: {time_ms: timer})
# => Processed background job in 54.2ms @metadata {"level": "info", "event": {"background_job": {"time_ms": 54.2}}}
@@ -219,11 +113,10 @@
```
Lastly, metrics aren't limited to timings. You can capture any metric you want:
```ruby
-logger = Timber::Logger.new(STDOUT)
logger.info("Credit card charged", credit_card_charge: {amount: 123.23})
# => Credit card charged @metadata {"level": "info", "event": {"credit_card_charge": {"amount": 123.23}}}
```
@@ -329,11 +222,10 @@
Simply set the formatter like you would with any other logger:
```ruby
# This is set in your various environment files
-logger = Timber::Logger.new(STDOUT)
logger.formatter = Timber::Logger::JSONFormatter.new
```
Your options are:
@@ -405,62 +297,70 @@
</p></details>
## Jibber-Jabber
-<details><summary><strong>Which events and contexts does Timber capture for me?</strong></summary><p>
+<details><summary><strong>Which log events does Timber structure for me?</strong></summary><p>
-Out of the box you get everything in the
-[`Timber::Events`](http://www.rubydoc.info/github/timberio/timber-ruby/Timber/Events) namespace.
+Out of the box you get everything in the [`Timber.Events`](lib/timber/events) namespace.
-We also add context to every log, everything in the
-[`Timber::Contexts`](http://www.rubydoc.info/github/timberio/timber-ruby/Timber/Contexts)
+We also add context to every log, everything in the [`Timber.Contexts`](lib/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. It's
-how Timber is able to accomplished tailing users (`context.user.id:1`).
+was written. It is included in every log line. Think of it like join data for your logs.
-Lastly, you can checkout how we capture these events in
-[`Timber::Integrations`](lib/timber/integrations).
-
---
</p></details>
-<details><summary><strong>Won't this increase the size of my log data?</strong></summary><p>
+<details><summary><strong>What about my current log statements?</strong></summary><p>
-Yes, but it's no different than adding any other useful data to your logs, such as
-[tags](http://api.rubyonrails.org/classes/ActiveSupport/TaggedLogging.html). A few
-of things to note:
+They'll continue to work as expected. Timber adheres strictly to the default `Logger` interface
+and will never deviate in *any* way.
-1. Timber generally _reduces_ the amount of logs your app generates, trading quality for quantity.
- It does so by providing options to consolidate request / response logs, template logs, and
- even silence logs that are not of value to you. (see [configuration](#configuration) for examples).
-2. Timber lets you pick exactly which events and contexts you want.
- (see [configuration](#configuration) for examples)
-3. Your logging provider should be compressing your data and charging you accordingly. Log data
- is notoriously repetitive, and the context Timber generates is repetitive.
- Because of compression we've seen somes apps only incur a ~15% increase in data size.
+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](#usage).
-Finally, log what is useful to you. Quality over quantity certainly applies to logging.
+</p></details>
----
+<details><summary><strong>When to use metadata or events?</strong></summary><p>
-</p></details>
+At it's basic level, both metadata and events serve the same purpose: they add structured
+data to your logs. And anyone that's implemented structured logging know's this can quickly get
+out of hand. This is why we created events. Here's how we recommend using them:
-<details><summary><strong>What about my current log statements?</strong></summary><p>
+1. Use `events` when the log cleanly maps to an event that you'd like to alert on, graph, or use
+ in a meaningful way. Typically something that is core to your business or application.
+2. Use metadata for debugging purposes; when you simply want additional insight without
+ polluting the message.
-They'll continue to work as expected. Timber adheres to the default `::Logger` interface.
-Your previous logger calls will work as they always do. Just swap in `Timber::Logger` and
-you're good to go.
+### Example 1: Logging that a payment was rejected
-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](#usage).
+This is clearly an event that is meaningful to your business. You'll probably want to alert and
+graph this data. So let's log it as an official event:
+```ruby
+logger.info("Payment rejected", payment_rejected: {customer_id: "xiaus1934", amount: 1900, currency: "USD"})
+```
+
+### Example 2: Logging that an email was changed
+
+This is definitely log worthy, but not something that is core to your business or application.
+Instead of an event, use metadata:
+
+```ruby
+logger.info("Email successfully changed", old_email: old_email, new_email: new_email)
+```
+
---
</p></details>
----
+## The Timber Console
+
+[![Timber Console](http://files.timber.io/images/readme-interface7.gif)](https://app.timber.io)
+
+## Your Moment of Zen
+
<p align="center" style="background: #221f40;">
-<a href="http://github.com/timberio/timber-elixir"><img src="http://files.timber.io/images/ruby-library-readme-log-truth.png" height="947" /></a>
-</p>
\ No newline at end of file
+<a href="http://github.com/timberio/timber-ruby"><img src="http://files.timber.io/images/readme-log-truth.png" height="947" /></a>
+</p>