timber 1.1.14 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +4 -2
- data/.travis.yml +47 -0
- data/Gemfile +1 -28
- data/README.md +83 -298
- data/bin/timber +13 -0
- data/gemfiles/rails-3.0.gemfile +5 -0
- data/gemfiles/rails-3.1.gemfile +5 -0
- data/gemfiles/rails-3.2.gemfile +5 -0
- data/gemfiles/rails-4.0.gemfile +9 -0
- data/gemfiles/rails-4.1.gemfile +9 -0
- data/gemfiles/rails-4.2.gemfile +9 -0
- data/gemfiles/rails-5.0.gemfile +9 -0
- data/gemfiles/rails-edge.gemfile +7 -0
- data/lib/timber.rb +7 -7
- data/lib/timber/cli.rb +72 -0
- data/lib/timber/cli/api.rb +104 -0
- data/lib/timber/cli/application.rb +28 -0
- data/lib/timber/cli/install.rb +186 -0
- data/lib/timber/cli/io_helper.rb +58 -0
- data/lib/timber/cli/messages.rb +170 -0
- data/lib/timber/config.rb +47 -6
- data/lib/timber/contexts/http.rb +2 -2
- data/lib/timber/current_context.rb +1 -1
- data/lib/timber/event.rb +8 -0
- data/lib/timber/events.rb +2 -0
- data/lib/timber/events/controller_call.rb +12 -3
- data/lib/timber/events/exception.rb +4 -3
- data/lib/timber/events/http_client_request.rb +61 -0
- data/lib/timber/events/http_client_response.rb +47 -0
- data/lib/timber/events/http_server_request.rb +15 -23
- data/lib/timber/events/http_server_response.rb +9 -9
- data/lib/timber/events/sql_query.rb +2 -2
- data/lib/timber/events/template_render.rb +2 -2
- data/lib/timber/frameworks/rails.rb +31 -6
- data/lib/timber/integrations.rb +22 -0
- data/lib/timber/integrations/action_controller/log_subscriber.rb +25 -0
- data/lib/timber/integrations/action_controller/log_subscriber/timber_log_subscriber.rb +40 -0
- data/lib/timber/integrations/action_dispatch/debug_exceptions.rb +51 -0
- data/lib/timber/integrations/action_view/log_subscriber.rb +25 -0
- data/lib/timber/integrations/action_view/log_subscriber/timber_log_subscriber.rb +73 -0
- data/lib/timber/integrations/active_record/log_subscriber.rb +25 -0
- data/lib/timber/integrations/active_record/log_subscriber/timber_log_subscriber.rb +39 -0
- data/lib/timber/integrations/active_support/tagged_logging.rb +71 -0
- data/lib/timber/integrations/rack.rb +16 -0
- data/lib/timber/integrations/rack/exception_event.rb +28 -0
- data/lib/timber/integrations/rack/http_context.rb +25 -0
- data/lib/timber/integrations/rack/http_events.rb +46 -0
- data/lib/timber/integrations/rack/user_context.rb +59 -0
- data/lib/timber/integrations/rails/rack_logger.rb +49 -0
- data/lib/timber/integrator.rb +24 -0
- data/lib/timber/log_devices/http.rb +14 -21
- data/lib/timber/log_entry.rb +1 -1
- data/lib/timber/logger.rb +38 -12
- data/lib/timber/overrides.rb +9 -0
- data/lib/timber/overrides/lograge.rb +14 -0
- data/lib/timber/overrides/rails_server.rb +10 -0
- data/lib/timber/util.rb +2 -0
- data/lib/timber/util/active_support_log_subscriber.rb +13 -9
- data/lib/timber/util/http_event.rb +54 -0
- data/lib/timber/util/request.rb +44 -0
- data/lib/timber/version.rb +1 -1
- data/spec/README.md +5 -9
- data/spec/spec_helper.rb +1 -4
- data/spec/support/action_controller.rb +7 -3
- data/spec/support/active_record.rb +23 -19
- data/spec/support/rails.rb +56 -32
- data/spec/support/timber.rb +2 -3
- data/spec/support/webmock.rb +1 -0
- data/spec/timber/integrations/action_controller/log_subscriber_spec.rb +55 -0
- data/spec/timber/integrations/action_dispatch/debug_exceptions_spec.rb +53 -0
- data/spec/timber/integrations/action_view/log_subscriber_spec.rb +115 -0
- data/spec/timber/integrations/active_record/log_subscriber_spec.rb +46 -0
- data/spec/timber/integrations/rack/http_context_spec.rb +60 -0
- data/spec/timber/integrations/rails/rack_logger_spec.rb +58 -0
- data/spec/timber/logger_spec.rb +45 -9
- data/timber.gemspec +29 -3
- metadata +143 -46
- data/Appraisals +0 -41
- data/circle.yml +0 -33
- data/lib/timber/overrides/logger_add.rb +0 -38
- data/lib/timber/probe.rb +0 -23
- data/lib/timber/probes.rb +0 -23
- data/lib/timber/probes/action_controller_log_subscriber.rb +0 -20
- data/lib/timber/probes/action_controller_log_subscriber/log_subscriber.rb +0 -64
- data/lib/timber/probes/action_controller_user_context.rb +0 -52
- data/lib/timber/probes/action_dispatch_debug_exceptions.rb +0 -80
- data/lib/timber/probes/action_view_log_subscriber.rb +0 -20
- data/lib/timber/probes/action_view_log_subscriber/log_subscriber.rb +0 -69
- data/lib/timber/probes/active_record_log_subscriber.rb +0 -20
- data/lib/timber/probes/active_record_log_subscriber/log_subscriber.rb +0 -31
- data/lib/timber/probes/active_support_tagged_logging.rb +0 -63
- data/lib/timber/probes/rails_rack_logger.rb +0 -77
- data/lib/timber/rack_middlewares.rb +0 -12
- data/lib/timber/rack_middlewares/http_context.rb +0 -30
- data/spec/support/action_view.rb +0 -4
- data/spec/support/coveralls.rb +0 -2
- data/spec/support/simplecov.rb +0 -9
- data/spec/timber/overrides/logger_add_spec.rb +0 -26
- data/spec/timber/probes/action_controller_log_subscriber_spec.rb +0 -65
- data/spec/timber/probes/action_controller_user_context_spec.rb +0 -53
- data/spec/timber/probes/action_dispatch_debug_exceptions_spec.rb +0 -48
- data/spec/timber/probes/action_view_log_subscriber_spec.rb +0 -107
- data/spec/timber/probes/active_record_log_subscriber_spec.rb +0 -47
- data/spec/timber/probes/rails_rack_logger_spec.rb +0 -46
- data/spec/timber/rack_middlewares/http_context_spec.rb +0 -47
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: eab99caab83ef2be6496c0ad1db6d736cf54817f
|
4
|
+
data.tar.gz: dfdd212606d1ff42d908401e073ecf94a2cc2f72
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b7e9143deab1f3d58076b7c55600f8ee72d7a11f3d659c1494f6bef053d03e444555564e1a7a7977fc1ed8bfab8b2c5d53bd1d238d2934b5d23537e6f23da2e5
|
7
|
+
data.tar.gz: bb07cec849ea6a95a6480711b123612b1db91d6f4a59c23aac8c01b5f0b6ee921fc52ff43147a8123d9ad341b934055676e594cbc5ab4d1082268f423cd7d4f4
|
data/.gitignore
CHANGED
data/.travis.yml
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
sudo: false
|
2
|
+
language: ruby
|
3
|
+
cache: bundler
|
4
|
+
rvm:
|
5
|
+
- 1.9.3
|
6
|
+
- 2.2.6
|
7
|
+
- 2.3.3
|
8
|
+
- 2.4.0
|
9
|
+
- jruby
|
10
|
+
gemfile:
|
11
|
+
- gemfiles/rails-3.0.gemfile
|
12
|
+
- gemfiles/rails-3.1.gemfile
|
13
|
+
- gemfiles/rails-3.2.gemfile
|
14
|
+
- gemfiles/rails-4.0.gemfile
|
15
|
+
- gemfiles/rails-4.1.gemfile
|
16
|
+
- gemfiles/rails-4.2.gemfile
|
17
|
+
- gemfiles/rails-4.2.gemfile
|
18
|
+
- gemfiles/rails-5.0.gemfile
|
19
|
+
- gemfiles/rails-edge.gemfile
|
20
|
+
env:
|
21
|
+
global: RAILS_ENV=test
|
22
|
+
before_script:
|
23
|
+
- echo $BUNDLE_GEMFILE
|
24
|
+
- bundle install
|
25
|
+
script: bundle exec rspec
|
26
|
+
matrix:
|
27
|
+
fast_finish: true
|
28
|
+
exclude:
|
29
|
+
- rvm: "1.9.3"
|
30
|
+
include:
|
31
|
+
- rvm: "1.9.3"
|
32
|
+
gemfile: "gemfiles/rails-3.0.gemfile"
|
33
|
+
- rvm: "1.9.3"
|
34
|
+
gemfile: "gemfiles/rails-3.1.gemfile"
|
35
|
+
- rvm: "1.9.3"
|
36
|
+
gemfile: "gemfiles/rails-3.2.gemfile"
|
37
|
+
allow_failures:
|
38
|
+
- rvm: 2.4.0
|
39
|
+
- rvm: jruby
|
40
|
+
gemfile: gemfiles/rails-5.0.gemfile
|
41
|
+
- rvm: jruby
|
42
|
+
gemfile: gemfiles/rails-edge.gemfile
|
43
|
+
notifications:
|
44
|
+
email: false
|
45
|
+
slack:
|
46
|
+
rooms:
|
47
|
+
secure: F4BGVLUnaDqJ3YXfuIwx+m6047E8YstCUXs33Tfcs7SUlSuOSChuXqvCfVtnfNy2muF7xgB6VRL3xpFIRm7qNStqGUWCQJXmKq2OEgq1DYGkhAVle4d/LBtVcfBgeLelsoi+1TI9MrUtpZDHPl0li3PLoC+dq7rzSuhrxQ9EOhZlZGVn6LTeVcgNw6cLNzHSWJJ8zpYWLjBWUXgJ75MQvo5qaNbQxyfzm7GzEgRNfSzabFBwpKwB1Tog9X9TKTtPrn30O9Ur9+wmTu6EnwaDWZjaTK6I+AbxE8huIfUGvSrq1aV2JaDIra6zHEQ+d4j0oRYutgFM4YfyN9124MbPE2yH/5lXNQHMpUOsP0bl2U+KGDzq/V5APyrZ6irsvwGYpo3fSXrW8nDIAK4Mh8KB+Ta0zN5H8PmIRK76wJ+wG2zAtrfl+ailxMrdpK6J04fl3pCBuO6eW+AKEJ7Wfi5GiE7a9lk/YewAeDHyyLSnUNFIP0/iFAbTtRh5denCk0ZUS1XyfZNQuFoku7jk5lpe41SNItqOO0jv/jXPF+wensNa2UgMBIP0XkRw55LKn9eY0MKm9P+zp9ePaXs0T0Ttv4e0T4Jxrgf5QBynefgHwAsOI1nHr7GhlPaFQ6u8iNmjNYLB9v1JZMlO08LkytzZFpUuJoHbYYoBaRtUtEosBHg=
|
data/Gemfile
CHANGED
@@ -1,30 +1,3 @@
|
|
1
1
|
source 'https://rubygems.org'
|
2
|
-
gemspec
|
3
2
|
|
4
|
-
|
5
|
-
gem 'appraisal'
|
6
|
-
gem 'coveralls', require: false
|
7
|
-
gem 'json', '~> 1'
|
8
|
-
gem 'pry'
|
9
|
-
gem 'rails_stdout_logging'
|
10
|
-
gem 'rake'
|
11
|
-
gem 'rspec', '~> 3.4'
|
12
|
-
gem 'rspec-its'
|
13
|
-
gem 'simplecov', require: false
|
14
|
-
gem 'sqlite3'
|
15
|
-
gem 'terminal-table'
|
16
|
-
gem 'timecop'
|
17
|
-
|
18
|
-
ruby_version = Gem::Version.new("#{RUBY_VERSION}")
|
19
|
-
if ruby_version < Gem::Version.new("2.0.0")
|
20
|
-
gem 'public_suffix', '~> 1.4.6'
|
21
|
-
gem 'term-ansicolor', '~> 1.3.2'
|
22
|
-
gem 'webmock', '~> 2.2.0'
|
23
|
-
else
|
24
|
-
gem 'webmock'
|
25
|
-
end
|
26
|
-
|
27
|
-
# for coveralls
|
28
|
-
gem 'rest-client', '~> 1.8' # >= 2.0 requires ruby 2+, we have tests for 1.9
|
29
|
-
gem 'tins', '~> 1.6.0' # > 1.6 requires ruby 2+, we have tests for 1.9
|
30
|
-
end
|
3
|
+
gemspec
|
data/README.md
CHANGED
@@ -1,126 +1,55 @@
|
|
1
|
-
# 🌲 Timber -
|
2
|
-
|
3
|
-
<p align="center" style="background: #140f2a;">
|
4
|
-
<a href="http://files.timber.io/images/readme-interface.gif"><img src="http://files.timber.io/images/readme-interface.gif" width="100%" /></a>
|
5
|
-
</p>
|
1
|
+
# 🌲 Timber - Log Better. Solve Problems Faster.
|
6
2
|
|
7
3
|
[![ISC License](https://img.shields.io/badge/license-ISC-ff69b4.svg)](LICENSE.md)
|
8
4
|
[![CircleCI](https://circleci.com/gh/timberio/timber-ruby.svg?style=shield&circle-token=:circle-token)](https://circleci.com/gh/timberio/timber-ruby/tree/master)
|
9
|
-
[![Coverage Status](https://coveralls.io/repos/github/timberio/timber-ruby/badge.svg?branch=master)](https://coveralls.io/github/timberio/timber-ruby?branch=master)
|
10
5
|
[![Code Climate](https://codeclimate.com/github/timberio/timber-ruby/badges/gpa.svg)](https://codeclimate.com/github/timberio/timber-ruby)
|
11
6
|
[![View docs](https://img.shields.io/badge/docs-viewdocs-blue.svg?style=flat-square "Viewdocs")](http://www.rubydoc.info/github/timberio/timber-ruby)
|
12
7
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
## Installation
|
20
|
-
|
21
|
-
1. *Add* the `timber` gem in `Gemfile`:
|
22
|
-
|
23
|
-
```ruby
|
24
|
-
# Gemfile
|
25
|
-
|
26
|
-
gem 'timber'
|
27
|
-
```
|
8
|
+
* [Timber website](https://timber.io)
|
9
|
+
* [Timber docs](https://timber.io/docs)
|
10
|
+
* [Library docs](http://www.rubydoc.info/github/timberio/timber-ruby)
|
11
|
+
* [Support](mailto:support@timber.io)
|
28
12
|
|
29
|
-
2. *Install* the `Timber::Logger` in `config/environments/production.rb`:
|
30
13
|
|
31
|
-
|
32
|
-
# config/environments/production.rb
|
14
|
+
## Overview
|
33
15
|
|
34
|
-
|
35
|
-
|
16
|
+
Timber turns your raw text logs into rich JSON events that can be consumed by the
|
17
|
+
[Timber.io service](https://timber.io). It improves log data quality at the source, adding
|
18
|
+
critical event and context data to your logs so that you can filter out the noise and
|
19
|
+
solve problems faster.
|
36
20
|
|
37
|
-
|
38
|
-
```
|
21
|
+
For example, Timber turns this:
|
39
22
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
Checkout our the [Timber install example pull request](https://github.com/timberio/ruby-rails-example-app/pull/1/files)
|
45
|
-
|
46
|
-
---
|
47
|
-
|
48
|
-
</p></details>
|
49
|
-
|
50
|
-
<details><summary><strong>Not using Rails?</strong></summary><p>
|
51
|
-
|
52
|
-
No problem! You can easily install Timber following these steps:
|
53
|
-
|
54
|
-
1. *Insert* the Timber probes:
|
55
|
-
|
56
|
-
This should be executed *immediately after* you have required your dependencies.
|
57
|
-
|
58
|
-
```ruby
|
59
|
-
Timber::Probes.insert!
|
60
|
-
```
|
61
|
-
|
62
|
-
2. *Add* the Rack middlewares:
|
63
|
-
|
64
|
-
This should be included where you build your `Rack` application. Usually `config.ru`:
|
65
|
-
|
66
|
-
```ruby
|
67
|
-
# Most likely config.ru
|
68
|
-
|
69
|
-
Timber::RackMiddlewares.middlewares.each do |m|
|
70
|
-
use m
|
71
|
-
end
|
72
|
-
```
|
73
|
-
|
74
|
-
2. *Instantiate* the Timber logger:
|
75
|
-
|
76
|
-
This should be *globally* available to your application:
|
77
|
-
|
78
|
-
```ruby
|
79
|
-
logger = Timber::Logger.new(STDOUT)
|
80
|
-
```
|
81
|
-
|
82
|
-
---
|
83
|
-
|
84
|
-
</p></details>
|
85
|
-
|
86
|
-
|
87
|
-
## Send your logs (choose one)
|
88
|
-
|
89
|
-
<details><summary><strong>Heroku (log drains)</strong></summary><p>
|
90
|
-
|
91
|
-
The recommended strategy for Heroku is to setup a
|
92
|
-
[log drain](https://devcenter.heroku.com/articles/log-drains). To get your Timber log drain URL:
|
93
|
-
|
94
|
-
👉 **[Add your app to Timber](https://app.timber.io)**
|
95
|
-
|
96
|
-
---
|
97
|
-
|
98
|
-
</p></details>
|
99
|
-
|
100
|
-
<details><summary><strong>Or, all other platforms (Network / HTTP)</strong></summary><p>
|
23
|
+
```
|
24
|
+
Sent 200 in 45.ms
|
25
|
+
```
|
101
26
|
|
102
|
-
|
27
|
+
Into this:
|
103
28
|
|
104
|
-
|
29
|
+
```
|
30
|
+
Sent 200 in 45.2ms @metadata {"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}}}
|
31
|
+
```
|
105
32
|
|
106
|
-
|
107
|
-
# config/environments/production.rb (or staging, etc)
|
33
|
+
Allowing you to run queries like:
|
108
34
|
|
109
|
-
|
110
|
-
|
111
|
-
|
35
|
+
1. `context.request_id:abcd1234` - View all logs generated for a specific request.
|
36
|
+
2. `context.user.id:1` - View logs generated by a specific user.
|
37
|
+
3. `type:http_response` - View specific events (exceptions, sql queries, etc)
|
38
|
+
4. `http_server_response.time_ms:>=1000` - View slow responses with the ability to zoom out and view them in context (request, user, etc).
|
39
|
+
5. `level:error` - Levels in your logs!
|
112
40
|
|
113
|
-
2. Obtain your Timber API :key: by **[adding your app in Timber](https://app.timber.io)**.
|
114
41
|
|
115
|
-
|
42
|
+
## Installation
|
116
43
|
|
117
|
-
|
44
|
+
1. In `Gemfile`, add the `timber` gem:
|
118
45
|
|
119
|
-
|
46
|
+
```ruby
|
47
|
+
gem 'timber', '~> 2.0'
|
48
|
+
```
|
120
49
|
|
121
|
-
|
50
|
+
2. In your `shell`, run `bundle install`
|
122
51
|
|
123
|
-
|
52
|
+
3. In your `shell`, run `bundle exec timber install`
|
124
53
|
|
125
54
|
|
126
55
|
## Usage
|
@@ -132,7 +61,7 @@ Use `Logger` as normal:
|
|
132
61
|
```ruby
|
133
62
|
logger.info("My log message")
|
134
63
|
|
135
|
-
# My log message @metadata {"level": "info", "context": {...}}
|
64
|
+
# => My log message @metadata {"level": "info", "context": {...}}
|
136
65
|
```
|
137
66
|
|
138
67
|
Timber will *never* deviate from the public `::Logger` interface in *any* way.
|
@@ -141,228 +70,63 @@ Timber will *never* deviate from the public `::Logger` interface in *any* way.
|
|
141
70
|
|
142
71
|
</p></details>
|
143
72
|
|
144
|
-
<details><summary><strong>
|
145
|
-
|
146
|
-
Tags provide a quick way to identify logs. They work just like any tagging system.
|
147
|
-
In the context of logging, they prevent obstructing the log message to
|
148
|
-
accomplish the same thing, while also being a step down from creating a classified custom
|
149
|
-
event. If the event is meaningful in any way, we recommend creating a custom event.
|
150
|
-
|
151
|
-
```ruby
|
152
|
-
logger.info(message: "My log message", tag: "tag")
|
153
|
-
|
154
|
-
# My log message @metadata {"level": "info", "tags": ["tag"], "context": {...}}
|
155
|
-
```
|
156
|
-
|
157
|
-
Multiple tags:
|
158
|
-
|
159
|
-
```ruby
|
160
|
-
logger.info(message: "My log message", tags: ["tag1", "tag2"])
|
161
|
-
|
162
|
-
# My log message @metadata {"level": "info", "tags": ["tag1", "tag2"], "context": {...}}
|
163
|
-
```
|
164
|
-
|
165
|
-
Using `ActiveSupport::TaggedLogging`? It works with that as well:
|
166
|
-
|
167
|
-
```ruby
|
168
|
-
logger.tagged("tag") do
|
169
|
-
logger.info(message: "My log message", tags: ["important", "slow"])
|
170
|
-
end
|
171
|
-
|
172
|
-
# My log message @metadata {"level": "info", "tags": ["tag"], "context": {...}}
|
173
|
-
```
|
174
|
-
|
175
|
-
* In the Timber console use the query: `tags:tag`.
|
176
|
-
|
177
|
-
---
|
178
|
-
|
179
|
-
</p></details>
|
180
|
-
|
181
|
-
<details><summary><strong>Timing events</strong></summary><p>
|
73
|
+
<details><summary><strong>Custom events</strong></summary><p>
|
182
74
|
|
183
|
-
|
75
|
+
Custom events allow you to extend beyond events already defined in
|
76
|
+
the [`Timber::Events`](lib/timber/events) namespace.
|
184
77
|
|
185
78
|
```ruby
|
186
|
-
|
187
|
-
# ...my code to time...
|
188
|
-
time_ms = (Time.now - start) * 1000
|
189
|
-
logger.info(message: "Task complete", tag: "my_task", time_ms: time_ms)
|
79
|
+
Logger.warn "Payment rejected", payment_rejected: {customer_id: "abcd1234", amount: 100, reason: "Card expired"}
|
190
80
|
|
191
|
-
#
|
81
|
+
# => Payment rejected @metadata {"level": "warn", "event": {"payment_rejected": {"customer_id": "abcd1234", "amount": 100, "reason": "Card expired"}}, "context": {...}}
|
192
82
|
```
|
193
83
|
|
194
|
-
*
|
195
|
-
*
|
196
|
-
|
84
|
+
* Notice the `:payment_rejected` root key. Timber will classify this event as such.
|
85
|
+
* In the [Timber console](https://app.timber.io) use the query: `type:payment_rejected` or `payment_rejected.amount:>100`.
|
86
|
+
* See more details on our [custom events docs page](https://timber.io/docs/ruby/custom-events/)
|
197
87
|
|
198
88
|
---
|
199
89
|
|
200
90
|
</p></details>
|
201
91
|
|
92
|
+
<details><summary><strong>Custom contexts</strong></summary><p>
|
202
93
|
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
to your line of business like receiving credit card payments, saving a draft of a post,
|
207
|
-
or changing a user's password. You have 2 options to do this:
|
208
|
-
|
209
|
-
1. Log a structured Hash (simplest)
|
210
|
-
|
211
|
-
```ruby
|
212
|
-
Logger.warn message: "Payment rejected", payment_rejected: {customer_id: "abcd1234", amount: 100, reason: "Card expired"}
|
213
|
-
|
214
|
-
# Payment rejected @metadata {"level": "warn", "event": {"payment_rejected": {"customer_id": "abcd1234", "amount": 100, "reason": "Card expired"}}, "context": {...}}
|
215
|
-
```
|
216
|
-
|
217
|
-
* The hash can *only* have 2 keys: `:message` and "event type" key; `:payment_rejected` in this example.
|
218
|
-
* Timber will keyspace your event data by the event type key passed.
|
219
|
-
|
220
|
-
2. Log a Struct (recommended)
|
221
|
-
|
222
|
-
Defining structs for your important events just feels oh so good :) It creates a strong contract
|
223
|
-
with down stream consumers and gives you compile time guarantees.
|
224
|
-
|
225
|
-
```ruby
|
226
|
-
PaymentRejectedEvent = Struct.new(:customer_id, :amount, :reason) do
|
227
|
-
def message; "Payment rejected for #{customer_id}"; end
|
228
|
-
def type; :payment_rejected; end
|
229
|
-
end
|
230
|
-
Logger.warn PaymentRejectedEvent.new("abcd1234", 100, "Card expired")
|
231
|
-
|
232
|
-
# Payment rejected @metadata {"level": "warn", "event": {"payment_rejected": {"customer_id": "abcd1234", "amount": 100, "reason": "Card expired"}}, "context": {...}}
|
233
|
-
```
|
234
|
-
|
235
|
-
* In the Timber console use queries like: `payment_rejected.customer_id:xiaus1934` or `payment_rejected.amount>100`
|
236
|
-
* For more advanced examples see [`Timber::Logger`](lib/timber.logger.rb).
|
237
|
-
* Also, notice there is no mention of Timber in the above code. Just plain old logging.
|
238
|
-
|
239
|
-
#### What about regular Hashes, JSON, or logfmt?
|
240
|
-
|
241
|
-
Go for it! Timber will parse the data server side, but we *highly* recommend the above examples.
|
242
|
-
Providing a `:type` allows timber to classify the event, create a namespace for the data you
|
243
|
-
send, and make it easier to search, graph, alert, etc.
|
94
|
+
Context is additional data shared across log lines. Think of it like log join data.
|
95
|
+
Custom contexts allow you to extend beyond contexts already defined in
|
96
|
+
the [`Timber::Contexts`](lib/timber/contexts) namespace.
|
244
97
|
|
245
98
|
```ruby
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
logger.info('{"key": "value"}')
|
250
|
-
# {"key": "value"} @metadata {"level": "info", "context": {...}}
|
99
|
+
Timber::CurrentContext.with({build: {version: "1.0.0"}}) do
|
100
|
+
logger.info("My log message")
|
101
|
+
end
|
251
102
|
|
252
|
-
|
253
|
-
# key=value @metadata {"level": "info", "context": {...}}
|
103
|
+
# => My log message @metadata {"level": "info", "context": {"build": {"version": "1.0.0"}}}
|
254
104
|
```
|
255
105
|
|
256
|
-
|
106
|
+
* Notice the `:build` root key. Timber will classify this context as such.
|
107
|
+
* In the [Timber console](https://app.timber.io) use queries like: `build.version:1.0.0`
|
108
|
+
* See more details on our [custom contexts docs page](https://timber.io/docs/ruby/custom-contexts/)
|
257
109
|
|
258
110
|
</p></details>
|
259
111
|
|
260
|
-
<details><summary><strong>
|
261
|
-
|
262
|
-
Context is structured data representing the current environment when the log line was written.
|
263
|
-
It is included in every log line. Think of it like join data for your logs. For example, the
|
264
|
-
`http.request_id` field is included in the context, allowing you to find all log lines related
|
265
|
-
to that request ID, if desired. This is in contrast to *only* showing log lines that contain this
|
266
|
-
value.
|
267
|
-
|
268
|
-
1. Add a Hash (simplest)
|
269
|
-
|
270
|
-
```ruby
|
271
|
-
Timber::CurrentContext.with({build: {version: "1.0.0"}}) do
|
272
|
-
logger.info("My log message")
|
273
|
-
end
|
274
|
-
|
275
|
-
# My log message @metadata {"level": "info", "context": {"build": {"version": "1.0.0"}}}
|
276
|
-
```
|
112
|
+
<details><summary><strong>Metrics</strong></summary><p>
|
277
113
|
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
Just like events, we recommend defining your custom contexts. It makes a stronger contract
|
283
|
-
with downstream consumers.
|
284
|
-
|
285
|
-
```ruby
|
286
|
-
BuildContext = Struct.new(:version) do
|
287
|
-
def type; :build; end
|
288
|
-
end
|
289
|
-
build_context = BuildContext.new("1.0.0")
|
290
|
-
Timber::CurrentContext.with(build_context) do
|
291
|
-
logger.info("My log message")
|
292
|
-
end
|
293
|
-
|
294
|
-
# My log message @metadata {"level": "info", "context": {"build": {"version": "1.0.0"}}}
|
295
|
-
```
|
114
|
+
Logging metrics is accomplished by logging custom events. Please see our
|
115
|
+
[metrics docs page](https://timber.io/docs/ruby/metrics/) for a more detailed explanation
|
116
|
+
with examples.
|
296
117
|
|
297
118
|
</p></details>
|
298
119
|
|
299
120
|
|
300
121
|
## Jibber-Jabber
|
301
122
|
|
302
|
-
<details><summary><strong>
|
303
|
-
|
304
|
-
1. Captures and structures your framework and 3rd party logs. (see next question)
|
305
|
-
2. Adds useful context to every log line. (see next question)
|
306
|
-
3. Allows you to easily add tags and timings to log. (see [Usage](#usage))
|
307
|
-
4. Provides a framework for logging custom structured events. (see [Usage](#usage))
|
308
|
-
5. Offers transport strategies to [send your logs](#send-your-logs) to the Timber service.
|
309
|
-
|
310
|
-
---
|
311
|
-
|
312
|
-
</p></details>
|
313
|
-
|
314
|
-
<details><summary><strong>What are the benefits of using Timber?</strong></summary><p>
|
315
|
-
|
316
|
-
1. **Data quality.** The usefulness of your logs starts here. This is why we ship libraries that
|
317
|
-
structure logs from *within* your application; a fundamental difference from parsing. Not only
|
318
|
-
is it much more stable, but we can include data you couldn't obtain otherwise.
|
319
|
-
2. **Human readability.** Structuring your logs doesn't mean they have to be unreadable. Timber
|
320
|
-
*augments* your logs with structured data. Meaning we do not alter the original log message,
|
321
|
-
we simply attach metadata to it. And our console is specifically designed to give you access
|
322
|
-
to this data, without compromising readability. 😮
|
323
|
-
3. **Reliable downstream consumption.** All log events adhere to a
|
324
|
-
[normalized, shared, schema](https://github.com/timberio/log-event-json-schema) that follows
|
325
|
-
[semantic versioning](http://semver.org/) and goes through a [standard release process](https://github.com/timberio/log-event-json-schema/releases).
|
326
|
-
This means you can *rely* on the structure of your logs and interact consistently with them
|
327
|
-
across apps of any language: queries, graphs, alerts, and other downstream consumers.
|
328
|
-
4. **Zero risk of code debt or lock-in.** Logging is a standard that has been around since the dawn
|
329
|
-
of computers. It's built into every language, framework, and library. Timber adheres strictly
|
330
|
-
to the default `Logger` interface. There are no special APIs, and no need to pepper your app
|
331
|
-
with Timber specific code. It's just better logging. If you choose to stop using Timber, you
|
332
|
-
can do so without consequence.
|
333
|
-
5. **Long term retention.** Timber is designed on modern big-data principles. As a result, we can
|
334
|
-
offer 6+ months of retention at prices cheaper than alternatives offering <1 month.
|
335
|
-
This allows you to unlock your logs for purposes beyond debugging.
|
336
|
-
|
337
|
-
---
|
338
|
-
|
339
|
-
</p></details>
|
340
|
-
|
341
|
-
<details><summary><strong>What events does Timber capture & structure for me?</strong></summary><p>
|
342
|
-
|
343
|
-
Out of the box you get everything in the [`Timber::Events`](lib/timber/events) namespace:
|
123
|
+
<details><summary><strong>Which log events does Timber structure for me?</strong></summary><p>
|
344
124
|
|
345
|
-
|
346
|
-
2. [Exception Event](lib/timber/events/exception.rb)
|
347
|
-
3. [HTTP Client Request Event (net/http outgoing)](lib/timber/events/http_client_request.rb)
|
348
|
-
4. [HTTP Client Response Event (resposne from net/http outgoing)](lib/timber/events/http_client_response.rb)
|
349
|
-
5. [HTTP Server Request Event (incoming client request)](lib/timber/events/http_server_request.rb)
|
350
|
-
6. [HTTP Server Response Event (response to incoming client request)](lib/timber/events/http_server_response.rb)
|
351
|
-
7. [SQL Query Event](lib/timber/events/sql_query.rb)
|
352
|
-
8. [Template Render Event](lib/timber/events/template_render.rb)
|
353
|
-
9. ...more coming soon, [file an issue](https://github.com/timberio/timber-ruby/issues) to request.
|
125
|
+
Out of the box you get everything in the [`Timber::Events`](lib/timber/events) namespace.
|
354
126
|
|
355
127
|
We also add context to every log, everything in the [`Timber::Contexts`](lib/timber/contexts)
|
356
|
-
namespace. Context is structured data representing the current environment when the log line
|
357
|
-
written. It is included in every log line. Think of it like join data for your logs
|
358
|
-
|
359
|
-
1. [HTTP Context](lib/timber/contexts/http.rb)
|
360
|
-
2. [Organization Context](lib/timber/contexts/organization.rb)
|
361
|
-
3. [Process Context](lib/timber/contexts/process.rb)
|
362
|
-
4. [Server Context](lib/timber/contexts/server.rb)
|
363
|
-
5. [Runtime Context](lib/timber/contexts/runtime.rb)
|
364
|
-
5. [User Context](lib/timber/contexts/user.rb)
|
365
|
-
6. ...more coming soon, [file an issue](https://github.com/timberio/timber-ruby/issues) to request.
|
128
|
+
namespace. Context is structured data representing the current environment when the log line
|
129
|
+
was written. It is included in every log line. Think of it like join data for your logs.
|
366
130
|
|
367
131
|
---
|
368
132
|
|
@@ -370,17 +134,38 @@ written. It is included in every log line. Think of it like join data for your l
|
|
370
134
|
|
371
135
|
<details><summary><strong>What about my current log statements?</strong></summary><p>
|
372
136
|
|
373
|
-
They'll continue to work as expected. Timber adheres
|
374
|
-
|
137
|
+
They'll continue to work as expected. Timber adheres to the default `Logger` interface.
|
138
|
+
Your previous logger calls will work as they always do.
|
375
139
|
|
376
140
|
In fact, traditional log statements for non-meaningful events, debug statements, etc, are
|
377
141
|
encouraged. In cases where the data is meaningful, consider [logging a custom event](#usage).
|
378
142
|
|
379
143
|
</p></details>
|
380
144
|
|
145
|
+
<details><summary><strong>How is Timber different?</strong></summary><p>
|
146
|
+
|
147
|
+
1. **It's just _better_ logging**. Nothing beats well structured raw data. And that's exactly
|
148
|
+
what Timber aims to provide. There are no agents, special APIs, or proprietary data
|
149
|
+
sets that you can't access.
|
150
|
+
2. **Improved log data quality.** Instead of relying on parsing alone, Timber ships libraries that
|
151
|
+
structure and augment your logs from _within_ your application. Improving your log data at the
|
152
|
+
source.
|
153
|
+
3. **Human readability.** Timber _augments_ your logs without sacrificing human readability. For
|
154
|
+
example: `log message @metadata {...}`. And when you view your logs in the
|
155
|
+
[Timber console](https://app.timber.io), you'll see the human friendly messages
|
156
|
+
with the ability to view the associated metadata.
|
157
|
+
4. **Long retention**. Logging is notoriously expensive with low retention. Timber
|
158
|
+
offers _6 months_ of retention by default with sane prices.
|
159
|
+
5. **Normalized schema.** Have multiple apps? All of Timber's libraries adhere to our
|
160
|
+
[JSON schema](https://github.com/timberio/log-event-json-schema). This means queries, alerts,
|
161
|
+
and graphs for your ruby app can also be applied to your elixir app (for example).
|
162
|
+
|
163
|
+
---
|
164
|
+
|
165
|
+
</p></details>
|
381
166
|
|
382
167
|
---
|
383
168
|
|
384
169
|
<p align="center" style="background: #221f40;">
|
385
|
-
<a href="http://github.com/timberio/timber-
|
170
|
+
<a href="http://github.com/timberio/timber-elixir"><img src="http://files.timber.io/images/ruby-library-readme-log-truth.png" height="947" /></a>
|
386
171
|
</p>
|