timber 1.1.14 → 2.0.0
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/.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
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module Timber
|
|
2
|
+
module Integrations
|
|
3
|
+
module ActiveRecord
|
|
4
|
+
# Reponsible for uninstalling the default `ActiveRecord::LogSubscriber` and replacing it
|
|
5
|
+
# with the `TimberLogSubscriber`.
|
|
6
|
+
#
|
|
7
|
+
# @private
|
|
8
|
+
class LogSubscriber < Integrator
|
|
9
|
+
def initialize
|
|
10
|
+
require "active_record/log_subscriber"
|
|
11
|
+
require "timber/integrations/active_record/log_subscriber/timber_log_subscriber"
|
|
12
|
+
rescue LoadError => e
|
|
13
|
+
raise RequirementNotMetError.new(e.message)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def integrate!
|
|
17
|
+
return true if Util::ActiveSupportLogSubscriber.subscribed?(:active_record, TimberLogSubscriber)
|
|
18
|
+
|
|
19
|
+
Util::ActiveSupportLogSubscriber.unsubscribe!(:active_record, ::ActiveRecord::LogSubscriber)
|
|
20
|
+
TimberLogSubscriber.attach_to(:active_record)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
module Timber
|
|
2
|
+
module Integrations
|
|
3
|
+
module ActiveRecord
|
|
4
|
+
class LogSubscriber < Integrator
|
|
5
|
+
# The log subscriber that replaces the default `ActiveRecord::LogSubscriber`.
|
|
6
|
+
# The intent of this subscriber is to, as transparently as possible, properly
|
|
7
|
+
# track events that are being logged here. This LogSubscriber will never change
|
|
8
|
+
# default behavior / log messages.
|
|
9
|
+
#
|
|
10
|
+
# @private
|
|
11
|
+
class TimberLogSubscriber < ::ActiveRecord::LogSubscriber
|
|
12
|
+
def sql(event)
|
|
13
|
+
r = super(event)
|
|
14
|
+
|
|
15
|
+
if @message
|
|
16
|
+
payload = event.payload
|
|
17
|
+
event = Events::SQLQuery.new(
|
|
18
|
+
sql: payload[:sql],
|
|
19
|
+
time_ms: event.duration,
|
|
20
|
+
message: @message
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
logger.debug event
|
|
24
|
+
|
|
25
|
+
@message = nil
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
r
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
def debug(message)
|
|
33
|
+
@message = message
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
module Timber
|
|
2
|
+
module Integrations
|
|
3
|
+
module ActiveSupport
|
|
4
|
+
# Reponsible for automatimcally tracking SQL query events in `ActiveRecord`, while still
|
|
5
|
+
# preserving the default log style.
|
|
6
|
+
#
|
|
7
|
+
# @private
|
|
8
|
+
class TaggedLogging < Integrator
|
|
9
|
+
# @private
|
|
10
|
+
module FormatterMethods
|
|
11
|
+
def self.included(mod)
|
|
12
|
+
mod.module_eval do
|
|
13
|
+
alias_method :_timber_original_push_tags, :push_tags
|
|
14
|
+
alias_method :_timber_original_pop_tags, :pop_tags
|
|
15
|
+
|
|
16
|
+
def call(severity, timestamp, progname, msg)
|
|
17
|
+
if is_a?(Timber::Logger::Formatter)
|
|
18
|
+
# Don't convert the message into a string
|
|
19
|
+
super(severity, timestamp, progname, msg)
|
|
20
|
+
else
|
|
21
|
+
super(severity, timestamp, progname, "#{tags_text}#{msg}")
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# @private
|
|
29
|
+
module LoggerMethods
|
|
30
|
+
def self.included(klass)
|
|
31
|
+
klass.class_eval do
|
|
32
|
+
def add(severity, message = nil, progname = nil, &block)
|
|
33
|
+
if message.nil?
|
|
34
|
+
if block_given?
|
|
35
|
+
message = block.call
|
|
36
|
+
else
|
|
37
|
+
message = progname
|
|
38
|
+
progname = nil #No instance variable for this like Logger
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
if @logger.is_a?(Timber::Logger)
|
|
42
|
+
@logger.add(severity, message, progname)
|
|
43
|
+
else
|
|
44
|
+
@logger.add(severity, "#{tags_text}#{message}", progname)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def initialize
|
|
52
|
+
require "active_support/tagged_logging"
|
|
53
|
+
rescue LoadError => e
|
|
54
|
+
raise RequirementNotMetError.new(e.message)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def integrate!
|
|
58
|
+
if defined?(::ActiveSupport::TaggedLogging::Formatter)
|
|
59
|
+
return true if ::ActiveSupport::TaggedLogging::Formatter.include?(FormatterMethods)
|
|
60
|
+
|
|
61
|
+
::ActiveSupport::TaggedLogging::Formatter.send(:include, FormatterMethods)
|
|
62
|
+
else
|
|
63
|
+
return true if ::ActiveSupport::TaggedLogging.include?(LoggerMethods)
|
|
64
|
+
|
|
65
|
+
::ActiveSupport::TaggedLogging.send(:include, LoggerMethods)
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
require "timber/integrations/rack/exception_event"
|
|
2
|
+
require "timber/integrations/rack/http_context"
|
|
3
|
+
require "timber/integrations/rack/http_events"
|
|
4
|
+
require "timber/integrations/rack/user_context"
|
|
5
|
+
|
|
6
|
+
module Timber
|
|
7
|
+
module Integrations
|
|
8
|
+
module Rack
|
|
9
|
+
# All available middlewares. The order is relevant. Middlewares that set
|
|
10
|
+
# context are added first so that context is included in subsequent log lines.
|
|
11
|
+
def self.middlewares
|
|
12
|
+
@middlewares ||= [HTTPContext, UserContext, HTTPEvents, ExceptionEvent]
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
module Timber
|
|
2
|
+
module Integrations
|
|
3
|
+
module Rack
|
|
4
|
+
# Reponsible for capturing exceptions events within a Rack stack.
|
|
5
|
+
class ExceptionEvent
|
|
6
|
+
def initialize(app)
|
|
7
|
+
@app = app
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def call(env)
|
|
11
|
+
begin
|
|
12
|
+
status, headers, body = @app.call(env)
|
|
13
|
+
rescue Exception => exception
|
|
14
|
+
Config.instance.logger.fatal do
|
|
15
|
+
Events::Exception.new(
|
|
16
|
+
name: exception.class.name,
|
|
17
|
+
exception_message: exception.message,
|
|
18
|
+
backtrace: exception.backtrace
|
|
19
|
+
)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
raise exception
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module Timber
|
|
2
|
+
module Integrations
|
|
3
|
+
module Rack
|
|
4
|
+
# Reponsible for adding the HTTP context for applications that use `Rack`.
|
|
5
|
+
class HTTPContext
|
|
6
|
+
def initialize(app)
|
|
7
|
+
@app = app
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def call(env)
|
|
11
|
+
request = Util::Request.new(env)
|
|
12
|
+
context = Contexts::HTTP.new(
|
|
13
|
+
method: request.request_method,
|
|
14
|
+
path: request.path,
|
|
15
|
+
remote_addr: request.ip,
|
|
16
|
+
request_id: request.request_id
|
|
17
|
+
)
|
|
18
|
+
CurrentContext.with(context) do
|
|
19
|
+
@app.call(env)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
module Timber
|
|
2
|
+
module Integrations
|
|
3
|
+
module Rack
|
|
4
|
+
# Reponsible for capturing and logging HTTP server requests and response events.
|
|
5
|
+
class HTTPEvents
|
|
6
|
+
def initialize(app)
|
|
7
|
+
@app = app
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def call(env)
|
|
11
|
+
start = Time.now
|
|
12
|
+
request = Util::Request.new(env)
|
|
13
|
+
body = Config.instance.capture_http_bodies? ? request.body_content : nil
|
|
14
|
+
|
|
15
|
+
Config.instance.logger.info do
|
|
16
|
+
Events::HTTPServerRequest.new(
|
|
17
|
+
body: body,
|
|
18
|
+
headers: request.headers,
|
|
19
|
+
host: request.host,
|
|
20
|
+
method: request.request_method,
|
|
21
|
+
path: request.path,
|
|
22
|
+
port: request.port,
|
|
23
|
+
query_string: request.query_string,
|
|
24
|
+
request_id: request.request_id, # we insert this middleware after ActionDispatch::RequestId
|
|
25
|
+
scheme: request.scheme
|
|
26
|
+
)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
status, headers, body = @app.call(env)
|
|
30
|
+
|
|
31
|
+
Config.instance.logger.info do
|
|
32
|
+
time_ms = (Time.now - start) * 1000.0
|
|
33
|
+
Events::HTTPServerResponse.new(
|
|
34
|
+
headers: headers,
|
|
35
|
+
request_id: request.request_id,
|
|
36
|
+
status: status,
|
|
37
|
+
time_ms: time_ms
|
|
38
|
+
)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
[status, headers, body]
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
module Timber
|
|
2
|
+
module Integrations
|
|
3
|
+
module Rack
|
|
4
|
+
# Reponsible for adding the user context.
|
|
5
|
+
class UserContext
|
|
6
|
+
def initialize(app)
|
|
7
|
+
@app = app
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def call(env)
|
|
11
|
+
user = get_user(env)
|
|
12
|
+
if user
|
|
13
|
+
context = Contexts::User.new(
|
|
14
|
+
id: user_id(user),
|
|
15
|
+
name: user_name(user),
|
|
16
|
+
email: user_email(user)
|
|
17
|
+
)
|
|
18
|
+
CurrentContext.with(context) do
|
|
19
|
+
@app.call(env)
|
|
20
|
+
end
|
|
21
|
+
else
|
|
22
|
+
@app.call(env)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
def get_user(env)
|
|
28
|
+
if env['warden']
|
|
29
|
+
env['warden'].user
|
|
30
|
+
else
|
|
31
|
+
nil
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def user_id(user)
|
|
36
|
+
user.respond_to?(:id) ? user.id : nil
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def user_name(user)
|
|
40
|
+
if user.respond_to?(:name) && user.name.is_a?(String)
|
|
41
|
+
user.name
|
|
42
|
+
elsif user.respond_to?(:first_name) && user.first_name.is_a?(String) && user.respond_to?(:last_name) && user.last_name.is_a?(String)
|
|
43
|
+
"#{user.first_name} #{user.last_name}"
|
|
44
|
+
else
|
|
45
|
+
nil
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def user_email(user)
|
|
50
|
+
if user.respond_to?(:email) && user.email.is_a?(String)
|
|
51
|
+
user.email
|
|
52
|
+
else
|
|
53
|
+
nil
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
module Timber
|
|
2
|
+
module Integrations
|
|
3
|
+
module Rails
|
|
4
|
+
# Disables the default rail's rack logging. Note, we cannot simply uninstall this rack
|
|
5
|
+
# middleware because rails couples this with ActiveSupport instrumentation. As such,
|
|
6
|
+
# we simply disable the logger and let our Rack middleware handle the logging.
|
|
7
|
+
#
|
|
8
|
+
# See: https://github.com/rails/rails/blob/80e66cc4d90bf8c15d1a5f6e3152e90147f00772/railties/lib/rails/rack/logger.rb#L34
|
|
9
|
+
#
|
|
10
|
+
# @private
|
|
11
|
+
class RackLogger < Integrator
|
|
12
|
+
|
|
13
|
+
# @private
|
|
14
|
+
module InstanceMethods
|
|
15
|
+
LOGGER = ::Logger.new(nil)
|
|
16
|
+
|
|
17
|
+
def self.included(klass)
|
|
18
|
+
klass.class_eval do
|
|
19
|
+
private
|
|
20
|
+
# Rails 3.2 calls Rails.logger directly, so this is the first place
|
|
21
|
+
# we can mute the logger calls.
|
|
22
|
+
def started_request_message(*args)
|
|
23
|
+
""
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Rails > 3.2 uses a logger method. Muting logs is accomplished by
|
|
27
|
+
# passing a dummy logger instance with a nil log device.
|
|
28
|
+
def logger
|
|
29
|
+
LOGGER
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def initialize
|
|
36
|
+
require "rails/rack/logger"
|
|
37
|
+
rescue LoadError => e
|
|
38
|
+
raise RequirementNotMetError.new(e.message)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def integrate!
|
|
42
|
+
return true if ::Rails::Rack::Logger.include?(InstanceMethods)
|
|
43
|
+
|
|
44
|
+
::Rails::Rack::Logger.send(:include, InstanceMethods)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module Timber
|
|
2
|
+
# Base class for `Timber::Integrations::*`.
|
|
3
|
+
#
|
|
4
|
+
# @private
|
|
5
|
+
class Integrator
|
|
6
|
+
class RequirementNotMetError < StandardError; end
|
|
7
|
+
|
|
8
|
+
class << self
|
|
9
|
+
def integrate!(*args)
|
|
10
|
+
new(*args).integrate!
|
|
11
|
+
Config.instance.debug_logger.debug("Integrated #{name}") if Config.instance.debug_logger
|
|
12
|
+
true
|
|
13
|
+
# RequirementUnsatisfiedError is the only silent failure we support
|
|
14
|
+
rescue RequirementNotMetError => e
|
|
15
|
+
Config.instance.debug_logger.debug("Failed integrating #{name}: #{e.message}") if Config.instance.debug_logger
|
|
16
|
+
false
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def integrate!
|
|
21
|
+
raise NotImplementedError.new
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -80,8 +80,6 @@ module Timber
|
|
|
80
80
|
# each HTTP payload. If the queue exceeds this limit an HTTP request will be issued. Bigger
|
|
81
81
|
# payloads mean higher throughput, but also use more memory. Timber will not accept
|
|
82
82
|
# payloads larger than 1mb.
|
|
83
|
-
# @option attributes [Symbol] :debug (false) Whether to print debug output or not. This is also
|
|
84
|
-
# inferred from ENV['debug']. Output will be sent to `Timber::Config.logger`.
|
|
85
83
|
# @option attributes [Symbol] :flush_interval (1) How often the client should
|
|
86
84
|
# attempt to deliver logs to the Timber API in fractional seconds. The HTTP client buffers
|
|
87
85
|
# logs and this options represents how often that will happen, assuming `:batch_byte_size`
|
|
@@ -105,8 +103,7 @@ module Timber
|
|
|
105
103
|
# request_queue: Timber::LogDevices::HTTP::DroppingSizedQueue.new(3))
|
|
106
104
|
# Timber::Logger.new(http_log_device)
|
|
107
105
|
def initialize(api_key, options = {})
|
|
108
|
-
@api_key = api_key
|
|
109
|
-
@debug = options[:debug] || ENV['debug']
|
|
106
|
+
@api_key = api_key || raise(ArgumentError.new("The api_key parameter cannot be blank"))
|
|
110
107
|
@timber_url = URI.parse(options[:timber_url] || ENV['TIMBER_URL'] || TIMBER_URL)
|
|
111
108
|
@batch_size = options[:batch_size] || 1_000
|
|
112
109
|
@flush_interval = options[:flush_interval] || 1 # 1 second
|
|
@@ -126,7 +123,7 @@ module Timber
|
|
|
126
123
|
def write(msg)
|
|
127
124
|
@msg_queue.enqueue(msg)
|
|
128
125
|
if @msg_queue.full?
|
|
129
|
-
|
|
126
|
+
debug_logger.debug("Flushing timber buffer via write") if debug_logger
|
|
130
127
|
flush
|
|
131
128
|
end
|
|
132
129
|
true
|
|
@@ -140,8 +137,8 @@ module Timber
|
|
|
140
137
|
end
|
|
141
138
|
|
|
142
139
|
private
|
|
143
|
-
def
|
|
144
|
-
|
|
140
|
+
def debug_logger
|
|
141
|
+
Timber::Config.instance.debug_logger
|
|
145
142
|
end
|
|
146
143
|
|
|
147
144
|
def flush
|
|
@@ -163,7 +160,7 @@ module Timber
|
|
|
163
160
|
loop do
|
|
164
161
|
begin
|
|
165
162
|
if intervaled_flush_ready?
|
|
166
|
-
|
|
163
|
+
debug_logger.debug("Flushing timber buffer via the interval") if debug_logger
|
|
167
164
|
flush
|
|
168
165
|
end
|
|
169
166
|
sleep(0.1)
|
|
@@ -180,20 +177,20 @@ module Timber
|
|
|
180
177
|
def outlet
|
|
181
178
|
loop do
|
|
182
179
|
http = Net::HTTP.new(@timber_url.host, @timber_url.port)
|
|
183
|
-
http.set_debug_output(
|
|
180
|
+
http.set_debug_output(debug_logger) if debug_logger
|
|
184
181
|
http.use_ssl = true if @timber_url.scheme == 'https'
|
|
185
182
|
http.read_timeout = 30
|
|
186
183
|
http.ssl_timeout = 10
|
|
187
184
|
http.open_timeout = 10
|
|
188
185
|
|
|
189
186
|
begin
|
|
190
|
-
|
|
187
|
+
debug_logger.info("Starting Timber HTTP connection") if debug_logger
|
|
191
188
|
http.start do |conn|
|
|
192
189
|
num_reqs = 0
|
|
193
190
|
while num_reqs < @requests_per_conn
|
|
194
|
-
if
|
|
195
|
-
|
|
196
|
-
|
|
191
|
+
if debug_logger
|
|
192
|
+
debug_logger.debug("Waiting on next Timber request")
|
|
193
|
+
debug_logger.debug("Number of threads waiting on Timber request queue: #{@request_queue.num_waiting}")
|
|
197
194
|
end
|
|
198
195
|
|
|
199
196
|
# Blocks waiting for a request.
|
|
@@ -203,19 +200,19 @@ module Timber
|
|
|
203
200
|
begin
|
|
204
201
|
resp = conn.request(req)
|
|
205
202
|
rescue => e
|
|
206
|
-
|
|
203
|
+
debug_logger.error("Timber request error: #{e.message}") if debug_logger
|
|
207
204
|
next
|
|
208
205
|
ensure
|
|
209
206
|
@requests_in_flight -= 1
|
|
210
207
|
end
|
|
211
208
|
num_reqs += 1
|
|
212
|
-
|
|
209
|
+
debug_logger.debug("Timber request successful: #{resp.code}") if debug_logger
|
|
213
210
|
end
|
|
214
211
|
end
|
|
215
212
|
rescue => e
|
|
216
|
-
|
|
213
|
+
debug_logger.error("Timber request error: #{e.message}") if debug_logger
|
|
217
214
|
ensure
|
|
218
|
-
|
|
215
|
+
debug_logger.debug("Finishing Timber HTTP connection") if debug_logger
|
|
219
216
|
http.finish if http.started?
|
|
220
217
|
end
|
|
221
218
|
end
|
|
@@ -224,10 +221,6 @@ module Timber
|
|
|
224
221
|
def authorization_payload
|
|
225
222
|
@authorization_payload ||= "Basic #{Base64.urlsafe_encode64(@api_key).chomp}"
|
|
226
223
|
end
|
|
227
|
-
|
|
228
|
-
def logger
|
|
229
|
-
Config.instance.logger
|
|
230
|
-
end
|
|
231
224
|
end
|
|
232
225
|
end
|
|
233
226
|
end
|