timber 2.0.24 → 2.1.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +2 -2
- data/CHANGELOG +3 -0
- data/README.md +314 -59
- data/bin/timber +11 -2
- data/lib/timber.rb +2 -7
- data/lib/timber/cli.rb +16 -28
- data/lib/timber/cli/api.rb +80 -14
- data/lib/timber/cli/api/application.rb +30 -0
- data/lib/timber/cli/config_file.rb +66 -0
- data/lib/timber/cli/file_helper.rb +43 -0
- data/lib/timber/cli/installer.rb +58 -0
- data/lib/timber/cli/installers.rb +37 -0
- data/lib/timber/cli/installers/other.rb +47 -0
- data/lib/timber/cli/installers/rails.rb +255 -0
- data/lib/timber/cli/installers/root.rb +189 -0
- data/lib/timber/cli/io.rb +97 -0
- data/lib/timber/cli/io/ansi.rb +22 -0
- data/lib/timber/cli/io/messages.rb +213 -0
- data/lib/timber/cli/os_helper.rb +53 -0
- data/lib/timber/config.rb +97 -43
- data/lib/timber/config/integrations.rb +63 -0
- data/lib/timber/config/integrations/rack.rb +74 -0
- data/lib/timber/context.rb +13 -10
- data/lib/timber/contexts.rb +1 -0
- data/lib/timber/contexts/custom.rb +16 -3
- data/lib/timber/contexts/http.rb +10 -3
- data/lib/timber/contexts/organization.rb +4 -0
- data/lib/timber/contexts/release.rb +46 -0
- data/lib/timber/contexts/runtime.rb +7 -1
- data/lib/timber/contexts/session.rb +8 -1
- data/lib/timber/contexts/system.rb +5 -1
- data/lib/timber/contexts/user.rb +9 -2
- data/lib/timber/current_context.rb +43 -11
- data/lib/timber/events/controller_call.rb +4 -0
- data/lib/timber/events/custom.rb +13 -5
- data/lib/timber/events/exception.rb +4 -0
- data/lib/timber/events/http_client_request.rb +4 -0
- data/lib/timber/events/http_client_response.rb +4 -0
- data/lib/timber/events/http_server_request.rb +5 -0
- data/lib/timber/events/http_server_response.rb +15 -3
- data/lib/timber/events/sql_query.rb +3 -0
- data/lib/timber/events/template_render.rb +3 -0
- data/lib/timber/integration.rb +40 -0
- data/lib/timber/integrations.rb +21 -14
- data/lib/timber/integrations/action_controller.rb +18 -0
- data/lib/timber/integrations/action_controller/log_subscriber.rb +2 -0
- data/lib/timber/integrations/action_controller/log_subscriber/timber_log_subscriber.rb +6 -0
- data/lib/timber/integrations/action_dispatch.rb +23 -0
- data/lib/timber/integrations/action_dispatch/debug_exceptions.rb +2 -0
- data/lib/timber/integrations/action_view.rb +18 -0
- data/lib/timber/integrations/action_view/log_subscriber.rb +2 -0
- data/lib/timber/integrations/action_view/log_subscriber/timber_log_subscriber.rb +10 -0
- data/lib/timber/integrations/active_record.rb +18 -0
- data/lib/timber/integrations/active_record/log_subscriber.rb +2 -0
- data/lib/timber/integrations/active_record/log_subscriber/timber_log_subscriber.rb +8 -0
- data/lib/timber/integrations/rack.rb +12 -2
- data/lib/timber/integrations/rack/exception_event.rb +38 -5
- data/lib/timber/integrations/rack/http_context.rb +4 -6
- data/lib/timber/integrations/rack/http_events.rb +177 -27
- data/lib/timber/integrations/rack/middleware.rb +28 -0
- data/lib/timber/integrations/rack/session_context.rb +5 -6
- data/lib/timber/integrations/rack/user_context.rb +90 -43
- data/lib/timber/integrations/rails.rb +22 -0
- data/lib/timber/integrations/rails/rack_logger.rb +2 -0
- data/lib/timber/integrator.rb +18 -3
- data/lib/timber/log_devices/http.rb +107 -99
- data/lib/timber/log_devices/http/dropping_sized_queue.rb +26 -0
- data/lib/timber/log_devices/http/flushable_sized_queue.rb +42 -0
- data/lib/timber/log_entry.rb +14 -2
- data/lib/timber/logger.rb +51 -36
- data/lib/timber/overrides.rb +2 -0
- data/lib/timber/overrides/active_support_3_tagged_logging.rb +103 -0
- data/lib/timber/overrides/active_support_tagged_logging.rb +53 -90
- data/lib/timber/timer.rb +21 -0
- data/lib/timber/util/hash.rb +1 -1
- data/lib/timber/util/http_event.rb +16 -3
- data/lib/timber/version.rb +1 -1
- data/spec/support/timber.rb +2 -3
- data/spec/timber/cli/installers/rails_spec.rb +160 -0
- data/spec/timber/cli/installers/root_spec.rb +100 -0
- data/spec/timber/config_spec.rb +28 -0
- data/spec/timber/current_context_spec.rb +61 -12
- data/spec/timber/events/custom_spec.rb +13 -2
- data/spec/timber/events/exception_spec.rb +15 -0
- data/spec/timber/events/http_server_request_spec.rb +3 -3
- data/spec/timber/integrations/rack/http_events_spec.rb +101 -0
- data/spec/timber/log_devices/http_spec.rb +20 -4
- data/spec/timber/log_entry_spec.rb +2 -1
- data/spec/timber/logger_spec.rb +8 -8
- metadata +40 -9
- data/benchmarks/rails.rb +0 -122
- data/lib/timber/cli/application.rb +0 -28
- data/lib/timber/cli/install.rb +0 -196
- data/lib/timber/cli/io_helper.rb +0 -65
- data/lib/timber/cli/messages.rb +0 -180
- data/lib/timber/integrations/active_support/tagged_logging.rb +0 -71
@@ -1,3 +1,6 @@
|
|
1
|
+
require "timber/event"
|
2
|
+
require "timber/util"
|
3
|
+
|
1
4
|
module Timber
|
2
5
|
module Events
|
3
6
|
# The controller call event tracks controller invocations. For example, this line in Rails:
|
@@ -23,6 +26,7 @@ module Timber
|
|
23
26
|
end
|
24
27
|
alias to_h to_hash
|
25
28
|
|
29
|
+
# Builds a hash representation of containing simply objects, suitable for serialization.
|
26
30
|
def as_json(_options = {})
|
27
31
|
{:controller_call => to_hash}
|
28
32
|
end
|
data/lib/timber/events/custom.rb
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
require "timber/event"
|
2
|
+
require "timber/util"
|
3
|
+
|
1
4
|
module Timber
|
2
5
|
module Events
|
3
6
|
# Allows for custom events that aren't covered elsewhere.
|
@@ -22,7 +25,15 @@ module Timber
|
|
22
25
|
def initialize(attributes)
|
23
26
|
@type = attributes[:type] || raise(ArgumentError.new(":type is required"))
|
24
27
|
@message = attributes[:message] || raise(ArgumentError.new(":message is required"))
|
25
|
-
|
28
|
+
|
29
|
+
data = attributes[:data]
|
30
|
+
|
31
|
+
if data.is_a?(Hash) && data[:time_ms].is_a?(Time)
|
32
|
+
data[:time_ms] = Timer.duration_ms(data[:time_ms])
|
33
|
+
@message << " in #{data[:time_ms]}ms"
|
34
|
+
end
|
35
|
+
|
36
|
+
@data = data
|
26
37
|
end
|
27
38
|
|
28
39
|
def to_hash
|
@@ -30,13 +41,10 @@ module Timber
|
|
30
41
|
end
|
31
42
|
alias to_h to_hash
|
32
43
|
|
44
|
+
# Builds a hash representation of containing simply objects, suitable for serialization.
|
33
45
|
def as_json(_options = {})
|
34
46
|
{:custom => to_hash}
|
35
47
|
end
|
36
|
-
|
37
|
-
def to_json(options = {})
|
38
|
-
as_json().to_json(options)
|
39
|
-
end
|
40
48
|
end
|
41
49
|
end
|
42
50
|
end
|
@@ -1,3 +1,6 @@
|
|
1
|
+
require "timber/event"
|
2
|
+
require "timber/util"
|
3
|
+
|
1
4
|
module Timber
|
2
5
|
module Events
|
3
6
|
# The exception event is used to track exceptions.
|
@@ -25,6 +28,7 @@ module Timber
|
|
25
28
|
end
|
26
29
|
alias to_h to_hash
|
27
30
|
|
31
|
+
# Builds a hash representation of containing simply objects, suitable for serialization.
|
28
32
|
def as_json(_options = {})
|
29
33
|
{:exception => to_hash}
|
30
34
|
end
|
@@ -1,3 +1,6 @@
|
|
1
|
+
require "timber/event"
|
2
|
+
require "timber/util"
|
3
|
+
|
1
4
|
module Timber
|
2
5
|
module Events
|
3
6
|
# The HTTP client request event tracks *outgoing* HTTP requests giving you structured insight
|
@@ -30,6 +33,7 @@ module Timber
|
|
30
33
|
end
|
31
34
|
alias to_h to_hash
|
32
35
|
|
36
|
+
# Builds a hash representation of containing simply objects, suitable for serialization.
|
33
37
|
def as_json(_options = {})
|
34
38
|
{:http_client_request => to_hash}
|
35
39
|
end
|
@@ -1,3 +1,6 @@
|
|
1
|
+
require "timber/event"
|
2
|
+
require "timber/util"
|
3
|
+
|
1
4
|
module Timber
|
2
5
|
module Events
|
3
6
|
# The HTTP client response event tracks responses for *outgoing* HTTP *requests*.
|
@@ -25,6 +28,7 @@ module Timber
|
|
25
28
|
end
|
26
29
|
alias to_h to_hash
|
27
30
|
|
31
|
+
# Builds a hash representation of containing simply objects, suitable for serialization.
|
28
32
|
def as_json(_options = {})
|
29
33
|
{:http_client_response => to_hash}
|
30
34
|
end
|
@@ -1,3 +1,6 @@
|
|
1
|
+
require "timber/event"
|
2
|
+
require "timber/util"
|
3
|
+
|
1
4
|
module Timber
|
2
5
|
module Events
|
3
6
|
# The HTTP server request event tracks incoming HTTP requests to your HTTP server.
|
@@ -10,6 +13,7 @@ module Timber
|
|
10
13
|
:scheme
|
11
14
|
|
12
15
|
def initialize(attributes)
|
16
|
+
@body = attributes[:body] && Util::HTTPEvent.normalize_body(attributes[:body])
|
13
17
|
@headers = Util::HTTPEvent.normalize_headers(attributes[:headers])
|
14
18
|
@host = attributes[:host] || raise(ArgumentError.new(":host is required"))
|
15
19
|
@method = Util::HTTPEvent.normalize_method(attributes[:method]) || raise(ArgumentError.new(":method is required"))
|
@@ -26,6 +30,7 @@ module Timber
|
|
26
30
|
end
|
27
31
|
alias to_h to_hash
|
28
32
|
|
33
|
+
# Builds a hash representation of containing simply objects, suitable for serialization.
|
29
34
|
def as_json(_options = {})
|
30
35
|
{:http_server_request => to_hash}
|
31
36
|
end
|
@@ -1,3 +1,6 @@
|
|
1
|
+
require "timber/event"
|
2
|
+
require "timber/util"
|
3
|
+
|
1
4
|
module Timber
|
2
5
|
module Events
|
3
6
|
# The HTTP server response event tracks outgoing HTTP responses that you send
|
@@ -6,10 +9,12 @@ module Timber
|
|
6
9
|
# @note This event should be installed automatically through integrations,
|
7
10
|
# such as the {Integrations::ActionController::LogSubscriber} integration.
|
8
11
|
class HTTPServerResponse < Timber::Event
|
9
|
-
attr_reader :headers, :request_id, :status, :time_ms
|
12
|
+
attr_reader :body, :headers, :http_context, :request_id, :status, :time_ms
|
10
13
|
|
11
14
|
def initialize(attributes)
|
15
|
+
@body = attributes[:body] && Util::HTTPEvent.normalize_body(attributes[:body])
|
12
16
|
@headers = Util::HTTPEvent.normalize_headers(attributes[:headers])
|
17
|
+
@http_context = attributes[:http_context]
|
13
18
|
@request_id = attributes[:request_id]
|
14
19
|
@status = attributes[:status] || raise(ArgumentError.new(":status is required"))
|
15
20
|
@time_ms = attributes[:time_ms] || raise(ArgumentError.new(":time_ms is required"))
|
@@ -17,16 +22,23 @@ module Timber
|
|
17
22
|
end
|
18
23
|
|
19
24
|
def to_hash
|
20
|
-
{headers: headers, request_id: request_id, status: status, time_ms: time_ms}
|
25
|
+
{body: body, headers: headers, request_id: request_id, status: status, time_ms: time_ms}
|
21
26
|
end
|
22
27
|
alias to_h to_hash
|
23
28
|
|
29
|
+
# Builds a hash representation of containing simply objects, suitable for serialization.
|
24
30
|
def as_json(_options = {})
|
25
31
|
{:http_server_response => to_hash}
|
26
32
|
end
|
27
33
|
|
34
|
+
# Returns the human readable log message for this event.
|
28
35
|
def message
|
29
|
-
|
36
|
+
if http_context
|
37
|
+
"#{http_context[:method]} #{http_context[:path]} sent #{status} #{status_description} " \
|
38
|
+
"in #{time_ms}ms"
|
39
|
+
else
|
40
|
+
"Completed #{status} #{status_description} in #{time_ms}ms"
|
41
|
+
end
|
30
42
|
end
|
31
43
|
|
32
44
|
def status_description
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require "timber/event"
|
2
|
+
|
1
3
|
module Timber
|
2
4
|
module Events
|
3
5
|
# The SQL query event tracks sql queries to your database.
|
@@ -19,6 +21,7 @@ module Timber
|
|
19
21
|
end
|
20
22
|
alias to_h to_hash
|
21
23
|
|
24
|
+
# Builds a hash representation of containing simply objects, suitable for serialization.
|
22
25
|
def as_json(_options = {})
|
23
26
|
{:sql_query => to_hash}
|
24
27
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require "timber/event"
|
2
|
+
|
1
3
|
module Timber
|
2
4
|
module Events
|
3
5
|
# The template render event track template renderings and their performance.
|
@@ -19,6 +21,7 @@ module Timber
|
|
19
21
|
end
|
20
22
|
alias to_h to_hash
|
21
23
|
|
24
|
+
# Builds a hash representation of containing simply objects, suitable for serialization.
|
22
25
|
def as_json(_options = {})
|
23
26
|
{:template_render => to_hash}
|
24
27
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Timber
|
2
|
+
# An integration represent an integration for an entire library. For example, `Rack`.
|
3
|
+
# While the Timber `Rack` integration is comprised of multiple middlewares, the
|
4
|
+
# `Timber::Integrations::Rack` module is an entire integration that extends this module.
|
5
|
+
module Integration
|
6
|
+
# Easily sisable entire library integrations. This is like removing the code from
|
7
|
+
# Timber. It will not touch this library and the library will function as it would
|
8
|
+
# without Timber.
|
9
|
+
#
|
10
|
+
# @example
|
11
|
+
# Timber::Integrations::ActiveRecord.enabled = false
|
12
|
+
def enabled=(value)
|
13
|
+
@enabled = value
|
14
|
+
end
|
15
|
+
|
16
|
+
# Accessor method for {#enabled=}
|
17
|
+
def enabled?
|
18
|
+
@enabled != false
|
19
|
+
end
|
20
|
+
|
21
|
+
# Silences a library's logs. This ensures that logs are not generated at all
|
22
|
+
# from this library.
|
23
|
+
#
|
24
|
+
# @example
|
25
|
+
# Timber::Integrations::ActiveRecord.silence = true
|
26
|
+
def silence=(value)
|
27
|
+
@silence = value
|
28
|
+
end
|
29
|
+
|
30
|
+
# Accessor method for {#silence=}
|
31
|
+
def silence?
|
32
|
+
@silence == true
|
33
|
+
end
|
34
|
+
|
35
|
+
# Abstract method that each integration must implement.
|
36
|
+
def integrate!
|
37
|
+
raise NotImplementedError.new
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/lib/timber/integrations.rb
CHANGED
@@ -1,22 +1,29 @@
|
|
1
|
-
require "timber/integrations/action_controller
|
2
|
-
require "timber/integrations/action_dispatch
|
3
|
-
require "timber/integrations/action_view
|
4
|
-
require "timber/integrations/active_record
|
5
|
-
require "timber/integrations/active_support/tagged_logging"
|
1
|
+
require "timber/integrations/action_controller"
|
2
|
+
require "timber/integrations/action_dispatch"
|
3
|
+
require "timber/integrations/action_view"
|
4
|
+
require "timber/integrations/active_record"
|
6
5
|
require "timber/integrations/rack"
|
7
|
-
require "timber/integrations/rails
|
6
|
+
require "timber/integrations/rails"
|
8
7
|
|
9
8
|
module Timber
|
10
|
-
# Namespace for all integrations.
|
11
|
-
#
|
9
|
+
# Namespace for all integrations. Each integration provides it's own settings.
|
10
|
+
# And all integrations can be disabled with the {.enabled=} class method.
|
12
11
|
module Integrations
|
12
|
+
# Disable / enable _all_ integrations with one setting.
|
13
|
+
def self.enabled=(value)
|
14
|
+
ActionController.enabled = value
|
15
|
+
ActionView.enabled = value
|
16
|
+
ActiveRecord.enabled = value
|
17
|
+
Rack.enabled = value
|
18
|
+
end
|
19
|
+
|
20
|
+
# Integrates all enabled integrations in one call.
|
13
21
|
def self.integrate!
|
14
|
-
ActionController
|
15
|
-
ActionDispatch
|
16
|
-
ActionView
|
17
|
-
ActiveRecord
|
18
|
-
|
19
|
-
Rails::RackLogger.integrate!
|
22
|
+
ActionController.integrate!
|
23
|
+
ActionDispatch.integrate!
|
24
|
+
ActionView.integrate!
|
25
|
+
ActiveRecord.integrate!
|
26
|
+
Rails.integrate!
|
20
27
|
end
|
21
28
|
end
|
22
29
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require "timber/integration"
|
2
|
+
require "timber/integrations/action_controller/log_subscriber"
|
3
|
+
|
4
|
+
module Timber
|
5
|
+
module Integrations
|
6
|
+
# Module for holding *all* ActionController integrations. See {Integration} for
|
7
|
+
# configuration details for all integrations.
|
8
|
+
module ActionController
|
9
|
+
extend Integration
|
10
|
+
|
11
|
+
def self.integrate!
|
12
|
+
return false if !enabled?
|
13
|
+
|
14
|
+
LogSubscriber.integrate!
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -10,6 +10,8 @@ module Timber
|
|
10
10
|
# @private
|
11
11
|
class TimberLogSubscriber < ::ActionController::LogSubscriber
|
12
12
|
def start_processing(event)
|
13
|
+
return true if silence?
|
14
|
+
|
13
15
|
info do
|
14
16
|
payload = event.payload
|
15
17
|
params = payload[:params].except(*INTERNAL_PARAMS)
|
@@ -33,6 +35,10 @@ module Timber
|
|
33
35
|
payload[:formats].first # rails 3.X
|
34
36
|
end
|
35
37
|
end
|
38
|
+
|
39
|
+
def silence?
|
40
|
+
ActionController.silence?
|
41
|
+
end
|
36
42
|
end
|
37
43
|
end
|
38
44
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require "timber/integration"
|
2
|
+
require "timber/integrations/rack/exception_event"
|
3
|
+
require "timber/integrations/action_dispatch/debug_exceptions"
|
4
|
+
|
5
|
+
module Timber
|
6
|
+
module Integrations
|
7
|
+
# Module for holding *all* ActionDispatch integrations. This module does *not*
|
8
|
+
# extend {Integration} because it's dependent on {Rack::ExceptionEvent}. This
|
9
|
+
# module simply disables the exception tracking middleware so that our middleware
|
10
|
+
# works as expected.
|
11
|
+
module ActionDispatch
|
12
|
+
def self.enabled?
|
13
|
+
Rack::ExceptionEvent.enabled?
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.integrate!
|
17
|
+
return false if !enabled?
|
18
|
+
|
19
|
+
DebugExceptions.integrate!
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require "timber/integration"
|
2
|
+
require "timber/integrations/action_view/log_subscriber"
|
3
|
+
|
4
|
+
module Timber
|
5
|
+
module Integrations
|
6
|
+
# Module for holding *all* ActionView integrations. See {Integration} for
|
7
|
+
# configuration details for all integrations.
|
8
|
+
module ActionView
|
9
|
+
extend Integration
|
10
|
+
|
11
|
+
def self.integrate!
|
12
|
+
return false if !enabled?
|
13
|
+
|
14
|
+
LogSubscriber.integrate!
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -10,6 +10,8 @@ module Timber
|
|
10
10
|
# @private
|
11
11
|
class TimberLogSubscriber < ::ActionView::LogSubscriber
|
12
12
|
def render_template(event)
|
13
|
+
return true if silence?
|
14
|
+
|
13
15
|
info do
|
14
16
|
full_name = from_rails_root(event.payload[:identifier])
|
15
17
|
message = " Rendered #{full_name}"
|
@@ -25,6 +27,8 @@ module Timber
|
|
25
27
|
end
|
26
28
|
|
27
29
|
def render_partial(event)
|
30
|
+
return true if silence?
|
31
|
+
|
28
32
|
info do
|
29
33
|
full_name = from_rails_root(event.payload[:identifier])
|
30
34
|
message = " Rendered #{full_name}"
|
@@ -41,6 +45,8 @@ module Timber
|
|
41
45
|
end
|
42
46
|
|
43
47
|
def render_collection(event)
|
48
|
+
return true if silence?
|
49
|
+
|
44
50
|
if respond_to?(:render_count, true)
|
45
51
|
info do
|
46
52
|
identifier = event.payload[:identifier] || "templates"
|
@@ -66,6 +72,10 @@ module Timber
|
|
66
72
|
# rendering a template. If you disagree, please feel free to open a PR and we
|
67
73
|
# can make this an option.
|
68
74
|
end
|
75
|
+
|
76
|
+
def silence?
|
77
|
+
ActionView.silence?
|
78
|
+
end
|
69
79
|
end
|
70
80
|
end
|
71
81
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require "timber/integration"
|
2
|
+
require "timber/integrations/active_record/log_subscriber"
|
3
|
+
|
4
|
+
module Timber
|
5
|
+
module Integrations
|
6
|
+
# Module for holding *all* ActiveRecord integrations. See {Integration} for
|
7
|
+
# configuration details for all integrations.
|
8
|
+
module ActiveRecord
|
9
|
+
extend Integration
|
10
|
+
|
11
|
+
def self.integrate!
|
12
|
+
return false if !enabled?
|
13
|
+
|
14
|
+
LogSubscriber.integrate!
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|