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