timber 2.0.3 → 2.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +15 -1
- data/lib/timber/cli/install.rb +32 -37
- data/lib/timber/config.rb +69 -17
- data/lib/timber/frameworks/rails.rb +33 -29
- data/lib/timber/logger.rb +13 -11
- data/lib/timber/logger/metadata_methods.rb +1 -0
- data/lib/timber/overrides.rb +0 -1
- data/lib/timber/version.rb +1 -1
- data/spec/support/timber.rb +3 -1
- data/spec/timber/logger_spec.rb +2 -2
- metadata +2 -2
- data/lib/timber/overrides/rails_server.rb +0 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0432ed485c5f9ddbe423ae464cabe9365ac1eefc
|
4
|
+
data.tar.gz: 2051b18db981d2542497cb6b26813ce272625833
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7e9f7183d5447b599b50cd6ca3e566be9e12179209eb1bc26177a71a61d2238bde6abe806593fc5fa0ca08aa4ad5efebf4414c5a72e9afe9745af3276859da09
|
7
|
+
data.tar.gz: 680b421e9412c3e814cc4d116670d2ae583a019501769bd117347b960850fd656f8cc1eacc6cce26e1f0f92cb78c49ea97b0c74c2f7772ad23ccd6fa01004020
|
data/README.md
CHANGED
@@ -30,7 +30,7 @@ Into this:
|
|
30
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
31
|
```
|
32
32
|
|
33
|
-
Allowing you to run queries like:
|
33
|
+
Allowing you to run queries in the [Timber console](https://app.timber.io) like:
|
34
34
|
|
35
35
|
1. `context.request_id:abcd1234` - View all logs generated for a specific request.
|
36
36
|
2. `context.user.id:1` - View logs generated by a specific user.
|
@@ -52,6 +52,20 @@ Allowing you to run queries like:
|
|
52
52
|
3. In your `shell`, run `bundle exec timber install`
|
53
53
|
|
54
54
|
|
55
|
+
## Configuration
|
56
|
+
|
57
|
+
All configuration options can be seen in the
|
58
|
+
[`Timber::Config docs`](http://www.rubydoc.info/github/timberio/timber-ruby/Timber/Config).
|
59
|
+
|
60
|
+
Here's a few popular options:
|
61
|
+
|
62
|
+
1. `config.timber.format =`
|
63
|
+
* `:default` - This is the default. It's the original, default, unchanged log messages.
|
64
|
+
* `:lograge` - Works exactly like [lograge](https://github.com/roidrage/lograge), except Timber's
|
65
|
+
additional context and metadata is also appended. Lograge++.
|
66
|
+
|
67
|
+
|
68
|
+
|
55
69
|
## Usage
|
56
70
|
|
57
71
|
<details><summary><strong>Basic logging</strong></summary><p>
|
data/lib/timber/cli/install.rb
CHANGED
@@ -32,7 +32,7 @@ module Timber
|
|
32
32
|
case ask_yes_no("Are the above details correct?")
|
33
33
|
when :yes
|
34
34
|
if app.heroku?
|
35
|
-
|
35
|
+
update_environment_config("production", :stdout)
|
36
36
|
|
37
37
|
puts ""
|
38
38
|
puts Messages.separator
|
@@ -55,7 +55,7 @@ module Timber
|
|
55
55
|
|
56
56
|
case ask("Enter your choice: (1/2) ")
|
57
57
|
when "1"
|
58
|
-
|
58
|
+
update_environment_config("production", :http, :api_key_code => "ENV['TIMBER_API_KEY']")
|
59
59
|
|
60
60
|
puts ""
|
61
61
|
puts Messages.http_environment_variables(app.api_key)
|
@@ -65,7 +65,7 @@ module Timber
|
|
65
65
|
puts ""
|
66
66
|
|
67
67
|
when "2"
|
68
|
-
|
68
|
+
update_environment_config("production", :http, :api_key_code => "'#{app.api_key}'")
|
69
69
|
|
70
70
|
end
|
71
71
|
|
@@ -107,53 +107,48 @@ module Timber
|
|
107
107
|
end
|
108
108
|
|
109
109
|
private
|
110
|
-
def
|
110
|
+
def update_environment_config(name, log_device_type, options = {})
|
111
|
+
path = File.join("config", "environments", "#{name}.rb")
|
112
|
+
|
111
113
|
puts ""
|
112
|
-
|
114
|
+
task_message = "Configuring Timber in #{path}"
|
115
|
+
write Messages.task_start(task_message)
|
113
116
|
|
114
117
|
logger_code = \
|
115
118
|
case log_device_type
|
116
119
|
when :http
|
117
120
|
api_key_code = options[:api_key_code] || raise(ArgumentError.new("the :api_key_code option is required"))
|
118
|
-
|
119
|
-
|
121
|
+
|
122
|
+
logger_code = defined?(::ActiveSupport::TaggedLogging) ? "ActiveSupport::TaggedLogging.new(logger)" : "logger"
|
123
|
+
|
124
|
+
code = <<-CODE
|
125
|
+
# Install the Timber.io logger, send logs over HTTP
|
126
|
+
log_device = Timber::LogDevices::HTTP.new(#{api_key_code})
|
127
|
+
logger = Timber::Logger.new(log_device)
|
128
|
+
logger.level = config.log_level
|
129
|
+
config.logger = #{logger_code}
|
130
|
+
CODE
|
131
|
+
code.rstrip
|
120
132
|
|
121
133
|
when :stdout
|
122
|
-
|
134
|
+
code = <<-CODE
|
135
|
+
# Install the Timber.io logger, send logs to STDOUT
|
136
|
+
logger = Timber::Logger.new(STDOUT)
|
137
|
+
logger.level = config.log_level
|
138
|
+
config.logger = #{logger_code}
|
139
|
+
CODE
|
140
|
+
code.rstrip
|
123
141
|
end
|
124
142
|
|
125
|
-
body = <<-BODY
|
126
|
-
# Timber.io Ruby Library
|
127
|
-
#
|
128
|
-
# ^ ^ ^ ^ ___I_ ^ ^ ^ ^ ^ ^ ^
|
129
|
-
# /|\\/|\\/|\\ /|\\ /\\-_--\\ /|\\/|\\ /|\\/|\\/|\\ /|\\/|\\
|
130
|
-
# /|\\/|\\/|\\ /|\\ / \\_-__\\ /|\\/|\\ /|\\/|\\/|\\ /|\\/|\\
|
131
|
-
# /|\\/|\\/|\\ /|\\ |[]| [] | /|\\/|\\ /|\\/|\\/|\\ /|\\/|\\
|
132
|
-
#
|
133
|
-
# Library: http://github.com/timberio/timber-ruby
|
134
|
-
# Docs: http://www.rubydoc.info/github/timberio/timber-ruby
|
135
|
-
# Support: support@timber.io
|
136
|
-
|
137
|
-
logger = case Rails.env
|
138
|
-
when "development"
|
139
|
-
# Write logs to STDOUT in a simple message only format
|
140
|
-
Timber::Logger.new(STDOUT).tap do |logger|
|
141
|
-
logger.formatter = Timber::Logger::SimpleFormatter.new
|
142
|
-
end
|
143
|
-
when "production", "staging"
|
144
|
-
#{logger_code}
|
145
|
-
end
|
146
143
|
|
147
|
-
|
148
|
-
logger.level = Rails.application.config.log_level
|
149
|
-
Timber::Frameworks::Rails.set_logger(logger)
|
150
|
-
end
|
151
|
-
BODY
|
144
|
+
current_contents = File.read(path)
|
152
145
|
|
153
|
-
|
154
|
-
|
146
|
+
if !current_contents.include?("Timber::Logger.new")
|
147
|
+
new_contents = current_contents.sub(/\nend/, "\n\n#{logger_code}\nend")
|
148
|
+
File.write(path, new_contents)
|
149
|
+
end
|
155
150
|
|
156
|
-
puts colorize(Messages.task_complete(
|
151
|
+
puts colorize(Messages.task_complete(task_message), :green)
|
157
152
|
end
|
158
153
|
|
159
154
|
def send_test_messages(api_key)
|
data/lib/timber/config.rb
CHANGED
@@ -1,34 +1,48 @@
|
|
1
1
|
require "singleton"
|
2
2
|
|
3
3
|
module Timber
|
4
|
-
# Interface for
|
4
|
+
# Interface for setting and reading Timber configuration.
|
5
5
|
#
|
6
|
-
#
|
6
|
+
# For Rails apps this is installed into `config.timber`. See examples below.
|
7
7
|
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
# If a value is not explicity set, the environment is checked for it's associated
|
15
|
-
# environment variable. If that is not set, a reasonable default will be chosen. Each
|
16
|
-
# method documents this.
|
8
|
+
# @example Rails example
|
9
|
+
# config.timber.append_metadata = false
|
10
|
+
# @example Everything else
|
11
|
+
# config = Timber::Config.instance
|
12
|
+
# config.append_metdata = false
|
17
13
|
class Config
|
18
14
|
class NoLoggerError < StandardError; end
|
19
15
|
|
16
|
+
PRODUCTION_NAME = "production".freeze
|
17
|
+
STAGING_NAME = "staging".freeze
|
18
|
+
|
20
19
|
include Singleton
|
21
20
|
|
22
|
-
attr_writer :debug_logger, :http_body_limit, :logger
|
21
|
+
attr_writer :append_metadata, :debug_logger, :http_body_limit, :logger
|
23
22
|
|
23
|
+
# @private
|
24
24
|
def initialize
|
25
25
|
@http_body_limit = 2000
|
26
26
|
end
|
27
27
|
|
28
|
+
# The environment your app is running in. Defaults to `RACK_ENV` and `RAILS_ENV`.
|
29
|
+
#
|
30
|
+
# @example Rails
|
31
|
+
# config.timber.environment = "staging"
|
32
|
+
# @example Everything else
|
33
|
+
# Timber::Config.instance.environment = "staging"
|
34
|
+
def environment
|
35
|
+
@environment ||= ENV["RACK_ENV"] || ENV["RAILS_ENV"] || "development"
|
36
|
+
end
|
28
37
|
|
29
38
|
# Set a debug_logger to view internal Timber library log message.
|
30
39
|
# Useful for debugging. Defaults to `nil`. If set, debug messages will be
|
31
40
|
# written to this logger.
|
41
|
+
#
|
42
|
+
# @example Rails
|
43
|
+
# config.timber.debug_logger = ::Logger.new(STDOUT)
|
44
|
+
# @example Everything else
|
45
|
+
# Timber::Config.instance.debug_logger = ::Logger.new(STDOUT)
|
32
46
|
def debug_logger
|
33
47
|
@debug_logger
|
34
48
|
end
|
@@ -36,16 +50,54 @@ module Timber
|
|
36
50
|
# Truncates captured HTTP bodies to this specified limit. The default is `2000`.
|
37
51
|
# If you want to capture more data, you can raise this to a maximum of `5000`,
|
38
52
|
# or lower this to be more efficient with data.
|
53
|
+
#
|
54
|
+
# @example Rails
|
55
|
+
# config.timber.http_body_limit = 500
|
56
|
+
# @example Everything else
|
57
|
+
# Timber::Config.instance.http_body_limit = 500
|
39
58
|
def http_body_limit
|
40
59
|
@http_body_limit
|
41
60
|
end
|
42
61
|
|
43
|
-
#
|
44
|
-
#
|
45
|
-
#
|
46
|
-
#
|
62
|
+
# Should the logger append the Timber metadata. This is automatically turned on
|
63
|
+
# for production and staging environments. Other environments should be set manually.
|
64
|
+
# If set to `true` log messages will look like:
|
65
|
+
#
|
66
|
+
# log message @metadata {...}
|
67
|
+
#
|
68
|
+
# @example Rails
|
69
|
+
# config.timber.append_metadata = false
|
70
|
+
# @example Everything else
|
71
|
+
# Timber::Config.instance.append_metadata = false
|
72
|
+
def append_metadata?
|
73
|
+
if defined?(@append_metadata)
|
74
|
+
return @append_metadata == true
|
75
|
+
end
|
76
|
+
|
77
|
+
production? || staging?
|
78
|
+
end
|
79
|
+
|
80
|
+
# This is the logger Timber writes to. All of the Timber integrations write to
|
81
|
+
# this logger. It should be set to your global logger to keep the logging destination consitent.
|
82
|
+
#
|
83
|
+
# For Rails this is set automatically to `Rails.logger`.
|
84
|
+
#
|
85
|
+
# @example Rails
|
86
|
+
# Rails.logger = Timber::Logger.new(STDOUT)
|
87
|
+
# config.timber.logger = Rails.logger
|
88
|
+
# @example Everything else
|
89
|
+
# Timber::Config.instance.logger = Timber::Logger.new(STDOUT)
|
47
90
|
def logger
|
48
|
-
@logger ||
|
91
|
+
@logger || Logger.new(STDOUT)
|
49
92
|
end
|
93
|
+
|
94
|
+
private
|
95
|
+
def production?
|
96
|
+
environment == PRODUCTION_NAME
|
97
|
+
end
|
98
|
+
|
99
|
+
def staging?
|
100
|
+
environment == STAGING_NAME
|
101
|
+
end
|
50
102
|
end
|
51
103
|
end
|
@@ -1,53 +1,57 @@
|
|
1
1
|
module Timber
|
2
2
|
module Frameworks
|
3
|
+
# Module for Rails specific code, such as the Railtie and any methods that assist
|
4
|
+
# with Rails setup.
|
3
5
|
module Rails
|
4
6
|
# Installs Timber into your Rails app automatically.
|
5
7
|
class Railtie < ::Rails::Railtie
|
6
8
|
config.timber = Config.instance
|
7
9
|
|
8
|
-
initializer(:timber_silence_logger_complaints, before: :initialize_logger) do
|
9
|
-
# We set a default logger because Rails tries to write to a file by default.
|
10
|
-
# This causes errors on platforms with a read only file system (Heroku).
|
11
|
-
# See this commit: https://github.com/heroku/rails_stdout_logging/commit/13d092650118bcfeb30f383d3274cee46cbf7b8f
|
12
|
-
# Moreover, the Timber logger gets configured properly later in an initiailizer.
|
13
|
-
# This is a hold over until we reach that file in the initialization process.
|
14
|
-
is_heroku = !ENV['DYNO'].nil?
|
15
|
-
if is_heroku
|
16
|
-
logger = defined?(::ActiveSupport::Logger) ?
|
17
|
-
::ActiveSupport::Logger.new(STDOUT) : ::Logger.new(STDOUT)
|
18
|
-
::Rails.logger = config.logger = logger
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
10
|
# Initialize Timber immediately after the logger in case anything uses the logger
|
23
11
|
# during the initialization process.
|
24
|
-
initializer(:timber, after: :initialize_logger) do
|
25
|
-
|
26
|
-
|
27
|
-
# 2. Replace the logger with Timber::Logger so that users get our logger API
|
28
|
-
# 3. Disable metadata so that the logger is essentially transparent until further
|
29
|
-
# configuration in initializers/timber.rb. This allows them to essentially "turn on"
|
30
|
-
# timber for production, staging, etc.
|
31
|
-
log_device = ::Rails.logger.instance_variable_get(:@logdev).try(:dev)
|
32
|
-
logger = Logger.new(log_device)
|
33
|
-
logger.formatter = Logger::SimpleFormatter.new
|
34
|
-
logger.level = ::Rails.logger.level
|
35
|
-
::Rails.logger = config.logger = logger
|
12
|
+
initializer(:timber, group: :all, after: :initialize_logger) do
|
13
|
+
logger = Rails.ensure_timber_logger(::Rails.logger)
|
14
|
+
Rails.set_logger(logger)
|
36
15
|
|
37
16
|
Rails.configure_middlewares(config.app_middleware)
|
38
17
|
Integrations.integrate!
|
39
18
|
end
|
40
19
|
end
|
41
20
|
|
21
|
+
# This builds a new Timber::Logger from an existing logger. This allows us to transparentl
|
22
|
+
# switch users onto the Timber::Logger since we support a more useful logging API.
|
23
|
+
def self.ensure_timber_logger(existing_logger)
|
24
|
+
if existing_logger.is_a?(Logger)
|
25
|
+
return existing_logger
|
26
|
+
end
|
27
|
+
|
28
|
+
log_device = existing_logger.instance_variable_get(:@logdev).try(:dev)
|
29
|
+
logger = Logger.new(log_device)
|
30
|
+
logger.level = existing_logger.try(:level) || Logger::DEBUG
|
31
|
+
if defined?(::ActiveSupport::TaggedLogging)
|
32
|
+
logger = ::ActiveSupport::TaggedLogging.new(logger)
|
33
|
+
end
|
34
|
+
logger
|
35
|
+
end
|
36
|
+
|
37
|
+
# Sets the Rails logger. Rails
|
42
38
|
def self.set_logger(logger)
|
43
39
|
if defined?(::ActiveSupport::TaggedLogging) && !logger.is_a?(::ActiveSupport::TaggedLogging)
|
44
40
|
logger = ::ActiveSupport::TaggedLogging.new(logger)
|
45
41
|
end
|
46
42
|
|
47
43
|
Config.instance.logger = logger
|
48
|
-
|
49
|
-
|
50
|
-
|
44
|
+
|
45
|
+
# Set the various Rails framework loggers. We *have* to do this because Rails
|
46
|
+
# internally sets these with an ActiveSupport.onload(:active_record) { } callback.
|
47
|
+
# We don't have an opportunity to intercept this since the :initialize_logger
|
48
|
+
# initializer loads these modules. Moreover, earlier version of rails don't do this
|
49
|
+
# at all, hence the defined? checks. Yay for being implicit.
|
50
|
+
::ActionCable::Server::Base.logger = logger if defined?(::ActionCable::Server::Base)
|
51
|
+
::ActionController::Base.logger = logger if defined?(::ActionController::Base)
|
52
|
+
::ActionMailer::Base.logger = logger if defined?(::ActionMailer::Base) && ::ActionMailer::Base.respond_to?(:logger=)
|
53
|
+
::ActionView::Base.logger = logger if defined?(::ActionView::Base) && ::ActionView::Base.respond_to?(:logger=)
|
54
|
+
::ActiveRecord::Base.logger = logger if defined?(::ActiveRecord::Base)
|
51
55
|
::Rails.logger = logger
|
52
56
|
end
|
53
57
|
|
data/lib/timber/logger.rb
CHANGED
@@ -119,24 +119,26 @@ module Timber
|
|
119
119
|
end
|
120
120
|
end
|
121
121
|
|
122
|
-
# Structures your log messages
|
123
|
-
#
|
122
|
+
# Structures your log messages as strings and appends metadata if
|
123
|
+
# `Timber::Config.instance.append_metadata?` is true.
|
124
124
|
#
|
125
|
-
#
|
126
|
-
# logger.formatter = Timber::JSONFormatter.new
|
127
|
-
#
|
128
|
-
# Example message:
|
125
|
+
# Example message with metdata:
|
129
126
|
#
|
130
127
|
# My log message @metadata {"level":"info","dt":"2016-09-01T07:00:00.000000-05:00"}
|
131
128
|
#
|
132
|
-
class
|
129
|
+
class StringFormatter < Formatter
|
133
130
|
METADATA_CALLOUT = "@metadata".freeze
|
134
131
|
|
135
132
|
def call(severity, time, progname, msg)
|
136
133
|
log_entry = build_log_entry(severity, time, progname, msg)
|
137
|
-
|
138
|
-
|
139
|
-
|
134
|
+
|
135
|
+
if Config.instance.append_metadata?
|
136
|
+
metadata = log_entry.to_json(:except => [:message])
|
137
|
+
# use << for concatenation for performance reasons
|
138
|
+
log_entry.message.gsub("\n", "\\n") << " " << METADATA_CALLOUT << " " << metadata << "\n"
|
139
|
+
else
|
140
|
+
log_entry.message + "\n"
|
141
|
+
end
|
140
142
|
end
|
141
143
|
end
|
142
144
|
|
@@ -190,7 +192,7 @@ module Timber
|
|
190
192
|
if args.size == 1 and args.first.is_a?(LogDevices::HTTP)
|
191
193
|
self.formatter = PassThroughFormatter.new
|
192
194
|
else
|
193
|
-
self.formatter =
|
195
|
+
self.formatter = StringFormatter.new
|
194
196
|
end
|
195
197
|
|
196
198
|
self.level = environment_level
|
@@ -0,0 +1 @@
|
|
1
|
+
metadata_methods.rb
|
data/lib/timber/overrides.rb
CHANGED
data/lib/timber/version.rb
CHANGED
data/spec/support/timber.rb
CHANGED
data/spec/timber/logger_spec.rb
CHANGED
@@ -10,8 +10,8 @@ describe Timber::Logger, :rails_23 => true do
|
|
10
10
|
Timecop.freeze(time) { example.run }
|
11
11
|
end
|
12
12
|
|
13
|
-
context "with the
|
14
|
-
before(:each) { logger.formatter = Timber::Logger::
|
13
|
+
context "with the StringFormatter" do
|
14
|
+
before(:each) { logger.formatter = Timber::Logger::StringFormatter.new }
|
15
15
|
|
16
16
|
it "should accept strings" do
|
17
17
|
logger.info("this is a test")
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: timber
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Timber Technologies, Inc.
|
@@ -198,9 +198,9 @@ files:
|
|
198
198
|
- lib/timber/log_devices/http.rb
|
199
199
|
- lib/timber/log_entry.rb
|
200
200
|
- lib/timber/logger.rb
|
201
|
+
- lib/timber/logger/metadata_methods.rb
|
201
202
|
- lib/timber/overrides.rb
|
202
203
|
- lib/timber/overrides/lograge.rb
|
203
|
-
- lib/timber/overrides/rails_server.rb
|
204
204
|
- lib/timber/overrides/rails_stdout_logging.rb
|
205
205
|
- lib/timber/util.rb
|
206
206
|
- lib/timber/util/active_support_log_subscriber.rb
|