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.
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