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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +395 -364
- data/CLA.md +1 -1
- data/LICENSE.md +7 -17
- data/README.md +1 -1
- data/ext/extconf.rb +42 -54
- data/ext/libskylight.yml +9 -6
- data/lib/skylight.rb +20 -30
- data/lib/skylight/api.rb +22 -18
- data/lib/skylight/cli.rb +47 -46
- data/lib/skylight/cli/doctor.rb +50 -50
- data/lib/skylight/cli/helpers.rb +19 -19
- data/lib/skylight/cli/merger.rb +141 -139
- data/lib/skylight/config.rb +265 -300
- data/lib/skylight/deprecation.rb +4 -4
- data/lib/skylight/errors.rb +3 -4
- data/lib/skylight/extensions.rb +17 -29
- data/lib/skylight/extensions/source_location.rb +128 -128
- data/lib/skylight/formatters/http.rb +1 -3
- data/lib/skylight/gc.rb +30 -40
- data/lib/skylight/helpers.rb +43 -41
- data/lib/skylight/instrumenter.rb +25 -18
- data/lib/skylight/middleware.rb +31 -35
- data/lib/skylight/native.rb +8 -10
- data/lib/skylight/native_ext_fetcher.rb +10 -12
- data/lib/skylight/normalizers.rb +43 -39
- data/lib/skylight/normalizers/action_controller/process_action.rb +24 -25
- data/lib/skylight/normalizers/action_controller/send_file.rb +7 -6
- data/lib/skylight/normalizers/action_dispatch/route_set.rb +7 -7
- data/lib/skylight/normalizers/active_job/perform.rb +48 -44
- data/lib/skylight/normalizers/active_model_serializers/render.rb +7 -3
- data/lib/skylight/normalizers/active_storage.rb +11 -13
- data/lib/skylight/normalizers/active_support/cache.rb +1 -12
- data/lib/skylight/normalizers/coach/handler_finish.rb +1 -3
- data/lib/skylight/normalizers/default.rb +1 -9
- data/lib/skylight/normalizers/faraday/request.rb +1 -3
- data/lib/skylight/normalizers/grape/endpoint.rb +13 -19
- data/lib/skylight/normalizers/grape/endpoint_run.rb +16 -18
- data/lib/skylight/normalizers/grape/endpoint_run_filters.rb +1 -3
- data/lib/skylight/normalizers/graphql/base.rb +23 -28
- data/lib/skylight/normalizers/render.rb +19 -21
- data/lib/skylight/normalizers/shrine.rb +15 -17
- data/lib/skylight/normalizers/sql.rb +4 -4
- data/lib/skylight/probes.rb +38 -46
- data/lib/skylight/probes/action_controller.rb +32 -28
- data/lib/skylight/probes/action_dispatch/request_id.rb +9 -5
- data/lib/skylight/probes/action_dispatch/routing/route_set.rb +7 -5
- data/lib/skylight/probes/action_view.rb +9 -10
- data/lib/skylight/probes/active_job_enqueue.rb +3 -9
- data/lib/skylight/probes/active_model_serializers.rb +8 -8
- data/lib/skylight/probes/delayed_job.rb +37 -42
- data/lib/skylight/probes/elasticsearch.rb +3 -5
- data/lib/skylight/probes/excon.rb +1 -1
- data/lib/skylight/probes/excon/middleware.rb +22 -23
- data/lib/skylight/probes/graphql.rb +2 -7
- data/lib/skylight/probes/middleware.rb +14 -5
- data/lib/skylight/probes/mongo.rb +83 -91
- data/lib/skylight/probes/net_http.rb +1 -1
- data/lib/skylight/probes/redis.rb +5 -17
- data/lib/skylight/probes/sequel.rb +7 -11
- data/lib/skylight/probes/sinatra.rb +8 -5
- data/lib/skylight/probes/tilt.rb +2 -4
- data/lib/skylight/railtie.rb +121 -135
- data/lib/skylight/sidekiq.rb +4 -5
- data/lib/skylight/subscriber.rb +31 -33
- data/lib/skylight/test.rb +89 -84
- data/lib/skylight/trace.rb +121 -115
- data/lib/skylight/user_config.rb +14 -17
- data/lib/skylight/util/clock.rb +1 -0
- data/lib/skylight/util/component.rb +18 -21
- data/lib/skylight/util/deploy.rb +11 -13
- data/lib/skylight/util/http.rb +104 -105
- data/lib/skylight/util/logging.rb +4 -6
- data/lib/skylight/util/lru_cache.rb +2 -6
- data/lib/skylight/util/platform.rb +2 -6
- data/lib/skylight/util/ssl.rb +1 -25
- data/lib/skylight/version.rb +1 -1
- data/lib/skylight/vm/gc.rb +1 -9
- metadata +6 -6
@@ -14,27 +14,25 @@ module Skylight
|
|
14
14
|
|
15
15
|
private
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
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
|
-
|
31
|
-
|
32
|
-
|
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
|
-
|
35
|
-
|
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
|
-
|
47
|
-
|
48
|
-
|
41
|
+
def key
|
42
|
+
self.class.key
|
43
|
+
end
|
49
44
|
|
50
|
-
|
51
|
-
|
52
|
-
|
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 =
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
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
|
-
|
54
|
-
|
55
|
-
|
53
|
+
def relative_path?(path)
|
54
|
+
!absolute_path?(path)
|
55
|
+
end
|
56
56
|
|
57
|
-
|
57
|
+
SEPARATOR_BYTE = File::SEPARATOR.ord
|
58
58
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
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
|
-
|
66
|
-
|
67
|
-
|
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
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
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"
|
6
|
-
"download.shrine"
|
7
|
-
"open.shrine"
|
8
|
-
"exists.shrine"
|
9
|
-
"delete.shrine"
|
10
|
-
"metadata.shrine"
|
11
|
-
"mime_type.shrine"
|
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"
|
14
|
-
"extension.shrine"
|
15
|
-
"derivation.shrine"
|
16
|
-
"derivatives.shrine"
|
17
|
-
"data_uri.shrine"
|
18
|
-
"remote_url.shrine"
|
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
|
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(
|
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
|
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
|
-
|
34
|
-
|
35
|
-
|
33
|
+
"query. " \
|
34
|
+
"encoding=#{payload[:sql].encoding.name} " \
|
35
|
+
"sql=#{payload[:sql].inspect} "
|
36
36
|
end
|
37
37
|
|
38
38
|
sql = nil
|
data/lib/skylight/probes.rb
CHANGED
@@ -26,31 +26,35 @@ module Skylight
|
|
26
26
|
|
27
27
|
private
|
28
28
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
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
|
-
|
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
|
-
|
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
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
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
|
-
|
89
|
-
|
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
|
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
|
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
|
-
|
11
|
-
|
12
|
-
|
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
|
-
|
15
|
-
|
16
|
-
|
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
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
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
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
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(
|
46
|
-
|
45
|
+
register(
|
46
|
+
:action_controller,
|
47
|
+
"ActionController::Instrumentation",
|
48
|
+
"action_controller/metal/instrumentation",
|
49
|
+
ActionController::Probe.new
|
50
|
+
)
|
47
51
|
end
|
48
52
|
end
|