brainzlab 0.1.2 → 0.1.4
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/LICENSE +6 -21
- data/README.md +16 -2
- data/lib/brainzlab/beacon/client.rb +38 -40
- data/lib/brainzlab/beacon/provisioner.rb +1 -1
- data/lib/brainzlab/beacon.rb +15 -15
- data/lib/brainzlab/configuration.rb +112 -90
- data/lib/brainzlab/context.rb +2 -3
- data/lib/brainzlab/cortex/client.rb +29 -31
- data/lib/brainzlab/cortex/provisioner.rb +1 -1
- data/lib/brainzlab/cortex.rb +7 -11
- data/lib/brainzlab/dendrite/client.rb +42 -44
- data/lib/brainzlab/dendrite/provisioner.rb +1 -1
- data/lib/brainzlab/dendrite.rb +4 -4
- data/lib/brainzlab/devtools/data/collector.rb +22 -22
- data/lib/brainzlab/devtools/middleware/asset_server.rb +14 -14
- data/lib/brainzlab/devtools/middleware/database_handler.rb +52 -55
- data/lib/brainzlab/devtools/middleware/debug_panel.rb +19 -19
- data/lib/brainzlab/devtools/middleware/error_page.rb +45 -44
- data/lib/brainzlab/devtools/renderers/debug_panel_renderer.rb +39 -35
- data/lib/brainzlab/devtools/renderers/error_page_renderer.rb +13 -9
- data/lib/brainzlab/devtools.rb +11 -11
- data/lib/brainzlab/flux/buffer.rb +3 -3
- data/lib/brainzlab/flux/client.rb +14 -16
- data/lib/brainzlab/flux/provisioner.rb +13 -13
- data/lib/brainzlab/flux.rb +8 -8
- data/lib/brainzlab/instrumentation/action_cable.rb +351 -0
- data/lib/brainzlab/instrumentation/action_controller.rb +649 -0
- data/lib/brainzlab/instrumentation/action_dispatch.rb +259 -0
- data/lib/brainzlab/instrumentation/action_mailbox.rb +197 -0
- data/lib/brainzlab/instrumentation/action_mailer.rb +14 -13
- data/lib/brainzlab/instrumentation/action_view.rb +380 -0
- data/lib/brainzlab/instrumentation/active_job.rb +569 -0
- data/lib/brainzlab/instrumentation/active_record.rb +467 -36
- data/lib/brainzlab/instrumentation/active_storage.rb +541 -0
- data/lib/brainzlab/instrumentation/active_support_cache.rb +700 -0
- data/lib/brainzlab/instrumentation/aws.rb +43 -39
- data/lib/brainzlab/instrumentation/dalli.rb +20 -20
- data/lib/brainzlab/instrumentation/delayed_job.rb +27 -29
- data/lib/brainzlab/instrumentation/elasticsearch.rb +23 -24
- data/lib/brainzlab/instrumentation/excon.rb +27 -27
- data/lib/brainzlab/instrumentation/faraday.rb +3 -4
- data/lib/brainzlab/instrumentation/good_job.rb +28 -28
- data/lib/brainzlab/instrumentation/grape.rb +24 -24
- data/lib/brainzlab/instrumentation/graphql.rb +24 -23
- data/lib/brainzlab/instrumentation/httparty.rb +13 -14
- data/lib/brainzlab/instrumentation/mongodb.rb +7 -7
- data/lib/brainzlab/instrumentation/net_http.rb +6 -6
- data/lib/brainzlab/instrumentation/rails_deprecation.rb +139 -0
- data/lib/brainzlab/instrumentation/railties.rb +134 -0
- data/lib/brainzlab/instrumentation/redis.rb +14 -21
- data/lib/brainzlab/instrumentation/resque.rb +23 -24
- data/lib/brainzlab/instrumentation/sidekiq.rb +29 -28
- data/lib/brainzlab/instrumentation/solid_queue.rb +37 -41
- data/lib/brainzlab/instrumentation/stripe.rb +36 -37
- data/lib/brainzlab/instrumentation/typhoeus.rb +19 -17
- data/lib/brainzlab/instrumentation.rb +111 -21
- data/lib/brainzlab/nerve/client.rb +38 -40
- data/lib/brainzlab/nerve/provisioner.rb +1 -1
- data/lib/brainzlab/nerve.rb +6 -6
- data/lib/brainzlab/pulse/client.rb +15 -11
- data/lib/brainzlab/pulse/instrumentation.rb +61 -57
- data/lib/brainzlab/pulse/propagation.rb +28 -28
- data/lib/brainzlab/pulse/provisioner.rb +12 -12
- data/lib/brainzlab/pulse/tracer.rb +3 -3
- data/lib/brainzlab/pulse.rb +13 -13
- data/lib/brainzlab/rails/log_formatter.rb +127 -121
- data/lib/brainzlab/rails/log_subscriber.rb +70 -76
- data/lib/brainzlab/rails/railtie.rb +66 -89
- data/lib/brainzlab/recall/buffer.rb +1 -1
- data/lib/brainzlab/recall/client.rb +14 -10
- data/lib/brainzlab/recall/logger.rb +16 -18
- data/lib/brainzlab/recall/provisioner.rb +16 -16
- data/lib/brainzlab/recall.rb +11 -13
- data/lib/brainzlab/reflex/breadcrumbs.rb +2 -2
- data/lib/brainzlab/reflex/client.rb +14 -10
- data/lib/brainzlab/reflex/provisioner.rb +12 -12
- data/lib/brainzlab/reflex.rb +29 -29
- data/lib/brainzlab/sentinel/client.rb +40 -42
- data/lib/brainzlab/sentinel/provisioner.rb +1 -1
- data/lib/brainzlab/sentinel.rb +5 -5
- data/lib/brainzlab/signal/client.rb +12 -14
- data/lib/brainzlab/signal/provisioner.rb +12 -12
- data/lib/brainzlab/signal.rb +7 -7
- data/lib/brainzlab/synapse/client.rb +42 -44
- data/lib/brainzlab/synapse/provisioner.rb +1 -1
- data/lib/brainzlab/synapse.rb +6 -6
- data/lib/brainzlab/utilities/circuit_breaker.rb +37 -41
- data/lib/brainzlab/utilities/health_check.rb +53 -55
- data/lib/brainzlab/utilities/log_formatter.rb +38 -40
- data/lib/brainzlab/utilities/rate_limiter.rb +5 -5
- data/lib/brainzlab/utilities.rb +4 -4
- data/lib/brainzlab/vault/cache.rb +1 -1
- data/lib/brainzlab/vault/client.rb +39 -41
- data/lib/brainzlab/vault/provisioner.rb +1 -1
- data/lib/brainzlab/vault.rb +19 -25
- data/lib/brainzlab/version.rb +1 -1
- data/lib/brainzlab/vision/client.rb +20 -20
- data/lib/brainzlab/vision/provisioner.rb +21 -21
- data/lib/brainzlab/vision.rb +17 -19
- data/lib/brainzlab-sdk.rb +1 -1
- data/lib/brainzlab.rb +22 -24
- data/lib/generators/brainzlab/install/install_generator.rb +29 -27
- metadata +11 -1
|
@@ -10,7 +10,7 @@ module BrainzLab
|
|
|
10
10
|
install_notifier!
|
|
11
11
|
install_middleware!
|
|
12
12
|
|
|
13
|
-
BrainzLab.debug_log(
|
|
13
|
+
BrainzLab.debug_log('[Instrumentation] GoodJob instrumentation installed')
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
private
|
|
@@ -19,12 +19,12 @@ module BrainzLab
|
|
|
19
19
|
return unless defined?(::ActiveSupport::Notifications)
|
|
20
20
|
|
|
21
21
|
# GoodJob emits ActiveSupport notifications
|
|
22
|
-
::ActiveSupport::Notifications.subscribe(
|
|
22
|
+
::ActiveSupport::Notifications.subscribe('perform_job.good_job') do |*args|
|
|
23
23
|
event = ::ActiveSupport::Notifications::Event.new(*args)
|
|
24
24
|
handle_perform(event)
|
|
25
25
|
end
|
|
26
26
|
|
|
27
|
-
::ActiveSupport::Notifications.subscribe(
|
|
27
|
+
::ActiveSupport::Notifications.subscribe('finished_job_task.good_job') do |*args|
|
|
28
28
|
event = ::ActiveSupport::Notifications::Event.new(*args)
|
|
29
29
|
handle_finished(event)
|
|
30
30
|
end
|
|
@@ -34,25 +34,28 @@ module BrainzLab
|
|
|
34
34
|
return unless defined?(::GoodJob::Adapter)
|
|
35
35
|
|
|
36
36
|
# Add our callback to GoodJob
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
return unless ::GoodJob.respond_to?(:on_thread_error)
|
|
38
|
+
|
|
39
|
+
::GoodJob.on_thread_error = lambda { |error|
|
|
40
|
+
if BrainzLab.configuration.reflex_effectively_enabled?
|
|
41
|
+
BrainzLab::Reflex.capture(error,
|
|
42
|
+
tags: { source: 'good_job' })
|
|
40
43
|
end
|
|
41
|
-
|
|
44
|
+
}
|
|
42
45
|
end
|
|
43
46
|
|
|
44
47
|
def handle_perform(event)
|
|
45
48
|
payload = event.payload
|
|
46
49
|
job = payload[:job]
|
|
47
|
-
job_class = job&.class&.name || payload[:job_class] ||
|
|
48
|
-
queue = job&.queue_name || payload[:queue_name] ||
|
|
50
|
+
job_class = job&.class&.name || payload[:job_class] || 'Unknown'
|
|
51
|
+
queue = job&.queue_name || payload[:queue_name] || 'default'
|
|
49
52
|
duration_ms = event.duration.round(2)
|
|
50
53
|
|
|
51
54
|
# Track with Pulse
|
|
52
55
|
if BrainzLab.configuration.pulse_effectively_enabled?
|
|
53
56
|
BrainzLab::Pulse.record_trace(
|
|
54
57
|
"job.#{job_class}",
|
|
55
|
-
kind:
|
|
58
|
+
kind: 'job',
|
|
56
59
|
started_at: event.time,
|
|
57
60
|
ended_at: event.end,
|
|
58
61
|
job_class: job_class,
|
|
@@ -67,33 +70,30 @@ module BrainzLab
|
|
|
67
70
|
# Track with Flux
|
|
68
71
|
if BrainzLab.configuration.flux_effectively_enabled?
|
|
69
72
|
tags = { job_class: job_class, queue: queue }
|
|
70
|
-
BrainzLab::Flux.distribution(
|
|
71
|
-
BrainzLab::Flux.increment(
|
|
73
|
+
BrainzLab::Flux.distribution('good_job.job.duration_ms', duration_ms, tags: tags)
|
|
74
|
+
BrainzLab::Flux.increment('good_job.job.processed', tags: tags)
|
|
72
75
|
|
|
73
|
-
if payload[:error]
|
|
74
|
-
BrainzLab::Flux.increment("good_job.job.failed", tags: tags)
|
|
75
|
-
end
|
|
76
|
+
BrainzLab::Flux.increment('good_job.job.failed', tags: tags) if payload[:error]
|
|
76
77
|
end
|
|
77
78
|
|
|
78
79
|
# Capture error with Reflex
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
end
|
|
80
|
+
return unless payload[:error] && BrainzLab.configuration.reflex_effectively_enabled?
|
|
81
|
+
|
|
82
|
+
BrainzLab::Reflex.capture(payload[:error],
|
|
83
|
+
tags: { job_class: job_class, queue: queue, source: 'good_job' },
|
|
84
|
+
extra: { job_id: job&.job_id, duration_ms: duration_ms })
|
|
85
85
|
end
|
|
86
86
|
|
|
87
87
|
def handle_finished(event)
|
|
88
88
|
payload = event.payload
|
|
89
89
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
90
|
+
return unless BrainzLab.configuration.flux_effectively_enabled?
|
|
91
|
+
|
|
92
|
+
result = payload[:result]
|
|
93
|
+
if result == :discarded
|
|
94
|
+
BrainzLab::Flux.increment('good_job.job.discarded')
|
|
95
|
+
elsif result == :retried
|
|
96
|
+
BrainzLab::Flux.increment('good_job.job.retried')
|
|
97
97
|
end
|
|
98
98
|
end
|
|
99
99
|
end
|
|
@@ -14,7 +14,7 @@ module BrainzLab
|
|
|
14
14
|
install_notifications!
|
|
15
15
|
|
|
16
16
|
@installed = true
|
|
17
|
-
BrainzLab.debug_log(
|
|
17
|
+
BrainzLab.debug_log('Grape instrumentation installed')
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
def installed?
|
|
@@ -29,23 +29,23 @@ module BrainzLab
|
|
|
29
29
|
|
|
30
30
|
def install_notifications!
|
|
31
31
|
# Grape emits these notifications
|
|
32
|
-
ActiveSupport::Notifications.subscribe(
|
|
32
|
+
ActiveSupport::Notifications.subscribe('endpoint_run.grape') do |*args|
|
|
33
33
|
event = ActiveSupport::Notifications::Event.new(*args)
|
|
34
34
|
record_endpoint(event)
|
|
35
35
|
end
|
|
36
36
|
|
|
37
|
-
ActiveSupport::Notifications.subscribe(
|
|
37
|
+
ActiveSupport::Notifications.subscribe('endpoint_render.grape') do |*args|
|
|
38
38
|
event = ActiveSupport::Notifications::Event.new(*args)
|
|
39
39
|
record_render(event)
|
|
40
40
|
end
|
|
41
41
|
|
|
42
|
-
ActiveSupport::Notifications.subscribe(
|
|
42
|
+
ActiveSupport::Notifications.subscribe('endpoint_run_filters.grape') do |*args|
|
|
43
43
|
event = ActiveSupport::Notifications::Event.new(*args)
|
|
44
44
|
record_filters(event)
|
|
45
45
|
end
|
|
46
46
|
|
|
47
47
|
# Format validation
|
|
48
|
-
ActiveSupport::Notifications.subscribe(
|
|
48
|
+
ActiveSupport::Notifications.subscribe('format_response.grape') do |*args|
|
|
49
49
|
event = ActiveSupport::Notifications::Event.new(*args)
|
|
50
50
|
record_format(event)
|
|
51
51
|
end
|
|
@@ -58,19 +58,19 @@ module BrainzLab
|
|
|
58
58
|
endpoint = payload[:endpoint]
|
|
59
59
|
env = payload[:env] || {}
|
|
60
60
|
|
|
61
|
-
method = env[
|
|
62
|
-
path = endpoint&.options&.dig(:path)&.first || env[
|
|
61
|
+
method = env['REQUEST_METHOD'] || 'GET'
|
|
62
|
+
path = endpoint&.options&.dig(:path)&.first || env['PATH_INFO'] || '/'
|
|
63
63
|
route_pattern = extract_route_pattern(endpoint)
|
|
64
64
|
duration_ms = event.duration.round(2)
|
|
65
65
|
|
|
66
|
-
status = env[
|
|
66
|
+
status = env['api.endpoint']&.status || 200
|
|
67
67
|
level = status >= 400 ? :error : :info
|
|
68
68
|
|
|
69
69
|
# Add breadcrumb for Reflex
|
|
70
70
|
if BrainzLab.configuration.reflex_enabled
|
|
71
71
|
BrainzLab::Reflex.add_breadcrumb(
|
|
72
72
|
"Grape #{method} #{route_pattern}",
|
|
73
|
-
category:
|
|
73
|
+
category: 'grape.endpoint',
|
|
74
74
|
level: level,
|
|
75
75
|
data: {
|
|
76
76
|
method: method,
|
|
@@ -85,7 +85,7 @@ module BrainzLab
|
|
|
85
85
|
# Record span for Pulse
|
|
86
86
|
record_span(
|
|
87
87
|
name: "Grape #{method} #{route_pattern}",
|
|
88
|
-
kind:
|
|
88
|
+
kind: 'grape',
|
|
89
89
|
started_at: event.time,
|
|
90
90
|
ended_at: event.end,
|
|
91
91
|
duration_ms: duration_ms,
|
|
@@ -117,12 +117,12 @@ module BrainzLab
|
|
|
117
117
|
duration_ms = event.duration.round(2)
|
|
118
118
|
|
|
119
119
|
record_span(
|
|
120
|
-
name:
|
|
121
|
-
kind:
|
|
120
|
+
name: 'Grape render',
|
|
121
|
+
kind: 'grape.render',
|
|
122
122
|
started_at: event.time,
|
|
123
123
|
ended_at: event.end,
|
|
124
124
|
duration_ms: duration_ms,
|
|
125
|
-
data: { phase:
|
|
125
|
+
data: { phase: 'render' }
|
|
126
126
|
)
|
|
127
127
|
rescue StandardError => e
|
|
128
128
|
BrainzLab.debug_log("Grape render recording failed: #{e.message}")
|
|
@@ -131,11 +131,11 @@ module BrainzLab
|
|
|
131
131
|
def record_filters(event)
|
|
132
132
|
payload = event.payload
|
|
133
133
|
duration_ms = event.duration.round(2)
|
|
134
|
-
filter_type = payload[:type] ||
|
|
134
|
+
filter_type = payload[:type] || 'filter'
|
|
135
135
|
|
|
136
136
|
record_span(
|
|
137
137
|
name: "Grape #{filter_type} filters",
|
|
138
|
-
kind:
|
|
138
|
+
kind: 'grape.filter',
|
|
139
139
|
started_at: event.time,
|
|
140
140
|
ended_at: event.end,
|
|
141
141
|
duration_ms: duration_ms,
|
|
@@ -149,12 +149,12 @@ module BrainzLab
|
|
|
149
149
|
duration_ms = event.duration.round(2)
|
|
150
150
|
|
|
151
151
|
record_span(
|
|
152
|
-
name:
|
|
153
|
-
kind:
|
|
152
|
+
name: 'Grape format response',
|
|
153
|
+
kind: 'grape.format',
|
|
154
154
|
started_at: event.time,
|
|
155
155
|
ended_at: event.end,
|
|
156
156
|
duration_ms: duration_ms,
|
|
157
|
-
data: { phase:
|
|
157
|
+
data: { phase: 'format' }
|
|
158
158
|
)
|
|
159
159
|
rescue StandardError => e
|
|
160
160
|
BrainzLab.debug_log("Grape format recording failed: #{e.message}")
|
|
@@ -177,14 +177,14 @@ module BrainzLab
|
|
|
177
177
|
end
|
|
178
178
|
|
|
179
179
|
def extract_route_pattern(endpoint)
|
|
180
|
-
return
|
|
180
|
+
return '/' unless endpoint
|
|
181
181
|
|
|
182
182
|
route = endpoint.route
|
|
183
|
-
return
|
|
183
|
+
return '/' unless route
|
|
184
184
|
|
|
185
|
-
route.pattern&.path || route.path ||
|
|
185
|
+
route.pattern&.path || route.path || '/'
|
|
186
186
|
rescue StandardError
|
|
187
|
-
|
|
187
|
+
'/'
|
|
188
188
|
end
|
|
189
189
|
end
|
|
190
190
|
|
|
@@ -243,14 +243,14 @@ module BrainzLab
|
|
|
243
243
|
path = request.path
|
|
244
244
|
|
|
245
245
|
# Get route pattern from Grape if available
|
|
246
|
-
route_pattern = env[
|
|
246
|
+
route_pattern = env['grape.routing_args']&.dig(:route_info)&.pattern&.path || path
|
|
247
247
|
|
|
248
248
|
spans = Thread.current[:brainzlab_pulse_spans] || []
|
|
249
249
|
|
|
250
250
|
payload = {
|
|
251
251
|
trace_id: SecureRandom.uuid,
|
|
252
252
|
name: "#{method} #{route_pattern}",
|
|
253
|
-
kind:
|
|
253
|
+
kind: 'request',
|
|
254
254
|
started_at: started_at.utc.iso8601(3),
|
|
255
255
|
ended_at: ended_at.utc.iso8601(3),
|
|
256
256
|
duration_ms: duration_ms,
|
|
@@ -13,14 +13,14 @@ module BrainzLab
|
|
|
13
13
|
# For GraphQL Ruby 2.0+
|
|
14
14
|
if ::GraphQL::Schema.respond_to?(:trace_with)
|
|
15
15
|
# Will be installed per-schema via BrainzLab::GraphQL::Tracer
|
|
16
|
-
BrainzLab.debug_log(
|
|
16
|
+
BrainzLab.debug_log('GraphQL tracer available - add `trace_with BrainzLab::Instrumentation::GraphQLInstrumentation::Tracer` to your schema')
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
# Subscribe to ActiveSupport notifications if available
|
|
20
20
|
install_notifications!
|
|
21
21
|
|
|
22
22
|
@installed = true
|
|
23
|
-
BrainzLab.debug_log(
|
|
23
|
+
BrainzLab.debug_log('GraphQL instrumentation installed')
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
def installed?
|
|
@@ -35,17 +35,17 @@ module BrainzLab
|
|
|
35
35
|
|
|
36
36
|
def install_notifications!
|
|
37
37
|
# GraphQL-ruby emits ActiveSupport notifications
|
|
38
|
-
ActiveSupport::Notifications.subscribe(
|
|
38
|
+
ActiveSupport::Notifications.subscribe('execute.graphql') do |*args|
|
|
39
39
|
event = ActiveSupport::Notifications::Event.new(*args)
|
|
40
40
|
record_execution(event)
|
|
41
41
|
end
|
|
42
42
|
|
|
43
|
-
ActiveSupport::Notifications.subscribe(
|
|
43
|
+
ActiveSupport::Notifications.subscribe('analyze.graphql') do |*args|
|
|
44
44
|
event = ActiveSupport::Notifications::Event.new(*args)
|
|
45
45
|
record_analyze(event)
|
|
46
46
|
end
|
|
47
47
|
|
|
48
|
-
ActiveSupport::Notifications.subscribe(
|
|
48
|
+
ActiveSupport::Notifications.subscribe('validate.graphql') do |*args|
|
|
49
49
|
event = ActiveSupport::Notifications::Event.new(*args)
|
|
50
50
|
record_validate(event)
|
|
51
51
|
end
|
|
@@ -56,15 +56,15 @@ module BrainzLab
|
|
|
56
56
|
def record_execution(event)
|
|
57
57
|
payload = event.payload
|
|
58
58
|
query = payload[:query]
|
|
59
|
-
operation_name = query&.operation_name ||
|
|
60
|
-
operation_type = query&.selected_operation&.operation_type ||
|
|
59
|
+
operation_name = query&.operation_name || 'anonymous'
|
|
60
|
+
operation_type = query&.selected_operation&.operation_type || 'query'
|
|
61
61
|
duration_ms = event.duration.round(2)
|
|
62
62
|
|
|
63
63
|
# Add breadcrumb
|
|
64
64
|
if BrainzLab.configuration.reflex_enabled
|
|
65
65
|
BrainzLab::Reflex.add_breadcrumb(
|
|
66
66
|
"GraphQL #{operation_type} #{operation_name}",
|
|
67
|
-
category:
|
|
67
|
+
category: 'graphql.execute',
|
|
68
68
|
level: payload[:errors]&.any? ? :error : :info,
|
|
69
69
|
data: {
|
|
70
70
|
operation_name: operation_name,
|
|
@@ -78,7 +78,7 @@ module BrainzLab
|
|
|
78
78
|
# Record span
|
|
79
79
|
record_span(
|
|
80
80
|
name: "GraphQL #{operation_type} #{operation_name}",
|
|
81
|
-
kind:
|
|
81
|
+
kind: 'graphql',
|
|
82
82
|
duration_ms: duration_ms,
|
|
83
83
|
started_at: event.time,
|
|
84
84
|
ended_at: event.end,
|
|
@@ -97,12 +97,12 @@ module BrainzLab
|
|
|
97
97
|
|
|
98
98
|
def record_analyze(event)
|
|
99
99
|
record_span(
|
|
100
|
-
name:
|
|
101
|
-
kind:
|
|
100
|
+
name: 'GraphQL analyze',
|
|
101
|
+
kind: 'graphql',
|
|
102
102
|
duration_ms: event.duration.round(2),
|
|
103
103
|
started_at: event.time,
|
|
104
104
|
ended_at: event.end,
|
|
105
|
-
data: { phase:
|
|
105
|
+
data: { phase: 'analyze' }
|
|
106
106
|
)
|
|
107
107
|
rescue StandardError => e
|
|
108
108
|
BrainzLab.debug_log("GraphQL analyze recording failed: #{e.message}")
|
|
@@ -110,12 +110,12 @@ module BrainzLab
|
|
|
110
110
|
|
|
111
111
|
def record_validate(event)
|
|
112
112
|
record_span(
|
|
113
|
-
name:
|
|
114
|
-
kind:
|
|
113
|
+
name: 'GraphQL validate',
|
|
114
|
+
kind: 'graphql',
|
|
115
115
|
duration_ms: event.duration.round(2),
|
|
116
116
|
started_at: event.time,
|
|
117
117
|
ended_at: event.end,
|
|
118
|
-
data: { phase:
|
|
118
|
+
data: { phase: 'validate' }
|
|
119
119
|
)
|
|
120
120
|
rescue StandardError => e
|
|
121
121
|
BrainzLab.debug_log("GraphQL validate recording failed: #{e.message}")
|
|
@@ -139,6 +139,7 @@ module BrainzLab
|
|
|
139
139
|
|
|
140
140
|
def truncate_query(query)
|
|
141
141
|
return nil unless query
|
|
142
|
+
|
|
142
143
|
query.to_s[0, 2000]
|
|
143
144
|
end
|
|
144
145
|
|
|
@@ -148,7 +149,7 @@ module BrainzLab
|
|
|
148
149
|
scrub_fields = BrainzLab.configuration.scrub_fields
|
|
149
150
|
variables.transform_values do |value|
|
|
150
151
|
if scrub_fields.any? { |f| value.to_s.downcase.include?(f.to_s) }
|
|
151
|
-
|
|
152
|
+
'[FILTERED]'
|
|
152
153
|
else
|
|
153
154
|
value
|
|
154
155
|
end
|
|
@@ -163,19 +164,19 @@ module BrainzLab
|
|
|
163
164
|
module Tracer
|
|
164
165
|
def execute_query(query:)
|
|
165
166
|
started_at = Time.now.utc
|
|
166
|
-
operation_name = query.operation_name ||
|
|
167
|
-
operation_type = query.selected_operation&.operation_type ||
|
|
167
|
+
operation_name = query.operation_name || 'anonymous'
|
|
168
|
+
operation_type = query.selected_operation&.operation_type || 'query'
|
|
168
169
|
|
|
169
170
|
result = super
|
|
170
171
|
|
|
171
172
|
duration_ms = ((Time.now.utc - started_at) * 1000).round(2)
|
|
172
|
-
has_errors = result.to_h[
|
|
173
|
+
has_errors = result.to_h['errors']&.any?
|
|
173
174
|
|
|
174
175
|
# Add breadcrumb
|
|
175
176
|
if BrainzLab.configuration.reflex_enabled
|
|
176
177
|
BrainzLab::Reflex.add_breadcrumb(
|
|
177
178
|
"GraphQL #{operation_type} #{operation_name}",
|
|
178
|
-
category:
|
|
179
|
+
category: 'graphql.execute',
|
|
179
180
|
level: has_errors ? :error : :info,
|
|
180
181
|
data: {
|
|
181
182
|
operation_name: operation_name,
|
|
@@ -191,7 +192,7 @@ module BrainzLab
|
|
|
191
192
|
spans << {
|
|
192
193
|
span_id: SecureRandom.uuid,
|
|
193
194
|
name: "GraphQL #{operation_type} #{operation_name}",
|
|
194
|
-
kind:
|
|
195
|
+
kind: 'graphql',
|
|
195
196
|
started_at: started_at,
|
|
196
197
|
ended_at: Time.now.utc,
|
|
197
198
|
duration_ms: duration_ms,
|
|
@@ -209,7 +210,7 @@ module BrainzLab
|
|
|
209
210
|
if BrainzLab.configuration.reflex_enabled
|
|
210
211
|
BrainzLab::Reflex.add_breadcrumb(
|
|
211
212
|
"GraphQL #{operation_type} #{operation_name} failed",
|
|
212
|
-
category:
|
|
213
|
+
category: 'graphql.error',
|
|
213
214
|
level: :error,
|
|
214
215
|
data: { error: e.class.name }
|
|
215
216
|
)
|
|
@@ -231,7 +232,7 @@ module BrainzLab
|
|
|
231
232
|
spans << {
|
|
232
233
|
span_id: SecureRandom.uuid,
|
|
233
234
|
name: "GraphQL field #{field.owner.graphql_name}.#{field.graphql_name}",
|
|
234
|
-
kind:
|
|
235
|
+
kind: 'graphql.field',
|
|
235
236
|
started_at: started_at,
|
|
236
237
|
ended_at: Time.now.utc,
|
|
237
238
|
duration_ms: duration_ms,
|
|
@@ -13,7 +13,7 @@ module BrainzLab
|
|
|
13
13
|
::HTTParty.singleton_class.prepend(Patch)
|
|
14
14
|
|
|
15
15
|
@installed = true
|
|
16
|
-
BrainzLab.debug_log(
|
|
16
|
+
BrainzLab.debug_log('HTTParty instrumentation installed')
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
def installed?
|
|
@@ -26,14 +26,13 @@ module BrainzLab
|
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
module Patch
|
|
29
|
-
def perform_request(http_method, path, options = {}, &
|
|
29
|
+
def perform_request(http_method, path, options = {}, &)
|
|
30
30
|
return super unless should_track?(path, options)
|
|
31
31
|
|
|
32
32
|
# Inject distributed tracing headers
|
|
33
33
|
options = inject_trace_context(options)
|
|
34
34
|
|
|
35
35
|
started_at = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
36
|
-
error_info = nil
|
|
37
36
|
|
|
38
37
|
begin
|
|
39
38
|
response = super
|
|
@@ -79,7 +78,7 @@ module BrainzLab
|
|
|
79
78
|
method = extract_method_name(http_method)
|
|
80
79
|
uri = parse_uri(path, options)
|
|
81
80
|
url = uri ? sanitize_url(uri) : path.to_s
|
|
82
|
-
host = uri&.host ||
|
|
81
|
+
host = uri&.host || 'unknown'
|
|
83
82
|
request_path = uri&.path || path.to_s
|
|
84
83
|
level = error || (status && status >= 400) ? :error : :info
|
|
85
84
|
|
|
@@ -87,7 +86,7 @@ module BrainzLab
|
|
|
87
86
|
if BrainzLab.configuration.reflex_enabled
|
|
88
87
|
BrainzLab::Reflex.add_breadcrumb(
|
|
89
88
|
"#{method} #{url}",
|
|
90
|
-
category:
|
|
89
|
+
category: 'http.httparty',
|
|
91
90
|
level: level,
|
|
92
91
|
data: {
|
|
93
92
|
method: method,
|
|
@@ -127,7 +126,7 @@ module BrainzLab
|
|
|
127
126
|
span = {
|
|
128
127
|
span_id: SecureRandom.uuid,
|
|
129
128
|
name: "HTTP #{method} #{host}",
|
|
130
|
-
kind:
|
|
129
|
+
kind: 'http',
|
|
131
130
|
started_at: Time.now.utc - (duration_ms / 1000.0),
|
|
132
131
|
ended_at: Time.now.utc,
|
|
133
132
|
duration_ms: duration_ms,
|
|
@@ -149,14 +148,14 @@ module BrainzLab
|
|
|
149
148
|
|
|
150
149
|
def extract_method_name(http_method)
|
|
151
150
|
case http_method.name
|
|
152
|
-
when /Get$/ then
|
|
153
|
-
when /Post$/ then
|
|
154
|
-
when /Put$/ then
|
|
155
|
-
when /Patch$/ then
|
|
156
|
-
when /Delete$/ then
|
|
157
|
-
when /Head$/ then
|
|
158
|
-
when /Options$/ then
|
|
159
|
-
else http_method.name.split(
|
|
151
|
+
when /Get$/ then 'GET'
|
|
152
|
+
when /Post$/ then 'POST'
|
|
153
|
+
when /Put$/ then 'PUT'
|
|
154
|
+
when /Patch$/ then 'PATCH'
|
|
155
|
+
when /Delete$/ then 'DELETE'
|
|
156
|
+
when /Head$/ then 'HEAD'
|
|
157
|
+
when /Options$/ then 'OPTIONS'
|
|
158
|
+
else http_method.name.split('::').last.upcase
|
|
160
159
|
end
|
|
161
160
|
end
|
|
162
161
|
|
|
@@ -26,7 +26,7 @@ module BrainzLab
|
|
|
26
26
|
return unless installed_any
|
|
27
27
|
|
|
28
28
|
@installed = true
|
|
29
|
-
BrainzLab.debug_log(
|
|
29
|
+
BrainzLab.debug_log('MongoDB instrumentation installed')
|
|
30
30
|
end
|
|
31
31
|
|
|
32
32
|
def installed?
|
|
@@ -51,9 +51,9 @@ module BrainzLab
|
|
|
51
51
|
|
|
52
52
|
def install_mongoid!
|
|
53
53
|
# For Mongoid 7+, use the APM module
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
54
|
+
return unless ::Mongoid.respond_to?(:subscribe)
|
|
55
|
+
|
|
56
|
+
::Mongoid.subscribe(CommandSubscriber.new)
|
|
57
57
|
end
|
|
58
58
|
end
|
|
59
59
|
|
|
@@ -96,7 +96,7 @@ module BrainzLab
|
|
|
96
96
|
def extract_collection(event)
|
|
97
97
|
# Try to extract collection name from command
|
|
98
98
|
cmd = event.command
|
|
99
|
-
cmd[
|
|
99
|
+
cmd['collection'] || cmd[event.command_name] || cmd.keys.first
|
|
100
100
|
rescue StandardError
|
|
101
101
|
nil
|
|
102
102
|
end
|
|
@@ -116,7 +116,7 @@ module BrainzLab
|
|
|
116
116
|
if BrainzLab.configuration.reflex_enabled
|
|
117
117
|
BrainzLab::Reflex.add_breadcrumb(
|
|
118
118
|
"MongoDB #{command_name}",
|
|
119
|
-
category:
|
|
119
|
+
category: 'mongodb',
|
|
120
120
|
level: level,
|
|
121
121
|
data: {
|
|
122
122
|
command: command_name,
|
|
@@ -163,7 +163,7 @@ module BrainzLab
|
|
|
163
163
|
span = {
|
|
164
164
|
span_id: SecureRandom.uuid,
|
|
165
165
|
name: "MongoDB #{command_name} #{collection}".strip,
|
|
166
|
-
kind:
|
|
166
|
+
kind: 'mongodb',
|
|
167
167
|
started_at: started_at,
|
|
168
168
|
ended_at: Time.now.utc,
|
|
169
169
|
duration_ms: duration_ms.round(2),
|
|
@@ -24,7 +24,7 @@ module BrainzLab
|
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
module Patch
|
|
27
|
-
def request(req, body = nil, &
|
|
27
|
+
def request(req, body = nil, &)
|
|
28
28
|
return super unless should_track?
|
|
29
29
|
|
|
30
30
|
# Inject distributed tracing context into outgoing request headers
|
|
@@ -38,7 +38,7 @@ module BrainzLab
|
|
|
38
38
|
response = super
|
|
39
39
|
track_request(method, url, response.code.to_i, started_at)
|
|
40
40
|
response
|
|
41
|
-
rescue => e
|
|
41
|
+
rescue StandardError => e
|
|
42
42
|
track_request(method, url, nil, started_at, e.class.name)
|
|
43
43
|
raise
|
|
44
44
|
end
|
|
@@ -69,9 +69,9 @@ module BrainzLab
|
|
|
69
69
|
end
|
|
70
70
|
|
|
71
71
|
def build_url(req)
|
|
72
|
-
scheme = use_ssl? ?
|
|
72
|
+
scheme = use_ssl? ? 'https' : 'http'
|
|
73
73
|
port_str = if (use_ssl? && port == 443) || (!use_ssl? && port == 80)
|
|
74
|
-
|
|
74
|
+
''
|
|
75
75
|
else
|
|
76
76
|
":#{port}"
|
|
77
77
|
end
|
|
@@ -86,7 +86,7 @@ module BrainzLab
|
|
|
86
86
|
if BrainzLab.configuration.reflex_enabled
|
|
87
87
|
BrainzLab::Reflex.add_breadcrumb(
|
|
88
88
|
"#{method} #{url}",
|
|
89
|
-
category:
|
|
89
|
+
category: 'http',
|
|
90
90
|
level: level,
|
|
91
91
|
data: { method: method, url: url, status_code: status, duration_ms: duration_ms, error: error }.compact
|
|
92
92
|
)
|
|
@@ -99,7 +99,7 @@ module BrainzLab
|
|
|
99
99
|
method: method, url: url, status_code: status, duration_ms: duration_ms, error: error
|
|
100
100
|
)
|
|
101
101
|
end
|
|
102
|
-
rescue => e
|
|
102
|
+
rescue StandardError => e
|
|
103
103
|
# Don't let instrumentation errors crash the app
|
|
104
104
|
BrainzLab.configuration.logger&.error("[BrainzLab] HTTP instrumentation error: #{e.message}")
|
|
105
105
|
end
|