skylight 5.0.1 → 5.1.1

Sign up to get free protection for your applications and to get access to all the features.
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