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
@@ -10,9 +10,9 @@ module Skylight
|
|
10
10
|
|
11
11
|
private
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
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(
|
27
|
-
|
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")
|
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(
|
26
|
-
|
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 =
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
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
|
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(
|
48
|
-
|
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)
|
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)
|
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(
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
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 =
|
48
|
-
|
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:
|
88
|
-
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
|
-
|
103
|
-
|
104
|
-
|
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
|
-
|
128
|
-
|
129
|
-
|
122
|
+
def plugin_defined?
|
123
|
+
defined?(::Skylight::Probes::DelayedJob::Plugin)
|
124
|
+
end
|
130
125
|
|
131
|
-
|
132
|
-
|
133
|
-
|
126
|
+
def validate_version
|
127
|
+
spec = Gem.loaded_specs["delayed_job"]
|
128
|
+
version = spec&.version
|
134
129
|
|
135
|
-
|
136
|
-
|
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
|
-
|
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:
|
12
|
+
name: "Request",
|
13
13
|
method: method,
|
14
|
-
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)
|
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
|
@@ -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
|
-
|
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
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
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
|
-
|
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
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
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
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
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
|
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)
|
@@ -16,7 +16,7 @@ module Skylight
|
|
16
16
|
elsif middleware.respond_to?(:call)
|
17
17
|
middleware.method(:call).source_location
|
18
18
|
end
|
19
|
-
rescue
|
19
|
+
rescue StandardError
|
20
20
|
nil
|
21
21
|
end
|
22
22
|
end
|
@@ -72,8 +72,13 @@ module Skylight
|
|
72
72
|
|
73
73
|
source_file, source_line = method(__method__).super_method.source_location
|
74
74
|
|
75
|
-
spans =
|
76
|
-
|
75
|
+
spans =
|
76
|
+
Skylight.instrument(
|
77
|
+
title: name,
|
78
|
+
category: __sk_category,
|
79
|
+
source_file: source_file,
|
80
|
+
source_line: source_line
|
81
|
+
)
|
77
82
|
|
78
83
|
proxied_response =
|
79
84
|
Skylight::Middleware.with_after_close(super(*args), debug_identifier: "Middleware: #{name}") do
|
@@ -120,7 +125,11 @@ module Skylight
|
|
120
125
|
end
|
121
126
|
end
|
122
127
|
|
123
|
-
register(
|
124
|
-
|
128
|
+
register(
|
129
|
+
:middleware,
|
130
|
+
"ActionDispatch::MiddlewareStack::Middleware",
|
131
|
+
"actionpack/action_dispatch",
|
132
|
+
Middleware::Probe.new
|
133
|
+
)
|
125
134
|
end
|
126
135
|
end
|
@@ -14,9 +14,7 @@ module Skylight
|
|
14
14
|
|
15
15
|
COMMANDS = %i[insert find count distinct update findandmodify findAndModify delete aggregate].freeze
|
16
16
|
|
17
|
-
COMMAND_NAMES = {
|
18
|
-
findandmodify: "findAndModify".freeze
|
19
|
-
}.freeze
|
17
|
+
COMMAND_NAMES = { findandmodify: "findAndModify".freeze }.freeze
|
20
18
|
|
21
19
|
def initialize
|
22
20
|
@events = {}
|
@@ -41,121 +39,115 @@ module Skylight
|
|
41
39
|
|
42
40
|
private
|
43
41
|
|
44
|
-
|
45
|
-
|
42
|
+
def begin_instrumentation(event)
|
43
|
+
return unless COMMANDS.include?(event.command_name.to_sym)
|
46
44
|
|
47
|
-
|
45
|
+
command_name = COMMAND_NAMES[event.command_name] || event.command_name.to_s
|
48
46
|
|
49
|
-
|
47
|
+
title = "#{event.database_name}.#{command_name}"
|
50
48
|
|
51
|
-
|
49
|
+
command = event.command
|
52
50
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
payload = {}
|
60
|
-
|
61
|
-
# Ruby Hashes are ordered based on insertion so do the most important ones first
|
51
|
+
# Not sure if this will always exist
|
52
|
+
# Delete so the description will be less redundant
|
53
|
+
if (target = command[event.command_name])
|
54
|
+
title << " #{target}"
|
55
|
+
end
|
62
56
|
|
63
|
-
|
64
|
-
add_bound("query".freeze, command, payload)
|
65
|
-
add_bound("filter".freeze, command, payload)
|
66
|
-
add_value("sort".freeze, command, payload)
|
57
|
+
payload = {}
|
67
58
|
|
68
|
-
|
69
|
-
add_bound("update".freeze, command, payload)
|
70
|
-
end
|
59
|
+
# Ruby Hashes are ordered based on insertion so do the most important ones first
|
71
60
|
|
72
|
-
|
73
|
-
|
61
|
+
add_value("key".freeze, command, payload)
|
62
|
+
add_bound("query".freeze, command, payload)
|
63
|
+
add_bound("filter".freeze, command, payload)
|
64
|
+
add_value("sort".freeze, command, payload)
|
74
65
|
|
75
|
-
|
76
|
-
# AFAICT the gem generally just sends one item in the updates array
|
77
|
-
update = updates[0]
|
78
|
-
update_payload = {}
|
79
|
-
add_bound("q".freeze, update, update_payload)
|
80
|
-
add_bound("u".freeze, update, update_payload)
|
81
|
-
add_value("multi".freeze, update, update_payload)
|
82
|
-
add_value("upsert".freeze, update, update_payload)
|
66
|
+
add_bound("update".freeze, command, payload) if command_name == "findAndModify".freeze
|
83
67
|
|
84
|
-
|
68
|
+
add_value("remove".freeze, command, payload)
|
69
|
+
add_value("new".freeze, command, payload)
|
85
70
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
71
|
+
if (updates = command["updates".freeze])
|
72
|
+
# AFAICT the gem generally just sends one item in the updates array
|
73
|
+
update = updates[0]
|
74
|
+
update_payload = {}
|
75
|
+
add_bound("q".freeze, update, update_payload)
|
76
|
+
add_bound("u".freeze, update, update_payload)
|
77
|
+
add_value("multi".freeze, update, update_payload)
|
78
|
+
add_value("upsert".freeze, update, update_payload)
|
90
79
|
|
91
|
-
|
92
|
-
# AFAICT the gem generally just sends one item in the updates array
|
93
|
-
delete = deletes[0]
|
94
|
-
delete_payload = {}
|
95
|
-
add_bound("q".freeze, delete, delete_payload)
|
96
|
-
add_value("limit".freeze, delete, delete_payload)
|
80
|
+
payload["updates".freeze] = [update_payload]
|
97
81
|
|
98
|
-
|
82
|
+
payload["updates".freeze] << "..." if updates.length > 1
|
83
|
+
end
|
99
84
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
85
|
+
if (deletes = command["deletes".freeze])
|
86
|
+
# AFAICT the gem generally just sends one item in the updates array
|
87
|
+
delete = deletes[0]
|
88
|
+
delete_payload = {}
|
89
|
+
add_bound("q".freeze, delete, delete_payload)
|
90
|
+
add_value("limit".freeze, delete, delete_payload)
|
104
91
|
|
105
|
-
|
106
|
-
payload["pipeline".freeze] = pipeline.map { |segment| extract_binds(segment) }
|
107
|
-
end
|
92
|
+
payload["deletes".freeze] = [delete_payload]
|
108
93
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
opts = {
|
113
|
-
category: CAT,
|
114
|
-
title: title,
|
115
|
-
description: payload.empty? ? nil : payload.to_json,
|
116
|
-
meta: { database: event.database_name },
|
117
|
-
internal: true
|
118
|
-
}
|
94
|
+
payload["deletes".freeze] << "..." if deletes.length > 1
|
95
|
+
end
|
119
96
|
|
120
|
-
|
121
|
-
|
122
|
-
error "failed to begin instrumentation for Mongo; msg=%s", e.message
|
97
|
+
if (pipeline = command["pipeline".freeze])
|
98
|
+
payload["pipeline".freeze] = pipeline.map { |segment| extract_binds(segment) }
|
123
99
|
end
|
124
100
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
101
|
+
# We're ignoring documents from insert because they could have completely inconsistent
|
102
|
+
# format which would make it hard to merge.
|
103
|
+
|
104
|
+
opts = {
|
105
|
+
category: CAT,
|
106
|
+
title: title,
|
107
|
+
description: payload.empty? ? nil : payload.to_json,
|
108
|
+
meta: {
|
109
|
+
database: event.database_name
|
110
|
+
},
|
111
|
+
internal: true
|
112
|
+
}
|
113
|
+
|
114
|
+
@events[event.operation_id] = Skylight.instrument(opts)
|
115
|
+
rescue Exception => e
|
116
|
+
error "failed to begin instrumentation for Mongo; msg=%s", e.message
|
117
|
+
end
|
118
|
+
|
119
|
+
def end_instrumentation(event)
|
120
|
+
if (original_event = @events.delete(event.operation_id))
|
121
|
+
meta = {}
|
122
|
+
if event.is_a?(::Mongo::Monitoring::Event::CommandFailed)
|
123
|
+
meta[:exception] = ["CommandFailed", event.message]
|
132
124
|
end
|
133
|
-
|
134
|
-
error "failed to end instrumentation for Mongo; msg=%s", e.message
|
125
|
+
Skylight.done(original_event, meta)
|
135
126
|
end
|
127
|
+
rescue Exception => e
|
128
|
+
error "failed to end instrumentation for Mongo; msg=%s", e.message
|
129
|
+
end
|
136
130
|
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
end
|
131
|
+
def add_value(key, command, payload)
|
132
|
+
if command.key?(key)
|
133
|
+
value = command[key]
|
134
|
+
payload[key] = value
|
142
135
|
end
|
136
|
+
end
|
143
137
|
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
end
|
138
|
+
def add_bound(key, command, payload)
|
139
|
+
if (value = command[key])
|
140
|
+
payload[key] = extract_binds(value)
|
148
141
|
end
|
142
|
+
end
|
149
143
|
|
150
|
-
|
151
|
-
|
144
|
+
def extract_binds(hash)
|
145
|
+
ret = {}
|
152
146
|
|
153
|
-
|
154
|
-
ret[k] = v.is_a?(Hash) ? extract_binds(v) : "?".freeze
|
155
|
-
end
|
147
|
+
hash.each { |k, v| ret[k] = v.is_a?(Hash) ? extract_binds(v) : "?".freeze }
|
156
148
|
|
157
|
-
|
158
|
-
|
149
|
+
ret
|
150
|
+
end
|
159
151
|
end
|
160
152
|
end
|
161
153
|
|