README.md in timber-1.1.0 vs README.md in timber-1.1.1

- old
+ new

@@ -53,20 +53,22 @@ with Timber specific code. It's just better logging. If you choose to stop using Timber, you can do so without consequence. 5. **Long term retention.** Timber is designed on modern big-data principles. As a result, we can offer 6+ months of retention at prices cheaper than alternatives offering <1 month. This allows you to unlock your logs for purposes beyond debugging. + --- </p></details> <details><summary><strong>What specifically does the Timber library do?</strong></summary><p> 1. Captures and structures your framework and 3rd party logs. (see next question) 2. Adds useful context to every log line. (see next question) -3. Provides a [framework for logging custom structured events](#what-about-custom-events). -4. Offers transport strategies to [send your logs](#send-your-logs) to the Timber service. +3. Allows you to easily add tags and timings to log. (see [Usage](#usage)) +4. Provides a framework for logging custom structured events. (see [Usage](#usage)) +5. Offers transport strategies to [send your logs](#send-your-logs) to the Timber service. --- </p></details> @@ -120,19 +122,19 @@ logger.info("My log message") # My log message @metadata {"level": "info", "context": {...}} ``` -Timber will never deviate from the public `::Logger` interface in *any* way. +Timber will *never* deviate from the public `::Logger` interface in *any* way. --- </p></details> <details><summary><strong>Tagging logs</strong></summary><p> -Need a quick and easy way to identify a log? Use tags!: +Need a quick way to identify logs? Use tags!: ```ruby logger.info(message: "My log message", tag: "tag") # My log message @metadata {"level": "info", "tags": ["tag"], "context": {...}} @@ -154,23 +156,55 @@ end # My log message @metadata {"level": "info", "tags": ["tag"], "context": {...}} ``` +* In the Timber console use the query: `tags:tag`. + +--- + </p></details> +<details><summary><strong>Timings, Durations, & Metrics</strong></summary><p> + +Timings allow you to easily capture one-off timings in your code; a simple +way to benchmark code execution: + +```ruby +start = Time.now +# ...my code to time... +time_ms = (Time.now - start) * 1000 +logger.info(message: "Task complete", tag: "my_task", time_ms: time_ms) + +# My log message @metadata {"level": "info", tags: ["my_task"], "time_ms": 54.2132, "context": {...}} +``` + +* In the Timber console use the query: `tags:my_task time_ms>500` +* The Timber console will also display this value inline with your logs. No need to include it + in the log message, but you certainly can if you'd prefer. + +--- + +</p></details> + + <details><summary><strong>Custom events</strong></summary><p> +Custom events can be used to structure information about events that are central +to your line of business like receiving credit card payments, saving a draft of a post, +or changing a user's password. You have 2 options to do this: + 1. Log a structured Hash (simplest) ```ruby Logger.warn message: "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": {...}} ``` - * The hash can *only* have a `:message` and "event type" key, where `:payment_rejected` is the event type in the above example. + * The hash can *only* have 2 keys: `:message` and "event type" key; `:payment_rejected` in this example. + * Timber will keyspace your event data by the event type key passed. 2. Log a Struct (recommended) Defining structs for your important events just feels oh so good :) It creates a strong contract with down stream consumers and gives you compile time guarantees. @@ -183,11 +217,11 @@ Logger.warn PaymentRejectedEvent.new("abcd1234", 100, "Card expired") # Payment rejected @metadata {"level": "warn", "event": {"payment_rejected": {"customer_id": "abcd1234", "amount": 100, "reason": "Card expired"}}, "context": {...}} ``` -* `:type` is how Timber classifies the event, it creates a namespace for the data you send. +* In the Timber console use queries like: `payment_rejected.customer_id:xiaus1934` or `payment_rejected.amount>100` * For more advanced examples see [`Timber::Logger`](lib/timber.logger.rb). * Also, notice there is no mention of Timber in the above code. Just plain old logging. #### What about regular Hashes, JSON, or logfmt? @@ -259,10 +293,10 @@ ``` ## Setup -<details><summary><strong>Rails >= 3.0</strong></summary><p> +<details><summary><strong>Rails (all versions, including edge)</strong></summary><p> *Replace* any existing `config.logger=` calls in `config/environments/production.rb` with: ```ruby # config/environments/production.rb \ No newline at end of file