skylight 5.0.1 → 5.1.1

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 (79) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +395 -364
  3. data/CLA.md +1 -1
  4. data/LICENSE.md +7 -17
  5. data/README.md +1 -1
  6. data/ext/extconf.rb +42 -54
  7. data/ext/libskylight.yml +9 -6
  8. data/lib/skylight.rb +20 -30
  9. data/lib/skylight/api.rb +22 -18
  10. data/lib/skylight/cli.rb +47 -46
  11. data/lib/skylight/cli/doctor.rb +50 -50
  12. data/lib/skylight/cli/helpers.rb +19 -19
  13. data/lib/skylight/cli/merger.rb +141 -139
  14. data/lib/skylight/config.rb +265 -300
  15. data/lib/skylight/deprecation.rb +4 -4
  16. data/lib/skylight/errors.rb +3 -4
  17. data/lib/skylight/extensions.rb +17 -29
  18. data/lib/skylight/extensions/source_location.rb +128 -128
  19. data/lib/skylight/formatters/http.rb +1 -3
  20. data/lib/skylight/gc.rb +30 -40
  21. data/lib/skylight/helpers.rb +43 -41
  22. data/lib/skylight/instrumenter.rb +25 -18
  23. data/lib/skylight/middleware.rb +31 -35
  24. data/lib/skylight/native.rb +8 -10
  25. data/lib/skylight/native_ext_fetcher.rb +10 -12
  26. data/lib/skylight/normalizers.rb +43 -39
  27. data/lib/skylight/normalizers/action_controller/process_action.rb +24 -25
  28. data/lib/skylight/normalizers/action_controller/send_file.rb +7 -6
  29. data/lib/skylight/normalizers/action_dispatch/route_set.rb +7 -7
  30. data/lib/skylight/normalizers/active_job/perform.rb +48 -44
  31. data/lib/skylight/normalizers/active_model_serializers/render.rb +7 -3
  32. data/lib/skylight/normalizers/active_storage.rb +11 -13
  33. data/lib/skylight/normalizers/active_support/cache.rb +1 -12
  34. data/lib/skylight/normalizers/coach/handler_finish.rb +1 -3
  35. data/lib/skylight/normalizers/default.rb +1 -9
  36. data/lib/skylight/normalizers/faraday/request.rb +1 -3
  37. data/lib/skylight/normalizers/grape/endpoint.rb +13 -19
  38. data/lib/skylight/normalizers/grape/endpoint_run.rb +16 -18
  39. data/lib/skylight/normalizers/grape/endpoint_run_filters.rb +1 -3
  40. data/lib/skylight/normalizers/graphql/base.rb +23 -28
  41. data/lib/skylight/normalizers/render.rb +19 -21
  42. data/lib/skylight/normalizers/shrine.rb +15 -17
  43. data/lib/skylight/normalizers/sql.rb +4 -4
  44. data/lib/skylight/probes.rb +38 -46
  45. data/lib/skylight/probes/action_controller.rb +32 -28
  46. data/lib/skylight/probes/action_dispatch/request_id.rb +9 -5
  47. data/lib/skylight/probes/action_dispatch/routing/route_set.rb +7 -5
  48. data/lib/skylight/probes/action_view.rb +9 -10
  49. data/lib/skylight/probes/active_job_enqueue.rb +3 -9
  50. data/lib/skylight/probes/active_model_serializers.rb +8 -8
  51. data/lib/skylight/probes/delayed_job.rb +37 -42
  52. data/lib/skylight/probes/elasticsearch.rb +3 -5
  53. data/lib/skylight/probes/excon.rb +1 -1
  54. data/lib/skylight/probes/excon/middleware.rb +22 -23
  55. data/lib/skylight/probes/graphql.rb +2 -7
  56. data/lib/skylight/probes/middleware.rb +14 -5
  57. data/lib/skylight/probes/mongo.rb +83 -91
  58. data/lib/skylight/probes/net_http.rb +1 -1
  59. data/lib/skylight/probes/redis.rb +5 -17
  60. data/lib/skylight/probes/sequel.rb +7 -11
  61. data/lib/skylight/probes/sinatra.rb +8 -5
  62. data/lib/skylight/probes/tilt.rb +2 -4
  63. data/lib/skylight/railtie.rb +121 -135
  64. data/lib/skylight/sidekiq.rb +4 -5
  65. data/lib/skylight/subscriber.rb +31 -33
  66. data/lib/skylight/test.rb +89 -84
  67. data/lib/skylight/trace.rb +121 -115
  68. data/lib/skylight/user_config.rb +14 -17
  69. data/lib/skylight/util/clock.rb +1 -0
  70. data/lib/skylight/util/component.rb +18 -21
  71. data/lib/skylight/util/deploy.rb +11 -13
  72. data/lib/skylight/util/http.rb +104 -105
  73. data/lib/skylight/util/logging.rb +4 -6
  74. data/lib/skylight/util/lru_cache.rb +2 -6
  75. data/lib/skylight/util/platform.rb +2 -6
  76. data/lib/skylight/util/ssl.rb +1 -25
  77. data/lib/skylight/version.rb +1 -1
  78. data/lib/skylight/vm/gc.rb +1 -9
  79. metadata +6 -6
@@ -79,18 +79,18 @@ module Skylight
79
79
 
80
80
  private
81
81
 
82
- def process_meta(trace, _name, payload, meta, cache_key: nil)
83
- trace.instrumenter.extensions.process_normalizer_meta(
84
- payload,
85
- meta,
86
- cache_key: cache_key,
87
- **process_meta_options(payload)
88
- )
89
- end
82
+ def process_meta(trace, _name, payload, meta, cache_key: nil)
83
+ trace.instrumenter.extensions.process_normalizer_meta(
84
+ payload,
85
+ meta,
86
+ cache_key: cache_key,
87
+ **process_meta_options(payload)
88
+ )
89
+ end
90
90
 
91
- def process_meta_options(_payload)
92
- {}
93
- end
91
+ def process_meta_options(_payload)
92
+ {}
93
+ end
94
94
  end
95
95
 
96
96
  require "skylight/normalizers/default"
@@ -105,6 +105,10 @@ module Skylight
105
105
  @normalizers.keys
106
106
  end
107
107
 
108
+ def each_key(&block)
109
+ @normalizers.each_key(&block)
110
+ end
111
+
108
112
  def normalize(trace, name, payload)
109
113
  normalizer_for(name).normalize_with_meta(trace, name, payload)
110
114
  end
@@ -121,33 +125,33 @@ module Skylight
121
125
  end
122
126
  end
123
127
 
124
- %w[ action_controller/process_action
125
- action_controller/send_file
126
- action_dispatch/process_middleware
127
- action_dispatch/route_set
128
- action_view/render_collection
129
- action_view/render_partial
130
- action_view/render_template
131
- action_view/render_layout
132
- active_job/perform
133
- active_model_serializers/render
134
- active_record/instantiation
135
- active_record/sql
136
- active_storage
137
- active_support/cache
138
- coach/handler_finish
139
- coach/middleware_finish
140
- couch_potato/query
141
- data_mapper/sql
142
- elasticsearch/request
143
- faraday/request
144
- grape/endpoint
145
- graphiti/resolve
146
- graphiti/render
147
- graphql/base
148
- sequel/sql
149
- shrine].each do |file|
150
- require "skylight/normalizers/#{file}"
151
- end
128
+ %w[
129
+ action_controller/process_action
130
+ action_controller/send_file
131
+ action_dispatch/process_middleware
132
+ action_dispatch/route_set
133
+ action_view/render_collection
134
+ action_view/render_partial
135
+ action_view/render_template
136
+ action_view/render_layout
137
+ active_job/perform
138
+ active_model_serializers/render
139
+ active_record/instantiation
140
+ active_record/sql
141
+ active_storage
142
+ active_support/cache
143
+ coach/handler_finish
144
+ coach/middleware_finish
145
+ couch_potato/query
146
+ data_mapper/sql
147
+ elasticsearch/request
148
+ faraday/request
149
+ grape/endpoint
150
+ graphiti/resolve
151
+ graphiti/render
152
+ graphql/base
153
+ sequel/sql
154
+ shrine
155
+ ].each { |file| require "skylight/normalizers/#{file}" }
152
156
  end
153
157
  end
@@ -32,37 +32,36 @@ module Skylight
32
32
 
33
33
  private
34
34
 
35
- def controller_action(payload)
36
- "#{payload[:controller]}##{payload[:action]}"
37
- end
35
+ def controller_action(payload)
36
+ "#{payload[:controller]}##{payload[:action]}"
37
+ end
38
38
 
39
- def process_meta_options(payload)
40
- # provide hints to override default source_location behavior
41
- super.merge(source_location_hint: [:instance_method, payload[:controller], payload[:action]])
42
- end
39
+ def process_meta_options(payload)
40
+ # provide hints to override default source_location behavior
41
+ super.merge(source_location_hint: [:instance_method, payload[:controller], payload[:action]])
42
+ end
43
43
 
44
- def segment_from_payload(payload)
45
- # Show 'error' if there's an unhandled exception or if the status is 4xx or 5xx
46
- return "error" if payload[:exception] || payload[:exception_object]
44
+ def segment_from_payload(payload)
45
+ # Show 'error' if there's an unhandled exception or if the status is 4xx or 5xx
46
+ return "error" if payload[:exception] || payload[:exception_object]
47
47
 
48
- segment_from_status(payload[:status]) ||
49
- if payload[:sk_rendered_format]
50
- # We only show the variant if we actually have a format
51
- # We won't have a sk_rendered_format if it's a `head` outside of a `respond_to` block.
52
- [payload[:sk_rendered_format], payload[:sk_variant]].compact.flatten.join("+")
53
- end
48
+ segment_from_status(payload[:status]) || if payload[:sk_rendered_format]
49
+ # We only show the variant if we actually have a format
50
+ # We won't have a sk_rendered_format if it's a `head` outside of a `respond_to` block.
51
+ [payload[:sk_rendered_format], payload[:sk_variant]].compact.flatten.join("+")
54
52
  end
53
+ end
55
54
 
56
- def segment_from_status(status)
57
- case status
58
- when 304
59
- "not modified"
60
- when (300..399)
61
- "redirect"
62
- when (400..599)
63
- "error"
64
- end
55
+ def segment_from_status(status)
56
+ case status
57
+ when 304
58
+ "not modified"
59
+ when (300..399)
60
+ "redirect"
61
+ when (400..599)
62
+ "error"
65
63
  end
64
+ end
66
65
  end
67
66
  end
68
67
  end
@@ -32,17 +32,18 @@ module Skylight
32
32
 
33
33
  private
34
34
 
35
- OCTET_STREAM = "application/octet-stream".freeze
36
- ATTACHMENT = "attachment".freeze
35
+ OCTET_STREAM = "application/octet-stream".freeze
36
+ ATTACHMENT = "attachment".freeze
37
37
 
38
- def initialize(*)
39
- super
38
+ def initialize(*)
39
+ super
40
40
 
41
- @mimes = Mime::SET.each_with_object({}) do |mime, hash|
41
+ @mimes =
42
+ Mime::SET.each_with_object({}) do |mime, hash|
42
43
  hash[mime.symbol] = mime.to_s.dup.freeze
43
44
  hash
44
45
  end
45
- end
46
+ end
46
47
  end
47
48
  end
48
49
  end
@@ -13,14 +13,14 @@ module Skylight
13
13
 
14
14
  private
15
15
 
16
- def router_class_name
17
- "ActionDispatch::Routing::RouteSet"
18
- end
16
+ def router_class_name
17
+ "ActionDispatch::Routing::RouteSet"
18
+ end
19
19
 
20
- def process_meta_options(_payload)
21
- # provide hints to override default source_location behavior
22
- super.merge(source_location_hint: [:own_instance_method, router_class_name, "call"])
23
- end
20
+ def process_meta_options(_payload)
21
+ # provide hints to override default source_location behavior
22
+ super.merge(source_location_hint: [:own_instance_method, router_class_name, "call"])
23
+ end
24
24
  end
25
25
  end
26
26
  end
@@ -8,12 +8,16 @@ module Skylight
8
8
  DELAYED_JOB_WRAPPER = "ActiveJob::QueueAdapters::DelayedJobAdapter::JobWrapper".freeze
9
9
 
10
10
  def self.normalize_title(job_instance)
11
- job_instance.class.name.to_s.tap do |str|
12
- if str.match(DELIVERY_JOB)
13
- mailer_class, mailer_method, * = job_instance.arguments
14
- return ["#{mailer_class}##{mailer_method}", str]
11
+ job_instance
12
+ .class
13
+ .name
14
+ .to_s
15
+ .tap do |str|
16
+ if str.match(DELIVERY_JOB)
17
+ mailer_class, mailer_method, * = job_instance.arguments
18
+ return "#{mailer_class}##{mailer_method}", str
19
+ end
15
20
  end
16
- end
17
21
  end
18
22
 
19
23
  CAT = "app.job.perform".freeze
@@ -36,50 +40,50 @@ module Skylight
36
40
 
37
41
  private
38
42
 
39
- def process_meta_options(payload)
40
- # provide hints to override default source_location behavior
41
- super.merge(source_location_hint: [:instance_method, payload[:job].class.to_s, "perform"])
42
- end
43
-
44
- def normalize_adapter_name(adapter)
45
- adapter_string = adapter.is_a?(Class) ? adapter.to_s : adapter.class.to_s
46
- adapter_string[/ActiveJob::QueueAdapters::(\w+)Adapter/, 1].underscore
47
- rescue
48
- "active_job"
49
- end
43
+ def process_meta_options(payload)
44
+ # provide hints to override default source_location behavior
45
+ super.merge(source_location_hint: [:instance_method, payload[:job].class.to_s, "perform"])
46
+ end
50
47
 
51
- def maybe_set_endpoint(trace, payload)
52
- if assign_endpoint?(trace, payload)
53
- trace.endpoint = normalize_title(payload[:job])
54
- end
55
- end
48
+ def normalize_adapter_name(adapter)
49
+ adapter_string = adapter.is_a?(Class) ? adapter.to_s : adapter.class.to_s
50
+ adapter_string[/ActiveJob::QueueAdapters::(\w+)Adapter/, 1].underscore
51
+ rescue StandardError
52
+ "active_job"
53
+ end
56
54
 
57
- def assign_endpoint?(trace, payload)
58
- # Always assign the endpoint if it has not yet been assigned by the ActiveJob probe.
59
- return true unless trace.endpoint
60
- return true if defined?(Skylight::Probes::ActiveJob::TITLE) &&
61
- trace.endpoint == Skylight::Probes::ActiveJob::TITLE
62
- return true if defined?(SKylight::Probes::DelayedJob::Probe::UNKNOWN) &&
63
- trace.endpoint == Skylight::Probes::DelayedJob::Probe::UNKNOWN
55
+ def maybe_set_endpoint(trace, payload)
56
+ trace.endpoint = normalize_title(payload[:job]) if assign_endpoint?(trace, payload)
57
+ end
64
58
 
65
- # If a job is called using #perform_now inside a controller action
66
- # or within another job's #perform method, we do not want this to
67
- # overwrite the existing endpoint name (unless it is the default from ActiveJob).
68
- #
69
- # If the current endpoint name matches this payload, return true to allow the
70
- # segment to be assigned by normalize_after.
71
- trace.endpoint == DELIVERY_JOB ||
72
- trace.endpoint == normalize_title(payload[:job]) ||
73
- # This adapter wrapper needs to be handled specifically due to interactions with the
74
- # standalone Delayed::Job probe, as there is no consistent way to get the wrapped
75
- # job name among all Delayed::Job backends.
76
- trace.endpoint == DELAYED_JOB_WRAPPER
59
+ def assign_endpoint?(trace, payload)
60
+ # Always assign the endpoint if it has not yet been assigned by the ActiveJob probe.
61
+ return true unless trace.endpoint
62
+ if defined?(Skylight::Probes::ActiveJob::TITLE) && trace.endpoint == Skylight::Probes::ActiveJob::TITLE
63
+ return true
77
64
  end
78
-
79
- def normalize_title(job_instance)
80
- title, * = self.class.normalize_title(job_instance)
81
- title
65
+ if defined?(SKylight::Probes::DelayedJob::Probe::UNKNOWN) &&
66
+ trace.endpoint == Skylight::Probes::DelayedJob::Probe::UNKNOWN
67
+ return true
82
68
  end
69
+
70
+ # If a job is called using #perform_now inside a controller action
71
+ # or within another job's #perform method, we do not want this to
72
+ # overwrite the existing endpoint name (unless it is the default from ActiveJob).
73
+ #
74
+ # If the current endpoint name matches this payload, return true to allow the
75
+ # segment to be assigned by normalize_after.
76
+ trace.endpoint == DELIVERY_JOB || trace.endpoint == normalize_title(payload[:job]) ||
77
+ # This adapter wrapper needs to be handled specifically due to interactions with the
78
+ # standalone Delayed::Job probe, as there is no consistent way to get the wrapped
79
+ # job name among all Delayed::Job backends.
80
+ trace.endpoint == DELAYED_JOB_WRAPPER
81
+ end
82
+
83
+ def normalize_title(job_instance)
84
+ title, * = self.class.normalize_title(job_instance)
85
+ title
86
+ end
83
87
  end
84
88
  end
85
89
  end
@@ -14,9 +14,13 @@ module Skylight
14
14
  title = title.sub(/^ActiveModel::(Serializer::)?/, "")
15
15
 
16
16
  if (adapter_instance = payload[:adapter])
17
- adapter_name = adapter_instance.class.name.to_s.
18
- sub(/^ActiveModel::Serializer::Adapter::/, "").
19
- sub(/^ActiveModelSerializers::Adapter::/, "")
17
+ adapter_name =
18
+ adapter_instance
19
+ .class
20
+ .name
21
+ .to_s
22
+ .sub(/^ActiveModel::Serializer::Adapter::/, "")
23
+ .sub(/^ActiveModelSerializers::Adapter::/, "")
20
24
  desc = "Adapter: #{adapter_name}"
21
25
  end
22
26
 
@@ -2,26 +2,24 @@ module Skylight
2
2
  module Normalizers
3
3
  class ActiveStorage < Normalizer
4
4
  TITLES = {
5
- "preview.active_storage" => "Preview",
6
- "transform.active_storage" => "Transform",
7
- "service_download.active_storage" => "Download",
8
- "service_upload.active_storage" => "Upload",
5
+ "preview.active_storage" => "Preview",
6
+ "transform.active_storage" => "Transform",
7
+ "service_download.active_storage" => "Download",
8
+ "service_upload.active_storage" => "Upload",
9
9
  "service_streaming_download.active_storage" => "Streaming Download",
10
- "service_download_chunk.active_storage" => "Download Chunk",
11
- "service_delete.active_storage" => "Delete",
12
- "service_delete_prefixed.active_storage" => "Delete Prefixed",
13
- "service_exist.active_storage" => "Exist",
14
- "service_url.active_storage" => "Url"
10
+ "service_download_chunk.active_storage" => "Download Chunk",
11
+ "service_delete.active_storage" => "Delete",
12
+ "service_delete_prefixed.active_storage" => "Delete Prefixed",
13
+ "service_exist.active_storage" => "Exist",
14
+ "service_url.active_storage" => "Url"
15
15
  }.freeze
16
16
 
17
- TITLES.each_key do |key|
18
- register key
19
- end
17
+ TITLES.each_key { |key| register key }
20
18
 
21
19
  def normalize(_trace, name, _payload)
22
20
  title = ["ActiveStorage", TITLES[name]].join(" ")
23
21
 
24
- cat = "app.#{name.split('.').reverse.join('.')}"
22
+ cat = "app.#{name.split(".").reverse.join(".")}"
25
23
 
26
24
  [cat, title, nil]
27
25
  end
@@ -2,18 +2,7 @@ module Skylight
2
2
  module Normalizers
3
3
  module ActiveSupport
4
4
  class Cache < Normalizer
5
- %w[
6
- clear
7
- decrement
8
- delete
9
- exist
10
- fetch_hit
11
- generate
12
- increment
13
- read
14
- read_multi
15
- write
16
- ].each do |type|
5
+ %w[clear decrement delete exist fetch_hit generate increment read read_multi write].each do |type|
17
6
  require "skylight/normalizers/active_support/cache_#{type}"
18
7
  end
19
8
  end
@@ -36,9 +36,7 @@ module Skylight
36
36
  response_status = payload.fetch(:response, {}).fetch(:status, "").to_s
37
37
  segments << "error" if response_status.start_with?("4", "5")
38
38
 
39
- if segments.any?
40
- trace.segment = segments.join("+")
41
- end
39
+ trace.segment = segments.join("+") if segments.any?
42
40
  end
43
41
  end
44
42
  end
@@ -17,15 +17,7 @@ module Skylight
17
17
  # @option payload [String] :description
18
18
  # @return [Array, :skip] the normalized array or `:skip` if `name` is not part of a known {Skylight::TIERS tier}
19
19
  def normalize(_trace, name, payload)
20
- if name =~ Skylight::TIER_REGEX
21
- [
22
- name,
23
- payload[:title],
24
- payload[:description]
25
- ]
26
- else
27
- :skip
28
- end
20
+ name =~ Skylight::TIER_REGEX ? [name, payload[:title], payload[:description]] : :skip
29
21
  end
30
22
  end
31
23
  end
@@ -23,9 +23,7 @@ module Skylight
23
23
  def normalize(_trace, _name, payload)
24
24
  uri = payload[:url]
25
25
 
26
- if disabled?
27
- return :skip
28
- end
26
+ return :skip if disabled?
29
27
 
30
28
  opts = Formatters::HTTP.build_opts(payload[:method], uri.scheme, uri.host, uri.port, uri.path, uri.query)
31
29
  description = opts[:title]
@@ -2,32 +2,26 @@ module Skylight
2
2
  module Normalizers
3
3
  module Grape
4
4
  class Endpoint < Normalizer
5
- %w[
6
- run
7
- render
8
- run_filters
9
- ].each do |type|
10
- require "skylight/normalizers/grape/endpoint_#{type}"
11
- end
5
+ %w[run render run_filters].each { |type| require "skylight/normalizers/grape/endpoint_#{type}" }
12
6
 
13
7
  require "skylight/normalizers/grape/format_response"
14
8
 
15
9
  private
16
10
 
17
- def get_method(endpoint)
18
- method = endpoint.options[:method].first
19
- method = "#{method}..." if endpoint.options[:method].length > 1
20
- method
21
- end
11
+ def get_method(endpoint)
12
+ method = endpoint.options[:method].first
13
+ method = "#{method}..." if endpoint.options[:method].length > 1
14
+ method
15
+ end
22
16
 
23
- def get_path(endpoint)
24
- endpoint.options[:path].join("/")
25
- end
17
+ def get_path(endpoint)
18
+ endpoint.options[:path].join("/")
19
+ end
26
20
 
27
- def get_namespace(endpoint)
28
- # slice off preceding slash for data continuity
29
- ::Grape::Namespace.joined_space_path(endpoint.namespace_stackable(:namespace)).to_s[1..-1]
30
- end
21
+ def get_namespace(endpoint)
22
+ # slice off preceding slash for data continuity
23
+ ::Grape::Namespace.joined_space_path(endpoint.namespace_stackable(:namespace)).to_s[1..-1]
24
+ end
31
25
  end
32
26
  end
33
27
  end