skylight 5.0.0.beta4 → 5.1.0.beta2

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 (80) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +399 -362
  3. data/CLA.md +1 -1
  4. data/CONTRIBUTING.md +1 -1
  5. data/LICENSE.md +7 -17
  6. data/README.md +1 -1
  7. data/ext/extconf.rb +42 -54
  8. data/ext/libskylight.yml +10 -5
  9. data/lib/skylight.rb +20 -30
  10. data/lib/skylight/api.rb +22 -18
  11. data/lib/skylight/cli.rb +47 -46
  12. data/lib/skylight/cli/doctor.rb +50 -50
  13. data/lib/skylight/cli/helpers.rb +19 -19
  14. data/lib/skylight/cli/merger.rb +141 -139
  15. data/lib/skylight/config.rb +267 -310
  16. data/lib/skylight/deprecation.rb +4 -4
  17. data/lib/skylight/errors.rb +3 -4
  18. data/lib/skylight/extensions.rb +17 -29
  19. data/lib/skylight/extensions/source_location.rb +128 -128
  20. data/lib/skylight/formatters/http.rb +1 -3
  21. data/lib/skylight/gc.rb +30 -40
  22. data/lib/skylight/helpers.rb +57 -30
  23. data/lib/skylight/instrumenter.rb +25 -18
  24. data/lib/skylight/middleware.rb +31 -35
  25. data/lib/skylight/native.rb +8 -10
  26. data/lib/skylight/native_ext_fetcher.rb +10 -12
  27. data/lib/skylight/normalizers.rb +43 -38
  28. data/lib/skylight/normalizers/action_controller/process_action.rb +24 -25
  29. data/lib/skylight/normalizers/action_controller/send_file.rb +7 -6
  30. data/lib/skylight/normalizers/action_dispatch/route_set.rb +7 -7
  31. data/lib/skylight/normalizers/active_job/perform.rb +48 -44
  32. data/lib/skylight/normalizers/active_model_serializers/render.rb +7 -3
  33. data/lib/skylight/normalizers/active_storage.rb +11 -13
  34. data/lib/skylight/normalizers/active_support/cache.rb +1 -12
  35. data/lib/skylight/normalizers/coach/handler_finish.rb +1 -3
  36. data/lib/skylight/normalizers/default.rb +1 -9
  37. data/lib/skylight/normalizers/faraday/request.rb +1 -3
  38. data/lib/skylight/normalizers/grape/endpoint.rb +13 -19
  39. data/lib/skylight/normalizers/grape/endpoint_run.rb +16 -18
  40. data/lib/skylight/normalizers/grape/endpoint_run_filters.rb +1 -3
  41. data/lib/skylight/normalizers/graphql/base.rb +23 -28
  42. data/lib/skylight/normalizers/render.rb +19 -21
  43. data/lib/skylight/normalizers/shrine.rb +32 -0
  44. data/lib/skylight/normalizers/sql.rb +4 -4
  45. data/lib/skylight/probes.rb +38 -46
  46. data/lib/skylight/probes/action_controller.rb +32 -28
  47. data/lib/skylight/probes/action_dispatch/request_id.rb +9 -5
  48. data/lib/skylight/probes/action_dispatch/routing/route_set.rb +7 -5
  49. data/lib/skylight/probes/action_view.rb +9 -10
  50. data/lib/skylight/probes/active_job_enqueue.rb +3 -9
  51. data/lib/skylight/probes/active_model_serializers.rb +8 -8
  52. data/lib/skylight/probes/delayed_job.rb +37 -42
  53. data/lib/skylight/probes/elasticsearch.rb +4 -6
  54. data/lib/skylight/probes/excon.rb +1 -1
  55. data/lib/skylight/probes/excon/middleware.rb +22 -23
  56. data/lib/skylight/probes/graphql.rb +2 -7
  57. data/lib/skylight/probes/middleware.rb +14 -5
  58. data/lib/skylight/probes/mongo.rb +83 -91
  59. data/lib/skylight/probes/net_http.rb +1 -1
  60. data/lib/skylight/probes/redis.rb +5 -17
  61. data/lib/skylight/probes/sequel.rb +7 -11
  62. data/lib/skylight/probes/sinatra.rb +8 -5
  63. data/lib/skylight/probes/tilt.rb +2 -4
  64. data/lib/skylight/railtie.rb +121 -135
  65. data/lib/skylight/sidekiq.rb +4 -5
  66. data/lib/skylight/subscriber.rb +31 -33
  67. data/lib/skylight/test.rb +89 -84
  68. data/lib/skylight/trace.rb +121 -115
  69. data/lib/skylight/user_config.rb +14 -17
  70. data/lib/skylight/util/clock.rb +1 -0
  71. data/lib/skylight/util/component.rb +18 -21
  72. data/lib/skylight/util/deploy.rb +11 -13
  73. data/lib/skylight/util/http.rb +104 -105
  74. data/lib/skylight/util/logging.rb +4 -6
  75. data/lib/skylight/util/lru_cache.rb +2 -6
  76. data/lib/skylight/util/platform.rb +2 -6
  77. data/lib/skylight/util/ssl.rb +1 -25
  78. data/lib/skylight/version.rb +1 -1
  79. data/lib/skylight/vm/gc.rb +1 -9
  80. metadata +20 -5
@@ -7,42 +7,46 @@ module Skylight
7
7
  ::ActionController::Instrumentation.class_eval do
8
8
  private
9
9
 
10
- alias_method :append_info_to_payload_without_sk, :append_info_to_payload
11
- def append_info_to_payload(payload)
12
- append_info_to_payload_without_sk(payload)
10
+ alias_method :append_info_to_payload_without_sk, :append_info_to_payload
11
+ def append_info_to_payload(payload)
12
+ append_info_to_payload_without_sk(payload)
13
13
 
14
- payload[:sk_rendered_format] = sk_rendered_mime.try(:ref)
15
- payload[:sk_variant] = request.respond_to?(:variant) ? request.variant : nil
16
- end
14
+ payload[:sk_rendered_format] = sk_rendered_mime.try(:ref)
15
+ payload[:sk_variant] = request.respond_to?(:variant) ? request.variant : nil
16
+ end
17
17
 
18
- def sk_rendered_mime
19
- if respond_to?(:media_type)
20
- mt = media_type
21
- return mt && Mime::Type.lookup(mt)
22
- end
18
+ def sk_rendered_mime
19
+ if respond_to?(:media_type)
20
+ mt = media_type
21
+ return mt && Mime::Type.lookup(mt)
22
+ end
23
23
 
24
- if content_type.is_a?(Mime::Type)
25
- content_type
26
- elsif content_type.respond_to?(:to_s)
27
- type_str = content_type.to_s.split(";").first
28
- Mime::Type.lookup(type_str) unless type_str.blank?
29
- elsif respond_to?(:rendered_format) && rendered_format
30
- rendered_format
31
- end
32
- rescue
33
- # There are cases in which actionpack can return
34
- # a stringified representation of a Mime::NullType instance,
35
- # which is invalid for a number of reasons. This string raises
36
- # errors when piped through Mime::Type.lookup, so it's probably
37
- # best to just return nil in those cases.
38
- nil
24
+ if content_type.is_a?(Mime::Type)
25
+ content_type
26
+ elsif content_type.respond_to?(:to_s)
27
+ type_str = content_type.to_s.split(";").first
28
+ Mime::Type.lookup(type_str) unless type_str.blank?
29
+ elsif respond_to?(:rendered_format) && rendered_format
30
+ rendered_format
39
31
  end
32
+ rescue StandardError
33
+ # There are cases in which actionpack can return
34
+ # a stringified representation of a Mime::NullType instance,
35
+ # which is invalid for a number of reasons. This string raises
36
+ # errors when piped through Mime::Type.lookup, so it's probably
37
+ # best to just return nil in those cases.
38
+ nil
39
+ end
40
40
  end
41
41
  end
42
42
  end
43
43
  end
44
44
 
45
- register(:action_controller, "ActionController::Instrumentation", "action_controller/metal/instrumentation",
46
- ActionController::Probe.new)
45
+ register(
46
+ :action_controller,
47
+ "ActionController::Instrumentation",
48
+ "action_controller/metal/instrumentation",
49
+ ActionController::Probe.new
50
+ )
47
51
  end
48
52
  end
@@ -10,9 +10,9 @@ module Skylight
10
10
 
11
11
  private
12
12
 
13
- def internal_request_id
14
- @skylight_request_id || super
15
- end
13
+ def internal_request_id
14
+ @skylight_request_id || super
15
+ end
16
16
  end
17
17
 
18
18
  class Probe
@@ -23,7 +23,11 @@ module Skylight
23
23
  end
24
24
  end
25
25
 
26
- register(:action_dispatch, "ActionDispatch::RequestId", "action_dispatch/middleware/request_id",
27
- ActionDispatch::RequestId::Probe.new)
26
+ register(
27
+ :action_dispatch,
28
+ "ActionDispatch::RequestId",
29
+ "action_dispatch/middleware/request_id",
30
+ ActionDispatch::RequestId::Probe.new
31
+ )
28
32
  end
29
33
  end
@@ -7,9 +7,7 @@ module Skylight
7
7
  module RouteSet
8
8
  module Instrumentation
9
9
  def call(env)
10
- ActiveSupport::Notifications.instrument("route_set.action_dispatch") do
11
- super
12
- end
10
+ ActiveSupport::Notifications.instrument("route_set.action_dispatch") { super }
13
11
  end
14
12
  end
15
13
 
@@ -22,7 +20,11 @@ module Skylight
22
20
  end
23
21
  end
24
22
 
25
- register(:rails_router, "ActionDispatch::Routing::RouteSet", "action_dispatch/routing/route_set",
26
- ActionDispatch::Routing::RouteSet::Probe.new)
23
+ register(
24
+ :rails_router,
25
+ "ActionDispatch::Routing::RouteSet",
26
+ "action_dispatch/routing/route_set",
27
+ ActionDispatch::Routing::RouteSet::Probe.new
28
+ )
27
29
  end
28
30
  end
@@ -5,19 +5,18 @@ module Skylight
5
5
  module ActionView
6
6
  module Instrumentation
7
7
  def render_with_layout(*args) #:nodoc:
8
- path, locals = case args.length
9
- when 2
10
- args
11
- when 4
12
- # Rails > 6.0.0.beta3 arguments are (view, template, path, locals)
13
- [args[2], args[3]]
14
- end
8
+ path, locals =
9
+ case args.length
10
+ when 2
11
+ args
12
+ when 4
13
+ # Rails > 6.0.0.beta3 arguments are (view, template, path, locals)
14
+ [args[2], args[3]]
15
+ end
15
16
 
16
17
  layout = nil
17
18
 
18
- if path
19
- layout = find_layout(path, locals.keys, [formats.first])
20
- end
19
+ layout = find_layout(path, locals.keys, [formats.first]) if path
21
20
 
22
21
  if layout
23
22
  ActiveSupport::Notifications.instrument("render_template.action_view", identifier: layout.identifier) do
@@ -14,17 +14,11 @@ module Skylight
14
14
  name, job_class_name = Normalizers::ActiveJob::Perform.normalize_title(job)
15
15
  descriptors = ["adapter: '#{adapter_name}'", "queue: '#{job.queue_name}'"]
16
16
  descriptors << "job: '#{job_class_name}'" if job_class_name
17
- desc = "{ #{descriptors.join(', ')} }"
18
- rescue
17
+ desc = "{ #{descriptors.join(", ")} }"
18
+ rescue StandardError
19
19
  block.call
20
20
  else
21
- Skylight.instrument(
22
- title: "Enqueue #{name}",
23
- category: CAT,
24
- description: desc,
25
- internal: true,
26
- &block
27
- )
21
+ Skylight.instrument(title: "Enqueue #{name}", category: CAT, description: desc, internal: true, &block)
28
22
  end
29
23
 
30
24
  self.class.instance_eval do
@@ -18,9 +18,7 @@ module Skylight
18
18
  rescue LoadError # rubocop:disable Lint/SuppressedException
19
19
  end
20
20
 
21
- if Gem.loaded_specs["active_model_serializers"]
22
- version = Gem.loaded_specs["active_model_serializers"].version
23
- end
21
+ version = Gem.loaded_specs["active_model_serializers"].version if Gem.loaded_specs["active_model_serializers"]
24
22
 
25
23
  if !version || version < Gem::Version.new("0.5.0")
26
24
  Skylight.error "Instrumention is only available for ActiveModelSerializers version 0.5.0 and greater."
@@ -37,14 +35,16 @@ module Skylight
37
35
  # End users could override as_json without calling super, but it's likely safer
38
36
  # than overriding serializable_array/hash/object.
39
37
 
40
- [::ActiveModel::Serializer, ::ActiveModel::ArraySerializer].each do |klass|
41
- klass.prepend(Instrumentation)
42
- end
38
+ [::ActiveModel::Serializer, ::ActiveModel::ArraySerializer].each { |klass| klass.prepend(Instrumentation) }
43
39
  end
44
40
  end
45
41
  end
46
42
 
47
- register(:active_model_serializers, "ActiveModel::Serializer", "active_model/serializer",
48
- ActiveModelSerializers::Probe.new)
43
+ register(
44
+ :active_model_serializers,
45
+ "ActiveModel::Serializer",
46
+ "active_model/serializer",
47
+ ActiveModelSerializers::Probe.new
48
+ )
49
49
  end
50
50
  end
@@ -10,13 +10,9 @@ module Skylight
10
10
 
11
11
  class Plugin < ::Delayed::Plugin
12
12
  callbacks do |lifecycle|
13
- lifecycle.around(:perform) do |worker, job, &block|
14
- sk_instrument(worker, job, &block)
15
- end
13
+ lifecycle.around(:perform) { |worker, job, &block| sk_instrument(worker, job, &block) }
16
14
 
17
- lifecycle.after(:error) do |_worker, _job|
18
- Skylight.trace&.segment = "error"
19
- end
15
+ lifecycle.after(:error) { |_worker, _job| Skylight.trace&.segment = "error" }
20
16
  end
21
17
 
22
18
  class << self
@@ -25,15 +21,19 @@ module Skylight
25
21
  def sk_instrument(_worker, job)
26
22
  endpoint = Skylight::Probes::DelayedJob.handler_name(job)
27
23
 
28
- Skylight.trace(endpoint,
29
- "app.delayed_job.worker",
30
- "Delayed::Worker#run",
31
- component: :worker,
32
- segment: job.queue,
33
- meta: { source_location: "delayed_job" }) do
34
- t { "Delayed::Job beginning trace" }
35
- yield
36
- end
24
+ Skylight.trace(
25
+ endpoint,
26
+ "app.delayed_job.worker",
27
+ "Delayed::Worker#run",
28
+ component: :worker,
29
+ segment: job.queue,
30
+ meta: {
31
+ source_location: "delayed_job"
32
+ }
33
+ ) do
34
+ t { "Delayed::Job beginning trace" }
35
+ yield
36
+ end
37
37
  end
38
38
  end
39
39
  end
@@ -44,11 +44,8 @@ module Skylight
44
44
  UNKNOWN = "<Delayed::Job Unknown>"
45
45
 
46
46
  def self.handler_name(job)
47
- payload_object = if job.respond_to?(:payload_object_without_sk)
48
- job.payload_object_without_sk
49
- else
50
- job.payload_object
51
- end
47
+ payload_object =
48
+ job.respond_to?(:payload_object_without_sk) ? job.payload_object_without_sk : job.payload_object
52
49
 
53
50
  payload_object_name(payload_object)
54
51
  end
@@ -62,7 +59,7 @@ module Skylight
62
59
  # Use class name instead to avoid this.
63
60
  payload_object.class.name
64
61
  end
65
- rescue
62
+ rescue StandardError
66
63
  UNKNOWN
67
64
  end
68
65
 
@@ -84,8 +81,10 @@ module Skylight
84
81
 
85
82
  opts = {
86
83
  category: "app.delayed_job.job",
87
- title: format_source(*source_meta),
88
- meta: { source_location_hint: source_meta },
84
+ title: format_source(*source_meta),
85
+ meta: {
86
+ source_location_hint: source_meta
87
+ },
89
88
  internal: true
90
89
  }
91
90
 
@@ -99,13 +98,9 @@ module Skylight
99
98
 
100
99
  private
101
100
 
102
- def format_source(method_type, constant_name, method_name)
103
- if method_type == :instance_method
104
- "#{constant_name}##{method_name}"
105
- else
106
- "#{constant_name}.#{method_name}"
107
- end
108
- end
101
+ def format_source(method_type, constant_name, method_name)
102
+ method_type == :instance_method ? "#{constant_name}##{method_name}" : "#{constant_name}.#{method_name}"
103
+ end
109
104
  end
110
105
 
111
106
  class Probe
@@ -124,23 +119,23 @@ module Skylight
124
119
 
125
120
  private
126
121
 
127
- def plugin_defined?
128
- defined?(::Skylight::Probes::DelayedJob::Plugin)
129
- end
122
+ def plugin_defined?
123
+ defined?(::Skylight::Probes::DelayedJob::Plugin)
124
+ end
130
125
 
131
- def validate_version
132
- spec = Gem.loaded_specs["delayed_job"]
133
- version = spec&.version
126
+ def validate_version
127
+ spec = Gem.loaded_specs["delayed_job"]
128
+ version = spec&.version
134
129
 
135
- if !version || version < Gem::Version.new("4.0.0")
136
- Skylight.error "The installed version of DelayedJob is not supported on Skylight. " \
130
+ if !version || version < Gem::Version.new("4.0.0")
131
+ Skylight.error "The installed version of DelayedJob is not supported on Skylight. " \
137
132
  "Your jobs will not be tracked."
138
133
 
139
- return false
140
- end
141
-
142
- true
134
+ return false
143
135
  end
136
+
137
+ true
138
+ end
144
139
  end
145
140
  end
146
141
 
@@ -9,16 +9,14 @@ module Skylight
9
9
  def perform_request(method, path, *args, &block)
10
10
  ActiveSupport::Notifications.instrument(
11
11
  "request.elasticsearch",
12
- name: "Request",
12
+ name: "Request",
13
13
  method: method,
14
- path: path
14
+ path: path
15
15
  ) do
16
16
  # Prevent HTTP-related probes from firing
17
17
  Skylight::Normalizers::Faraday::Request.disable do
18
18
  disable_skylight_probe(:NetHTTP) do
19
- disable_skylight_probe(:HTTPClient) do
20
- perform_request_without_sk(method, path, *args, &block)
21
- end
19
+ disable_skylight_probe(:HTTPClient) { perform_request_without_sk(method, path, *args, &block) }
22
20
  end
23
21
  end
24
22
  end
@@ -26,7 +24,7 @@ module Skylight
26
24
 
27
25
  def disable_skylight_probe(class_name)
28
26
  klass = ::ActiveSupport::Inflector.safe_constantize("Skylight::Probes::#{class_name}::Probe")
29
- (klass ? klass.disable { yield } : yield).tap { puts "re-enabling: #{klass}" }
27
+ (klass ? klass.disable { yield } : yield).tap { Skylight.log(:debug, "re-enabling: #{klass}") }
30
28
  end
31
29
  end
32
30
  end
@@ -14,7 +14,7 @@ module Skylight
14
14
  ::Excon.defaults[:middlewares].insert(idx, Probes::Excon::Middleware)
15
15
  else
16
16
  Skylight.error "The installed version of Excon doesn't support Middlewares. " \
17
- "The Excon probe will be disabled."
17
+ "The Excon probe will be disabled."
18
18
  end
19
19
  end
20
20
  end
@@ -33,33 +33,32 @@ module Skylight
33
33
 
34
34
  private
35
35
 
36
- def begin_instrumentation(datum)
37
- method = datum[:method].to_s
38
- scheme = datum[:scheme]
39
- host = datum[:host]
40
- # TODO: Maybe don't show other default ports like 443
41
- port = datum[:port] == 80 ? nil : datum[:port]
42
- path = datum[:path]
43
- query = datum[:query]
36
+ def begin_instrumentation(datum)
37
+ method = datum[:method].to_s
38
+ scheme = datum[:scheme]
39
+ host = datum[:host]
44
40
 
45
- opts = Formatters::HTTP.build_opts(method, scheme, host, port, path, query)
41
+ # TODO: Maybe don't show other default ports like 443
42
+ port = datum[:port] == 80 ? nil : datum[:port]
43
+ path = datum[:path]
44
+ query = datum[:query]
46
45
 
47
- @requests[datum] = Skylight.instrument(opts)
48
- rescue Exception => e
49
- Skylight.error "failed to begin instrumentation for Excon; msg=%s", e.message
50
- end
46
+ opts = Formatters::HTTP.build_opts(method, scheme, host, port, path, query)
47
+
48
+ @requests[datum] = Skylight.instrument(opts)
49
+ rescue Exception => e
50
+ Skylight.error "failed to begin instrumentation for Excon; msg=%s", e.message
51
+ end
51
52
 
52
- def end_instrumentation(datum)
53
- if (request = @requests.delete(datum))
54
- meta = {}
55
- if datum[:error].is_a?(Exception)
56
- meta[:exception_object] = datum[:error]
57
- end
58
- Skylight.done(request, meta)
59
- end
60
- rescue Exception => e
61
- Skylight.error "failed to end instrumentation for Excon; msg=%s", e.message
53
+ def end_instrumentation(datum)
54
+ if (request = @requests.delete(datum))
55
+ meta = {}
56
+ meta[:exception_object] = datum[:error] if datum[:error].is_a?(Exception)
57
+ Skylight.done(request, meta)
62
58
  end
59
+ rescue Exception => e
60
+ Skylight.error "failed to end instrumentation for Excon; msg=%s", e.message
61
+ end
63
62
  end
64
63
  end
65
64
  end
@@ -20,16 +20,11 @@ module Skylight
20
20
  class Probe
21
21
  def install
22
22
  tracing_klass_name = "::GraphQL::Tracing::ActiveSupportNotificationsTracing"
23
- klasses_to_probe = %w[
24
- ::GraphQL::Execution::Multiplex
25
- ::GraphQL::Query
26
- ]
23
+ klasses_to_probe = %w[::GraphQL::Execution::Multiplex ::GraphQL::Query]
27
24
 
28
25
  return unless ([tracing_klass_name] + klasses_to_probe).all?(&method(:safe_constantize))
29
26
 
30
- klasses_to_probe.each do |klass_name|
31
- safe_constantize(klass_name).prepend(Instrumentation)
32
- end
27
+ klasses_to_probe.each { |klass_name| safe_constantize(klass_name).prepend(Instrumentation) }
33
28
  end
34
29
 
35
30
  def safe_constantize(klass_name)