timber 2.0.24 → 2.1.0.rc1

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.
Files changed (97) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +2 -2
  3. data/CHANGELOG +3 -0
  4. data/README.md +314 -59
  5. data/bin/timber +11 -2
  6. data/lib/timber.rb +2 -7
  7. data/lib/timber/cli.rb +16 -28
  8. data/lib/timber/cli/api.rb +80 -14
  9. data/lib/timber/cli/api/application.rb +30 -0
  10. data/lib/timber/cli/config_file.rb +66 -0
  11. data/lib/timber/cli/file_helper.rb +43 -0
  12. data/lib/timber/cli/installer.rb +58 -0
  13. data/lib/timber/cli/installers.rb +37 -0
  14. data/lib/timber/cli/installers/other.rb +47 -0
  15. data/lib/timber/cli/installers/rails.rb +255 -0
  16. data/lib/timber/cli/installers/root.rb +189 -0
  17. data/lib/timber/cli/io.rb +97 -0
  18. data/lib/timber/cli/io/ansi.rb +22 -0
  19. data/lib/timber/cli/io/messages.rb +213 -0
  20. data/lib/timber/cli/os_helper.rb +53 -0
  21. data/lib/timber/config.rb +97 -43
  22. data/lib/timber/config/integrations.rb +63 -0
  23. data/lib/timber/config/integrations/rack.rb +74 -0
  24. data/lib/timber/context.rb +13 -10
  25. data/lib/timber/contexts.rb +1 -0
  26. data/lib/timber/contexts/custom.rb +16 -3
  27. data/lib/timber/contexts/http.rb +10 -3
  28. data/lib/timber/contexts/organization.rb +4 -0
  29. data/lib/timber/contexts/release.rb +46 -0
  30. data/lib/timber/contexts/runtime.rb +7 -1
  31. data/lib/timber/contexts/session.rb +8 -1
  32. data/lib/timber/contexts/system.rb +5 -1
  33. data/lib/timber/contexts/user.rb +9 -2
  34. data/lib/timber/current_context.rb +43 -11
  35. data/lib/timber/events/controller_call.rb +4 -0
  36. data/lib/timber/events/custom.rb +13 -5
  37. data/lib/timber/events/exception.rb +4 -0
  38. data/lib/timber/events/http_client_request.rb +4 -0
  39. data/lib/timber/events/http_client_response.rb +4 -0
  40. data/lib/timber/events/http_server_request.rb +5 -0
  41. data/lib/timber/events/http_server_response.rb +15 -3
  42. data/lib/timber/events/sql_query.rb +3 -0
  43. data/lib/timber/events/template_render.rb +3 -0
  44. data/lib/timber/integration.rb +40 -0
  45. data/lib/timber/integrations.rb +21 -14
  46. data/lib/timber/integrations/action_controller.rb +18 -0
  47. data/lib/timber/integrations/action_controller/log_subscriber.rb +2 -0
  48. data/lib/timber/integrations/action_controller/log_subscriber/timber_log_subscriber.rb +6 -0
  49. data/lib/timber/integrations/action_dispatch.rb +23 -0
  50. data/lib/timber/integrations/action_dispatch/debug_exceptions.rb +2 -0
  51. data/lib/timber/integrations/action_view.rb +18 -0
  52. data/lib/timber/integrations/action_view/log_subscriber.rb +2 -0
  53. data/lib/timber/integrations/action_view/log_subscriber/timber_log_subscriber.rb +10 -0
  54. data/lib/timber/integrations/active_record.rb +18 -0
  55. data/lib/timber/integrations/active_record/log_subscriber.rb +2 -0
  56. data/lib/timber/integrations/active_record/log_subscriber/timber_log_subscriber.rb +8 -0
  57. data/lib/timber/integrations/rack.rb +12 -2
  58. data/lib/timber/integrations/rack/exception_event.rb +38 -5
  59. data/lib/timber/integrations/rack/http_context.rb +4 -6
  60. data/lib/timber/integrations/rack/http_events.rb +177 -27
  61. data/lib/timber/integrations/rack/middleware.rb +28 -0
  62. data/lib/timber/integrations/rack/session_context.rb +5 -6
  63. data/lib/timber/integrations/rack/user_context.rb +90 -43
  64. data/lib/timber/integrations/rails.rb +22 -0
  65. data/lib/timber/integrations/rails/rack_logger.rb +2 -0
  66. data/lib/timber/integrator.rb +18 -3
  67. data/lib/timber/log_devices/http.rb +107 -99
  68. data/lib/timber/log_devices/http/dropping_sized_queue.rb +26 -0
  69. data/lib/timber/log_devices/http/flushable_sized_queue.rb +42 -0
  70. data/lib/timber/log_entry.rb +14 -2
  71. data/lib/timber/logger.rb +51 -36
  72. data/lib/timber/overrides.rb +2 -0
  73. data/lib/timber/overrides/active_support_3_tagged_logging.rb +103 -0
  74. data/lib/timber/overrides/active_support_tagged_logging.rb +53 -90
  75. data/lib/timber/timer.rb +21 -0
  76. data/lib/timber/util/hash.rb +1 -1
  77. data/lib/timber/util/http_event.rb +16 -3
  78. data/lib/timber/version.rb +1 -1
  79. data/spec/support/timber.rb +2 -3
  80. data/spec/timber/cli/installers/rails_spec.rb +160 -0
  81. data/spec/timber/cli/installers/root_spec.rb +100 -0
  82. data/spec/timber/config_spec.rb +28 -0
  83. data/spec/timber/current_context_spec.rb +61 -12
  84. data/spec/timber/events/custom_spec.rb +13 -2
  85. data/spec/timber/events/exception_spec.rb +15 -0
  86. data/spec/timber/events/http_server_request_spec.rb +3 -3
  87. data/spec/timber/integrations/rack/http_events_spec.rb +101 -0
  88. data/spec/timber/log_devices/http_spec.rb +20 -4
  89. data/spec/timber/log_entry_spec.rb +2 -1
  90. data/spec/timber/logger_spec.rb +8 -8
  91. metadata +40 -9
  92. data/benchmarks/rails.rb +0 -122
  93. data/lib/timber/cli/application.rb +0 -28
  94. data/lib/timber/cli/install.rb +0 -196
  95. data/lib/timber/cli/io_helper.rb +0 -65
  96. data/lib/timber/cli/messages.rb +0 -180
  97. 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
@@ -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
- @data = attributes[:data]
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
- "Completed #{status} #{status_description} in #{time_ms}ms"
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
@@ -1,22 +1,29 @@
1
- require "timber/integrations/action_controller/log_subscriber"
2
- require "timber/integrations/action_dispatch/debug_exceptions"
3
- require "timber/integrations/action_view/log_subscriber"
4
- require "timber/integrations/active_record/log_subscriber"
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/rack_logger"
6
+ require "timber/integrations/rails"
8
7
 
9
8
  module Timber
10
- # Namespace for all integrations.
11
- # @private
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::LogSubscriber.integrate!
15
- ActionDispatch::DebugExceptions.integrate!
16
- ActionView::LogSubscriber.integrate!
17
- ActiveRecord::LogSubscriber.integrate!
18
- ActiveSupport::TaggedLogging.integrate!
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
@@ -1,3 +1,5 @@
1
+ require "timber/integrator"
2
+
1
3
  module Timber
2
4
  module Integrations
3
5
  module ActionController
@@ -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
@@ -1,3 +1,5 @@
1
+ require "timber/integrator"
2
+
1
3
  module Timber
2
4
  module Integrations
3
5
  module ActionDispatch
@@ -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
@@ -1,3 +1,5 @@
1
+ require "timber/integrator"
2
+
1
3
  module Timber
2
4
  module Integrations
3
5
  module ActionView
@@ -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