skylight 5.1.0.beta → 5.1.0.beta2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +390 -371
  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/lib/skylight.rb +20 -30
  8. data/lib/skylight/api.rb +22 -18
  9. data/lib/skylight/cli.rb +47 -46
  10. data/lib/skylight/cli/doctor.rb +50 -50
  11. data/lib/skylight/cli/helpers.rb +19 -19
  12. data/lib/skylight/cli/merger.rb +141 -139
  13. data/lib/skylight/config.rb +265 -302
  14. data/lib/skylight/deprecation.rb +4 -4
  15. data/lib/skylight/errors.rb +3 -4
  16. data/lib/skylight/extensions.rb +17 -29
  17. data/lib/skylight/extensions/source_location.rb +128 -128
  18. data/lib/skylight/formatters/http.rb +1 -3
  19. data/lib/skylight/gc.rb +30 -40
  20. data/lib/skylight/helpers.rb +43 -41
  21. data/lib/skylight/instrumenter.rb +25 -18
  22. data/lib/skylight/middleware.rb +31 -35
  23. data/lib/skylight/native.rb +8 -10
  24. data/lib/skylight/native_ext_fetcher.rb +10 -12
  25. data/lib/skylight/normalizers.rb +43 -39
  26. data/lib/skylight/normalizers/action_controller/process_action.rb +24 -25
  27. data/lib/skylight/normalizers/action_controller/send_file.rb +7 -6
  28. data/lib/skylight/normalizers/action_dispatch/route_set.rb +7 -7
  29. data/lib/skylight/normalizers/active_job/perform.rb +48 -44
  30. data/lib/skylight/normalizers/active_model_serializers/render.rb +7 -3
  31. data/lib/skylight/normalizers/active_storage.rb +11 -13
  32. data/lib/skylight/normalizers/active_support/cache.rb +1 -12
  33. data/lib/skylight/normalizers/coach/handler_finish.rb +1 -3
  34. data/lib/skylight/normalizers/default.rb +1 -9
  35. data/lib/skylight/normalizers/faraday/request.rb +1 -3
  36. data/lib/skylight/normalizers/grape/endpoint.rb +13 -19
  37. data/lib/skylight/normalizers/grape/endpoint_run.rb +16 -18
  38. data/lib/skylight/normalizers/grape/endpoint_run_filters.rb +1 -3
  39. data/lib/skylight/normalizers/graphql/base.rb +23 -28
  40. data/lib/skylight/normalizers/render.rb +19 -21
  41. data/lib/skylight/normalizers/shrine.rb +15 -17
  42. data/lib/skylight/normalizers/sql.rb +4 -4
  43. data/lib/skylight/probes.rb +38 -46
  44. data/lib/skylight/probes/action_controller.rb +32 -28
  45. data/lib/skylight/probes/action_dispatch/request_id.rb +9 -5
  46. data/lib/skylight/probes/action_dispatch/routing/route_set.rb +7 -5
  47. data/lib/skylight/probes/action_view.rb +9 -10
  48. data/lib/skylight/probes/active_job_enqueue.rb +3 -9
  49. data/lib/skylight/probes/active_model_serializers.rb +8 -8
  50. data/lib/skylight/probes/delayed_job.rb +37 -42
  51. data/lib/skylight/probes/elasticsearch.rb +3 -5
  52. data/lib/skylight/probes/excon.rb +1 -1
  53. data/lib/skylight/probes/excon/middleware.rb +22 -23
  54. data/lib/skylight/probes/graphql.rb +2 -7
  55. data/lib/skylight/probes/middleware.rb +14 -5
  56. data/lib/skylight/probes/mongo.rb +83 -91
  57. data/lib/skylight/probes/net_http.rb +1 -1
  58. data/lib/skylight/probes/redis.rb +5 -17
  59. data/lib/skylight/probes/sequel.rb +7 -11
  60. data/lib/skylight/probes/sinatra.rb +8 -5
  61. data/lib/skylight/probes/tilt.rb +2 -4
  62. data/lib/skylight/railtie.rb +121 -135
  63. data/lib/skylight/sidekiq.rb +4 -5
  64. data/lib/skylight/subscriber.rb +31 -33
  65. data/lib/skylight/test.rb +89 -84
  66. data/lib/skylight/trace.rb +121 -115
  67. data/lib/skylight/user_config.rb +14 -17
  68. data/lib/skylight/util/clock.rb +1 -0
  69. data/lib/skylight/util/component.rb +18 -21
  70. data/lib/skylight/util/deploy.rb +11 -13
  71. data/lib/skylight/util/http.rb +104 -105
  72. data/lib/skylight/util/logging.rb +4 -6
  73. data/lib/skylight/util/lru_cache.rb +2 -6
  74. data/lib/skylight/util/platform.rb +2 -6
  75. data/lib/skylight/util/ssl.rb +1 -3
  76. data/lib/skylight/version.rb +1 -1
  77. data/lib/skylight/vm/gc.rb +1 -9
  78. metadata +4 -4
@@ -14,27 +14,25 @@ module Skylight
14
14
 
15
15
  private
16
16
 
17
- def get_endpoint_name(endpoint)
18
- method = get_method(endpoint)
19
- path = get_path(endpoint)
20
- namespace = get_namespace(endpoint)
21
-
22
- if namespace && !namespace.empty?
23
- path = "/#{path}" if path[0] != "/"
24
- path = "#{namespace}#{path}"
25
- end
26
-
27
- "#{base_app_name(endpoint)} [#{method}] #{path}".strip
17
+ def get_endpoint_name(endpoint)
18
+ method = get_method(endpoint)
19
+ path = get_path(endpoint)
20
+ namespace = get_namespace(endpoint)
21
+
22
+ if namespace && !namespace.empty?
23
+ path = "/#{path}" if path[0] != "/"
24
+ path = "#{namespace}#{path}"
28
25
  end
29
26
 
30
- def base_app_name(endpoint)
31
- ep = endpoint.options[:for]
32
- return ep.name if ep.name
27
+ "#{base_app_name(endpoint)} [#{method}] #{path}".strip
28
+ end
29
+
30
+ def base_app_name(endpoint)
31
+ ep = endpoint.options[:for]
32
+ return ep.name if ep.name
33
33
 
34
- if ep.respond_to?(:base) && ep.base.respond_to?(:name)
35
- ep.base.name
36
- end
37
- end
34
+ ep.base.name if ep.respond_to?(:base) && ep.base.respond_to?(:name)
35
+ end
38
36
  end
39
37
  end
40
38
  end
@@ -10,9 +10,7 @@ module Skylight
10
10
  filters = payload[:filters]
11
11
  type = payload[:type]
12
12
 
13
- if (!filters || filters.empty?) || !type
14
- return :skip
15
- end
13
+ return :skip if (!filters || filters.empty?) || !type
16
14
 
17
15
  [CAT, "#{type.to_s.capitalize} Filters", nil]
18
16
  end
@@ -25,12 +25,7 @@ module Skylight::Normalizers::GraphQL
25
25
 
26
26
  def self.inherited(klass)
27
27
  super
28
- klass.const_set(
29
- :KEY,
30
- ActiveSupport::Inflector.underscore(
31
- ActiveSupport::Inflector.demodulize(klass.name)
32
- ).freeze
33
- )
28
+ klass.const_set(:KEY, ActiveSupport::Inflector.underscore(ActiveSupport::Inflector.demodulize(klass.name)).freeze)
34
29
  end
35
30
 
36
31
  def self.key
@@ -43,15 +38,13 @@ module Skylight::Normalizers::GraphQL
43
38
 
44
39
  private
45
40
 
46
- def key
47
- self.class.key
48
- end
41
+ def key
42
+ self.class.key
43
+ end
49
44
 
50
- def extract_query_name(query)
51
- query&.context&.[](:skylight_endpoint) ||
52
- query&.operation_name ||
53
- ANONYMOUS
54
- end
45
+ def extract_query_name(query)
46
+ query&.context&.[](:skylight_endpoint) || query&.operation_name || ANONYMOUS
47
+ end
55
48
  end
56
49
 
57
50
  class Lex < Base
@@ -82,17 +75,21 @@ module Skylight::Normalizers::GraphQL
82
75
  # In graphql-ruby's case, the calculation of the operation name is lazy, and
83
76
  # has not been done yet at the point where execute_multiplex starts.
84
77
  # [1] https://graphql.org/learn/serving-over-http/#post-request
85
- queries, has_errors = payload[:multiplex].queries.each_with_object([Set.new, Set.new]) do |query, (names, errors)|
86
- names << extract_query_name(query)
87
- errors << query.static_errors.any?
88
- end
89
-
90
- trace.endpoint = "graphql:#{queries.sort.join('+')}"
91
- trace.compound_response_error_status = if has_errors.all?
92
- :all
93
- elsif has_errors.any?
94
- :partial
95
- end
78
+ queries, has_errors =
79
+ payload[:multiplex]
80
+ .queries
81
+ .each_with_object([Set.new, Set.new]) do |query, (names, errors)|
82
+ names << extract_query_name(query)
83
+ errors << query.static_errors.any?
84
+ end
85
+
86
+ trace.endpoint = "graphql:#{queries.sort.join("+")}"
87
+ trace.compound_response_error_status =
88
+ if has_errors.all?
89
+ :all
90
+ elsif has_errors.any?
91
+ :partial
92
+ end
96
93
  end
97
94
  end
98
95
 
@@ -106,9 +103,7 @@ module Skylight::Normalizers::GraphQL
106
103
  def normalize(trace, _name, payload)
107
104
  query_name = extract_query_name(payload[:query])
108
105
 
109
- if query_name == ANONYMOUS
110
- meta = { mute_children: true }
111
- end
106
+ meta = { mute_children: true } if query_name == ANONYMOUS
112
107
 
113
108
  # This is probably always overriden by execute_multiplex#normalize_after,
114
109
  # but in the case of a single query, it will be the same value anyway.
@@ -50,32 +50,30 @@ module Skylight
50
50
 
51
51
  private
52
52
 
53
- def relative_path?(path)
54
- !absolute_path?(path)
55
- end
53
+ def relative_path?(path)
54
+ !absolute_path?(path)
55
+ end
56
56
 
57
- SEPARATOR_BYTE = File::SEPARATOR.ord
57
+ SEPARATOR_BYTE = File::SEPARATOR.ord
58
58
 
59
- if File.const_defined?(:NULL) ? File::NULL == "NUL" : RbConfig::CONFIG["host_os"] =~ /mingw|mswin32/
60
- # This is a DOSish environment
61
- ALT_SEPARATOR_BYTE = File::ALT_SEPARATOR&.ord
62
- COLON_BYTE = ":".ord
63
- SEPARATOR_BYTES = [SEPARATOR_BYTE, ALT_SEPARATOR_BYTE].freeze
59
+ if File.const_defined?(:NULL) ? File::NULL == "NUL" : RbConfig::CONFIG["host_os"] =~ /mingw|mswin32/
60
+ # This is a DOSish environment
61
+ ALT_SEPARATOR_BYTE = File::ALT_SEPARATOR&.ord
62
+ COLON_BYTE = ":".ord
63
+ SEPARATOR_BYTES = [SEPARATOR_BYTE, ALT_SEPARATOR_BYTE].freeze
64
64
 
65
- def absolute_path?(path)
66
- if alpha?(path.getbyte(0)) && path.getbyte(1) == COLON_BYTE
67
- SEPARATOR_BYTES.include?(path.getbyte(2))
68
- end
69
- end
65
+ def absolute_path?(path)
66
+ SEPARATOR_BYTES.include?(path.getbyte(2)) if alpha?(path.getbyte(0)) && path.getbyte(1) == COLON_BYTE
67
+ end
70
68
 
71
- def alpha?(byte)
72
- (byte >= 65 && byte <= 90) || (byte >= 97 && byte <= 122)
73
- end
74
- else
75
- def absolute_path?(path)
76
- path.getbyte(0) == SEPARATOR_BYTE
77
- end
69
+ def alpha?(byte)
70
+ (byte >= 65 && byte <= 90) || (byte >= 97 && byte <= 122)
71
+ end
72
+ else
73
+ def absolute_path?(path)
74
+ path.getbyte(0) == SEPARATOR_BYTE
78
75
  end
76
+ end
79
77
  end
80
78
  end
81
79
  end
@@ -2,30 +2,28 @@ module Skylight
2
2
  module Normalizers
3
3
  class Shrine < Normalizer
4
4
  TITLES = {
5
- "upload.shrine" => "Upload",
6
- "download.shrine" => "Download",
7
- "open.shrine" => "Open",
8
- "exists.shrine" => "Exists",
9
- "delete.shrine" => "Delete",
10
- "metadata.shrine" => "Metadata",
11
- "mime_type.shrine" => "MIME Type",
5
+ "upload.shrine" => "Upload",
6
+ "download.shrine" => "Download",
7
+ "open.shrine" => "Open",
8
+ "exists.shrine" => "Exists",
9
+ "delete.shrine" => "Delete",
10
+ "metadata.shrine" => "Metadata",
11
+ "mime_type.shrine" => "MIME Type",
12
12
  "image_dimensions.shrine" => "Image Dimensions",
13
- "signature.shrine" => "Signature",
14
- "extension.shrine" => "Extension",
15
- "derivation.shrine" => "Derivation",
16
- "derivatives.shrine" => "Derivatives",
17
- "data_uri.shrine" => "Data URI",
18
- "remote_url.shrine" => "Remote URL"
13
+ "signature.shrine" => "Signature",
14
+ "extension.shrine" => "Extension",
15
+ "derivation.shrine" => "Derivation",
16
+ "derivatives.shrine" => "Derivatives",
17
+ "data_uri.shrine" => "Data URI",
18
+ "remote_url.shrine" => "Remote URL"
19
19
  }.freeze
20
20
 
21
- TITLES.each_key do |key|
22
- register key
23
- end
21
+ TITLES.each_key { |key| register key }
24
22
 
25
23
  def normalize(_trace, name, _payload)
26
24
  title = ["Shrine", TITLES[name]].join(" ")
27
25
 
28
- cat = "app.#{name.split('.').reverse.join('.')}"
26
+ cat = "app.#{name.split(".").reverse.join(".")}"
29
27
 
30
28
  [cat, title, nil]
31
29
  end
@@ -19,7 +19,7 @@ module Skylight
19
19
  when "SCHEMA", "CACHE"
20
20
  return :skip
21
21
  else
22
- name = CAT
22
+ name = CAT
23
23
  title = payload[:name] || "SQL"
24
24
  end
25
25
 
@@ -30,9 +30,9 @@ module Skylight
30
30
  unless sql.valid_encoding?
31
31
  if config[:log_sql_parse_errors]
32
32
  config.logger.error "[#{Skylight::SqlLexError.formatted_code}] Unable to extract binds from non-UTF-8 " \
33
- "query. " \
34
- "encoding=#{payload[:sql].encoding.name} " \
35
- "sql=#{payload[:sql].inspect} "
33
+ "query. " \
34
+ "encoding=#{payload[:sql].encoding.name} " \
35
+ "sql=#{payload[:sql].inspect} "
36
36
  end
37
37
 
38
38
  sql = nil
@@ -26,31 +26,35 @@ module Skylight
26
26
 
27
27
  private
28
28
 
29
- def log_install_exception(err)
30
- description = err.class.to_s
31
- description << ": #{err.message}" unless err.message.empty?
32
-
33
- backtrace = err.backtrace.map { |l| " #{l}" }.join("\n")
34
-
35
- gems =
36
- begin
37
- Bundler.locked_gems.dependencies.map { |d| [d.name, d.requirement.to_s] }
38
- rescue # rubocop:disable Lint/SuppressedException
39
- end
40
-
41
- error = "[SKYLIGHT] [#{Skylight::VERSION}] Encountered an error while installing the " \
42
- "probe for #{const_name}. Please notify support@skylight.io with the debugging " \
43
- "information below. It's recommended that you disable this probe until the " \
44
- "issue is resolved." \
45
- "\n\nERROR: #{description}\n\n#{backtrace}\n\n"
46
-
47
- if gems
48
- gems_string = gems.map { |g| " #{g[0]} #{g[1]}" }.join("\n")
49
- error << "GEMS:\n\n#{gems_string}\n\n"
29
+ def log_install_exception(err)
30
+ description = err.class.to_s
31
+ description << ": #{err.message}" unless err.message.empty?
32
+
33
+ backtrace = err.backtrace.map { |l| " #{l}" }.join("\n")
34
+
35
+ # rubocop:disable Lint/SuppressedException
36
+ gems =
37
+ begin
38
+ Bundler.locked_gems.dependencies.map { |d| [d.name, d.requirement.to_s] }
39
+ rescue StandardError
50
40
  end
51
41
 
52
- $stderr.puts(error)
42
+ # rubocop:enable Lint/SuppressedException
43
+
44
+ error =
45
+ "[SKYLIGHT] [#{Skylight::VERSION}] Encountered an error while installing the " \
46
+ "probe for #{const_name}. Please notify support@skylight.io with the debugging " \
47
+ "information below. It's recommended that you disable this probe until the " \
48
+ "issue is resolved." \
49
+ "\n\nERROR: #{description}\n\n#{backtrace}\n\n"
50
+
51
+ if gems
52
+ gems_string = gems.map { |g| " #{g[0]} #{g[1]}" }.join("\n")
53
+ error << "GEMS:\n\n#{gems_string}\n\n"
53
54
  end
55
+
56
+ $stderr.puts(error)
57
+ end
54
58
  end
55
59
 
56
60
  class << self
@@ -62,11 +66,7 @@ module Skylight
62
66
  pending = registered.values - installed.values
63
67
 
64
68
  pending.each do |registration|
65
- if registration.constant_available?
66
- install_probe(registration)
67
- else
68
- register_require_hook(registration)
69
- end
69
+ registration.constant_available? ? install_probe(registration) : register_require_hook(registration)
70
70
  end
71
71
  end
72
72
 
@@ -79,14 +79,14 @@ module Skylight
79
79
 
80
80
  def add_path(path)
81
81
  root = Pathname.new(path)
82
- Pathname.glob(root.join("./**/*.rb")).each do |f|
83
- name = f.relative_path_from(root).sub_ext("").to_s
84
- if available.key?(name)
85
- raise "duplicate probe name: #{name}; original=#{available[name]}; new=#{f}"
86
- end
82
+ Pathname
83
+ .glob(root.join("./**/*.rb"))
84
+ .each do |f|
85
+ name = f.relative_path_from(root).sub_ext("").to_s
86
+ raise "duplicate probe name: #{name}; original=#{available[name]}; new=#{f}" if available.key?(name)
87
87
 
88
- available[name] = f
89
- end
88
+ available[name] = f
89
+ end
90
90
  end
91
91
 
92
92
  def available
@@ -95,13 +95,9 @@ module Skylight
95
95
 
96
96
  def probe(*probes)
97
97
  unknown = probes.map(&:to_s) - available.keys
98
- unless unknown.empty?
99
- raise ArgumentError, "unknown probes: #{unknown.join(', ')}"
100
- end
98
+ raise ArgumentError, "unknown probes: #{unknown.join(", ")}" unless unknown.empty?
101
99
 
102
- probes.each do |p|
103
- require available[p.to_s]
104
- end
100
+ probes.each { |p| require available[p.to_s] }
105
101
  end
106
102
 
107
103
  def registered
@@ -117,9 +113,7 @@ module Skylight
117
113
  end
118
114
 
119
115
  def register(name, *args)
120
- if registered.key?(name)
121
- raise "already registered: #{name}"
122
- end
116
+ raise "already registered: #{name}" if registered.key?(name)
123
117
 
124
118
  registered[name] = ProbeRegistration.new(name, *args)
125
119
 
@@ -156,9 +150,7 @@ module Skylight
156
150
  return unless require_hooks.key?(require_path)
157
151
 
158
152
  # dup because we may be mutating the array
159
- require_hooks[require_path].dup.each do |registration|
160
- yield registration
161
- end
153
+ require_hooks[require_path].dup.each { |registration| yield registration }
162
154
  end
163
155
  end
164
156
 
@@ -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