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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a5285d17535de9890e141603c444772904265630
4
- data.tar.gz: 5ccb28e7a21bdcaa1d5d71822160114e422e5f7f
3
+ metadata.gz: 0432ed485c5f9ddbe423ae464cabe9365ac1eefc
4
+ data.tar.gz: 2051b18db981d2542497cb6b26813ce272625833
5
5
  SHA512:
6
- metadata.gz: ef8847f90d849dabed1702427574a3864095cf6098801cad33cc45302203bdfdd4ccc11fd0c37c9724342ff29bf2f40c3ae9b98bf8da71d07f1b022f71f4b970
7
- data.tar.gz: 8a200733730ff167b57ecbf844bd2aa1ab057bbab66dc3f6d407eec4830877c0b68e9437a1464123fd85bd1f150fdea044d3537cdf679d7414974e45f8d35210
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>
@@ -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
- create_initializer(:stdout)
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
- create_initializer(:http, :api_key_code => "ENV['TIMBER_API_KEY']")
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
- create_initializer(:http, :api_key_code => "'#{app.api_key}'")
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 create_initializer(log_device_type, options = {})
110
+ def update_environment_config(name, log_device_type, options = {})
111
+ path = File.join("config", "environments", "#{name}.rb")
112
+
111
113
  puts ""
112
- write Messages.task_start("Creating config/initializers/timber.rb")
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
- "log_device = Timber::LogDevices::HTTP.new(#{api_key_code})\n" +
119
- " Timber::Logger.new(log_device)"
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
- "Timber::Logger.new(STDOUT)"
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
- if logger
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
- FileUtils.mkdir_p(File.join(Dir.pwd, "config", "initializers"))
154
- File.write(File.join(Dir.pwd, "config/initializers/timber.rb"), body)
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("Creating config/initializers/timber.rb"), :green)
151
+ puts colorize(Messages.task_complete(task_message), :green)
157
152
  end
158
153
 
159
154
  def send_test_messages(api_key)
@@ -1,34 +1,48 @@
1
1
  require "singleton"
2
2
 
3
3
  module Timber
4
- # Interface for settings and reading Timber configuration.
4
+ # Interface for setting and reading Timber configuration.
5
5
  #
6
- # You can override any configuration supplied here by simply setting it:
6
+ # For Rails apps this is installed into `config.timber`. See examples below.
7
7
  #
8
- # # Rails
9
- # config.timber.api_key = "my api key"
10
- #
11
- # # Everything else
12
- # Timber::Config.instance.api_key = "my api key"
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
- # This is the logger Timber writes to. It should be set to your global
44
- # logger to keep the logging destination consitent. Please see `delegate_logger_to`
45
- # to delegate this call to another method. This is set to `Rails.logger`
46
- # for rails.
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 || raise(NoLoggerError.new)
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
- # The goals here:
26
- # 1. Respect the default log device that rails sets in :initialize_logger
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
- ::ActionController::Base.logger = logger
49
- ::ActionView::Base.logger = logger if ::ActionView::Base.respond_to?(:logger=)
50
- ::ActiveRecord::Base.logger = logger
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
 
@@ -119,24 +119,26 @@ module Timber
119
119
  end
120
120
  end
121
121
 
122
- # Structures your log messages into Timber's hybrid format, which makes
123
- # it easy to read while also appending the appropriate metadata.
122
+ # Structures your log messages as strings and appends metadata if
123
+ # `Timber::Config.instance.append_metadata?` is true.
124
124
  #
125
- # logger = Timber::Logger.new(STDOUT)
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 HybridFormatter < Formatter
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
- metadata = log_entry.to_json(:except => [:message])
138
- # use << for concatenation for performance reasons
139
- log_entry.message.gsub("\n", "\\n") << " " << METADATA_CALLOUT << " " << metadata << "\n"
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 = HybridFormatter.new
195
+ self.formatter = StringFormatter.new
194
196
  end
195
197
 
196
198
  self.level = environment_level
@@ -0,0 +1 @@
1
+ metadata_methods.rb
@@ -1,5 +1,4 @@
1
1
  require "timber/overrides/lograge"
2
- require "timber/overrides/rails_server"
3
2
  require "timber/overrides/rails_stdout_logging"
4
3
 
5
4
  module Timber
@@ -1,3 +1,3 @@
1
1
  module Timber
2
- VERSION = "2.0.3"
2
+ VERSION = "2.0.4"
3
3
  end
@@ -1,3 +1,5 @@
1
1
  require "timber"
2
2
 
3
- Timber::Config.instance.debug_logger = ::Logger.new(STDOUT)
3
+ config = Timber::Config.instance
4
+ config.append_metadata = true
5
+ config.debug_logger = ::Logger.new(STDOUT)
@@ -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 :hybrid format" do
14
- before(:each) { logger.formatter = Timber::Logger::HybridFormatter.new }
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.3
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
@@ -1,10 +0,0 @@
1
- begin
2
- require "rails/commands/server"
3
-
4
- class ::Rails::Server < ::Rack::Server
5
- private
6
- def log_to_stdout
7
- end
8
- end
9
- rescue Exception
10
- end