brainzlab 0.1.2 → 0.1.3
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 +92 -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_mailer.rb +14 -13
- data/lib/brainzlab/instrumentation/active_record.rb +13 -15
- 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/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 +20 -20
- 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 +1 -1
|
@@ -22,14 +22,14 @@ module BrainzLab
|
|
|
22
22
|
def install_active_record!
|
|
23
23
|
return unless defined?(ActiveRecord)
|
|
24
24
|
|
|
25
|
-
ActiveSupport::Notifications.subscribe(
|
|
25
|
+
ActiveSupport::Notifications.subscribe('sql.active_record') do |*args|
|
|
26
26
|
event = ActiveSupport::Notifications::Event.new(*args)
|
|
27
27
|
next if skip_query?(event.payload)
|
|
28
28
|
|
|
29
29
|
sql = event.payload[:sql]
|
|
30
30
|
record_span(
|
|
31
|
-
name: event.payload[:name] ||
|
|
32
|
-
kind:
|
|
31
|
+
name: event.payload[:name] || 'SQL',
|
|
32
|
+
kind: 'db',
|
|
33
33
|
started_at: event.time,
|
|
34
34
|
ended_at: event.end,
|
|
35
35
|
duration_ms: event.duration,
|
|
@@ -48,12 +48,12 @@ module BrainzLab
|
|
|
48
48
|
def install_action_view!
|
|
49
49
|
return unless defined?(ActionView)
|
|
50
50
|
|
|
51
|
-
ActiveSupport::Notifications.subscribe(
|
|
51
|
+
ActiveSupport::Notifications.subscribe('render_template.action_view') do |*args|
|
|
52
52
|
event = ActiveSupport::Notifications::Event.new(*args)
|
|
53
53
|
|
|
54
54
|
record_span(
|
|
55
55
|
name: short_path(event.payload[:identifier]),
|
|
56
|
-
kind:
|
|
56
|
+
kind: 'render',
|
|
57
57
|
started_at: event.time,
|
|
58
58
|
ended_at: event.end,
|
|
59
59
|
duration_ms: event.duration,
|
|
@@ -64,12 +64,12 @@ module BrainzLab
|
|
|
64
64
|
)
|
|
65
65
|
end
|
|
66
66
|
|
|
67
|
-
ActiveSupport::Notifications.subscribe(
|
|
67
|
+
ActiveSupport::Notifications.subscribe('render_partial.action_view') do |*args|
|
|
68
68
|
event = ActiveSupport::Notifications::Event.new(*args)
|
|
69
69
|
|
|
70
70
|
record_span(
|
|
71
71
|
name: short_path(event.payload[:identifier]),
|
|
72
|
-
kind:
|
|
72
|
+
kind: 'render',
|
|
73
73
|
started_at: event.time,
|
|
74
74
|
ended_at: event.end,
|
|
75
75
|
duration_ms: event.duration,
|
|
@@ -80,12 +80,12 @@ module BrainzLab
|
|
|
80
80
|
)
|
|
81
81
|
end
|
|
82
82
|
|
|
83
|
-
ActiveSupport::Notifications.subscribe(
|
|
83
|
+
ActiveSupport::Notifications.subscribe('render_collection.action_view') do |*args|
|
|
84
84
|
event = ActiveSupport::Notifications::Event.new(*args)
|
|
85
85
|
|
|
86
86
|
record_span(
|
|
87
87
|
name: short_path(event.payload[:identifier]),
|
|
88
|
-
kind:
|
|
88
|
+
kind: 'render',
|
|
89
89
|
started_at: event.time,
|
|
90
90
|
ended_at: event.end,
|
|
91
91
|
duration_ms: event.duration,
|
|
@@ -103,11 +103,11 @@ module BrainzLab
|
|
|
103
103
|
%w[cache_read.active_support cache_write.active_support cache_delete.active_support].each do |event_name|
|
|
104
104
|
ActiveSupport::Notifications.subscribe(event_name) do |*args|
|
|
105
105
|
event = ActiveSupport::Notifications::Event.new(*args)
|
|
106
|
-
operation = event_name.split(
|
|
106
|
+
operation = event_name.split('.').first.sub('cache_', '')
|
|
107
107
|
|
|
108
108
|
record_span(
|
|
109
109
|
name: "Cache #{operation}",
|
|
110
|
-
kind:
|
|
110
|
+
kind: 'cache',
|
|
111
111
|
started_at: event.time,
|
|
112
112
|
ended_at: event.end,
|
|
113
113
|
duration_ms: event.duration,
|
|
@@ -125,7 +125,7 @@ module BrainzLab
|
|
|
125
125
|
def install_action_controller!
|
|
126
126
|
return unless defined?(ActionController)
|
|
127
127
|
|
|
128
|
-
ActiveSupport::Notifications.subscribe(
|
|
128
|
+
ActiveSupport::Notifications.subscribe('process_action.action_controller') do |*args|
|
|
129
129
|
event = ActiveSupport::Notifications::Event.new(*args)
|
|
130
130
|
payload = event.payload
|
|
131
131
|
|
|
@@ -141,12 +141,12 @@ module BrainzLab
|
|
|
141
141
|
def install_http_clients!
|
|
142
142
|
# Net::HTTP instrumentation
|
|
143
143
|
if defined?(Net::HTTP)
|
|
144
|
-
ActiveSupport::Notifications.subscribe(
|
|
144
|
+
ActiveSupport::Notifications.subscribe('request.net_http') do |*args|
|
|
145
145
|
event = ActiveSupport::Notifications::Event.new(*args)
|
|
146
146
|
|
|
147
147
|
record_span(
|
|
148
148
|
name: "HTTP #{event.payload[:method]} #{event.payload[:host]}",
|
|
149
|
-
kind:
|
|
149
|
+
kind: 'http',
|
|
150
150
|
started_at: event.time,
|
|
151
151
|
ended_at: event.end,
|
|
152
152
|
duration_ms: event.duration,
|
|
@@ -161,26 +161,26 @@ module BrainzLab
|
|
|
161
161
|
end
|
|
162
162
|
|
|
163
163
|
# Faraday instrumentation
|
|
164
|
-
|
|
165
|
-
ActiveSupport::Notifications.subscribe("request.faraday") do |*args|
|
|
166
|
-
event = ActiveSupport::Notifications::Event.new(*args)
|
|
167
|
-
env = event.payload[:env]
|
|
168
|
-
next unless env
|
|
164
|
+
return unless defined?(Faraday)
|
|
169
165
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
166
|
+
ActiveSupport::Notifications.subscribe('request.faraday') do |*args|
|
|
167
|
+
event = ActiveSupport::Notifications::Event.new(*args)
|
|
168
|
+
env = event.payload[:env]
|
|
169
|
+
next unless env
|
|
170
|
+
|
|
171
|
+
record_span(
|
|
172
|
+
name: "HTTP #{env.method.to_s.upcase} #{env.url.host}",
|
|
173
|
+
kind: 'http',
|
|
174
|
+
started_at: event.time,
|
|
175
|
+
ended_at: event.end,
|
|
176
|
+
duration_ms: event.duration,
|
|
177
|
+
data: {
|
|
178
|
+
method: env.method.to_s.upcase,
|
|
179
|
+
host: env.url.host,
|
|
180
|
+
path: env.url.path,
|
|
181
|
+
status: env.status
|
|
182
|
+
}
|
|
183
|
+
)
|
|
184
184
|
end
|
|
185
185
|
end
|
|
186
186
|
|
|
@@ -189,13 +189,13 @@ module BrainzLab
|
|
|
189
189
|
return unless defined?(ActiveJob)
|
|
190
190
|
|
|
191
191
|
# Track job enqueuing
|
|
192
|
-
ActiveSupport::Notifications.subscribe(
|
|
192
|
+
ActiveSupport::Notifications.subscribe('enqueue.active_job') do |*args|
|
|
193
193
|
event = ActiveSupport::Notifications::Event.new(*args)
|
|
194
194
|
job = event.payload[:job]
|
|
195
195
|
|
|
196
196
|
record_span(
|
|
197
197
|
name: "Enqueue #{job.class.name}",
|
|
198
|
-
kind:
|
|
198
|
+
kind: 'job',
|
|
199
199
|
started_at: event.time,
|
|
200
200
|
ended_at: event.end,
|
|
201
201
|
duration_ms: event.duration,
|
|
@@ -208,14 +208,14 @@ module BrainzLab
|
|
|
208
208
|
end
|
|
209
209
|
|
|
210
210
|
# Track job retry
|
|
211
|
-
ActiveSupport::Notifications.subscribe(
|
|
211
|
+
ActiveSupport::Notifications.subscribe('retry_stopped.active_job') do |*args|
|
|
212
212
|
event = ActiveSupport::Notifications::Event.new(*args)
|
|
213
213
|
job = event.payload[:job]
|
|
214
214
|
error = event.payload[:error]
|
|
215
215
|
|
|
216
216
|
record_span(
|
|
217
217
|
name: "Retry stopped #{job.class.name}",
|
|
218
|
-
kind:
|
|
218
|
+
kind: 'job',
|
|
219
219
|
started_at: event.time,
|
|
220
220
|
ended_at: event.end,
|
|
221
221
|
duration_ms: event.duration,
|
|
@@ -232,14 +232,14 @@ module BrainzLab
|
|
|
232
232
|
end
|
|
233
233
|
|
|
234
234
|
# Track job discard
|
|
235
|
-
ActiveSupport::Notifications.subscribe(
|
|
235
|
+
ActiveSupport::Notifications.subscribe('discard.active_job') do |*args|
|
|
236
236
|
event = ActiveSupport::Notifications::Event.new(*args)
|
|
237
237
|
job = event.payload[:job]
|
|
238
238
|
error = event.payload[:error]
|
|
239
239
|
|
|
240
240
|
record_span(
|
|
241
241
|
name: "Discarded #{job.class.name}",
|
|
242
|
-
kind:
|
|
242
|
+
kind: 'job',
|
|
243
243
|
started_at: event.time,
|
|
244
244
|
ended_at: event.end,
|
|
245
245
|
duration_ms: event.duration,
|
|
@@ -260,12 +260,12 @@ module BrainzLab
|
|
|
260
260
|
def install_action_cable!
|
|
261
261
|
return unless defined?(ActionCable)
|
|
262
262
|
|
|
263
|
-
ActiveSupport::Notifications.subscribe(
|
|
263
|
+
ActiveSupport::Notifications.subscribe('perform_action.action_cable') do |*args|
|
|
264
264
|
event = ActiveSupport::Notifications::Event.new(*args)
|
|
265
265
|
|
|
266
266
|
record_span(
|
|
267
267
|
name: "Cable #{event.payload[:channel_class]}##{event.payload[:action]}",
|
|
268
|
-
kind:
|
|
268
|
+
kind: 'cable',
|
|
269
269
|
started_at: event.time,
|
|
270
270
|
ended_at: event.end,
|
|
271
271
|
duration_ms: event.duration,
|
|
@@ -276,12 +276,12 @@ module BrainzLab
|
|
|
276
276
|
)
|
|
277
277
|
end
|
|
278
278
|
|
|
279
|
-
ActiveSupport::Notifications.subscribe(
|
|
279
|
+
ActiveSupport::Notifications.subscribe('transmit.action_cable') do |*args|
|
|
280
280
|
event = ActiveSupport::Notifications::Event.new(*args)
|
|
281
281
|
|
|
282
282
|
record_span(
|
|
283
283
|
name: "Cable transmit #{event.payload[:channel_class]}",
|
|
284
|
-
kind:
|
|
284
|
+
kind: 'cable',
|
|
285
285
|
started_at: event.time,
|
|
286
286
|
ended_at: event.end,
|
|
287
287
|
duration_ms: event.duration,
|
|
@@ -292,12 +292,12 @@ module BrainzLab
|
|
|
292
292
|
)
|
|
293
293
|
end
|
|
294
294
|
|
|
295
|
-
ActiveSupport::Notifications.subscribe(
|
|
295
|
+
ActiveSupport::Notifications.subscribe('broadcast.action_cable') do |*args|
|
|
296
296
|
event = ActiveSupport::Notifications::Event.new(*args)
|
|
297
297
|
|
|
298
298
|
record_span(
|
|
299
299
|
name: "Cable broadcast #{event.payload[:broadcasting]}",
|
|
300
|
-
kind:
|
|
300
|
+
kind: 'cable',
|
|
301
301
|
started_at: event.time,
|
|
302
302
|
ended_at: event.end,
|
|
303
303
|
duration_ms: event.duration,
|
|
@@ -309,7 +309,8 @@ module BrainzLab
|
|
|
309
309
|
end
|
|
310
310
|
end
|
|
311
311
|
|
|
312
|
-
def record_span(name:, kind:, started_at:, ended_at:, duration_ms:, error: false, error_class: nil,
|
|
312
|
+
def record_span(name:, kind:, started_at:, ended_at:, duration_ms:, error: false, error_class: nil,
|
|
313
|
+
error_message: nil, data: {})
|
|
313
314
|
spans = Thread.current[:brainzlab_pulse_spans]
|
|
314
315
|
return unless spans
|
|
315
316
|
|
|
@@ -334,10 +335,10 @@ module BrainzLab
|
|
|
334
335
|
|
|
335
336
|
def skip_query?(payload)
|
|
336
337
|
# Skip SCHEMA queries and internal Rails queries
|
|
337
|
-
return true if payload[:name] ==
|
|
338
|
-
return true if payload[:name]&.start_with?(
|
|
339
|
-
return true if payload[:sql]&.include?(
|
|
340
|
-
return true if payload[:sql]&.include?(
|
|
338
|
+
return true if payload[:name] == 'SCHEMA'
|
|
339
|
+
return true if payload[:name]&.start_with?('EXPLAIN')
|
|
340
|
+
return true if payload[:sql]&.include?('pg_')
|
|
341
|
+
return true if payload[:sql]&.include?('information_schema')
|
|
341
342
|
return true if payload[:cached] && !include_cached_queries?
|
|
342
343
|
|
|
343
344
|
false
|
|
@@ -349,17 +350,20 @@ module BrainzLab
|
|
|
349
350
|
|
|
350
351
|
def truncate_sql(sql)
|
|
351
352
|
return nil unless sql
|
|
353
|
+
|
|
352
354
|
sql.to_s[0, 1000]
|
|
353
355
|
end
|
|
354
356
|
|
|
355
357
|
def truncate_key(key)
|
|
356
358
|
return nil unless key
|
|
359
|
+
|
|
357
360
|
key.to_s[0, 200]
|
|
358
361
|
end
|
|
359
362
|
|
|
360
363
|
def short_path(path)
|
|
361
364
|
return nil unless path
|
|
362
|
-
|
|
365
|
+
|
|
366
|
+
path.to_s.split('/').last(2).join('/')
|
|
363
367
|
end
|
|
364
368
|
|
|
365
369
|
def extract_table(sql)
|
|
@@ -383,12 +387,12 @@ module BrainzLab
|
|
|
383
387
|
return nil unless sql
|
|
384
388
|
|
|
385
389
|
case sql.to_s.strip.upcase
|
|
386
|
-
when /\ASELECT/i then
|
|
387
|
-
when /\AINSERT/i then
|
|
388
|
-
when /\AUPDATE/i then
|
|
389
|
-
when /\ADELETE/i then
|
|
390
|
-
when /\ABEGIN/i, /\ACOMMIT/i, /\AROLLBACK/i then
|
|
391
|
-
else
|
|
390
|
+
when /\ASELECT/i then 'SELECT'
|
|
391
|
+
when /\AINSERT/i then 'INSERT'
|
|
392
|
+
when /\AUPDATE/i then 'UPDATE'
|
|
393
|
+
when /\ADELETE/i then 'DELETE'
|
|
394
|
+
when /\ABEGIN/i, /\ACOMMIT/i, /\AROLLBACK/i then 'TRANSACTION'
|
|
395
|
+
else 'QUERY'
|
|
392
396
|
end
|
|
393
397
|
end
|
|
394
398
|
end
|
|
@@ -6,18 +6,18 @@ module BrainzLab
|
|
|
6
6
|
# https://www.w3.org/TR/trace-context/
|
|
7
7
|
module Propagation
|
|
8
8
|
# W3C Trace Context header names
|
|
9
|
-
TRACEPARENT_HEADER =
|
|
10
|
-
TRACESTATE_HEADER =
|
|
9
|
+
TRACEPARENT_HEADER = 'traceparent'
|
|
10
|
+
TRACESTATE_HEADER = 'tracestate'
|
|
11
11
|
|
|
12
12
|
# HTTP header versions (with HTTP_ prefix for Rack env)
|
|
13
|
-
HTTP_TRACEPARENT =
|
|
14
|
-
HTTP_TRACESTATE =
|
|
13
|
+
HTTP_TRACEPARENT = 'HTTP_TRACEPARENT'
|
|
14
|
+
HTTP_TRACESTATE = 'HTTP_TRACESTATE'
|
|
15
15
|
|
|
16
16
|
# Also support B3 format for compatibility
|
|
17
|
-
B3_TRACE_ID =
|
|
18
|
-
B3_SPAN_ID =
|
|
19
|
-
B3_SAMPLED =
|
|
20
|
-
B3_PARENT_SPAN_ID =
|
|
17
|
+
B3_TRACE_ID = 'X-B3-TraceId'
|
|
18
|
+
B3_SPAN_ID = 'X-B3-SpanId'
|
|
19
|
+
B3_SAMPLED = 'X-B3-Sampled'
|
|
20
|
+
B3_PARENT_SPAN_ID = 'X-B3-ParentSpanId'
|
|
21
21
|
|
|
22
22
|
class Context
|
|
23
23
|
attr_accessor :trace_id, :span_id, :parent_span_id, :sampled, :tracestate
|
|
@@ -137,8 +137,8 @@ module BrainzLab
|
|
|
137
137
|
# traceparent: version-traceid-spanid-flags
|
|
138
138
|
# Example: 00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01
|
|
139
139
|
def inject_w3c(headers, ctx)
|
|
140
|
-
version =
|
|
141
|
-
flags = ctx.sampled ?
|
|
140
|
+
version = '00'
|
|
141
|
+
flags = ctx.sampled ? '01' : '00'
|
|
142
142
|
trace_id = normalize_trace_id(ctx.trace_id, 32)
|
|
143
143
|
span_id = normalize_trace_id(ctx.span_id, 16)
|
|
144
144
|
|
|
@@ -152,31 +152,31 @@ module BrainzLab
|
|
|
152
152
|
def extract_w3c(headers)
|
|
153
153
|
traceparent = headers[TRACEPARENT_HEADER] ||
|
|
154
154
|
headers[HTTP_TRACEPARENT] ||
|
|
155
|
-
headers[
|
|
155
|
+
headers['Traceparent']
|
|
156
156
|
return nil unless traceparent
|
|
157
157
|
|
|
158
158
|
# Parse: version-traceid-spanid-flags
|
|
159
|
-
parts = traceparent.to_s.split(
|
|
159
|
+
parts = traceparent.to_s.split('-')
|
|
160
160
|
return nil if parts.length < 4
|
|
161
161
|
|
|
162
162
|
version, trace_id, span_id, flags = parts
|
|
163
163
|
|
|
164
164
|
# Validate version
|
|
165
|
-
return nil unless version ==
|
|
165
|
+
return nil unless version == '00'
|
|
166
166
|
|
|
167
167
|
# Validate trace_id (32 hex chars, not all zeros)
|
|
168
168
|
return nil unless trace_id&.match?(/\A[a-f0-9]{32}\z/i)
|
|
169
|
-
return nil if trace_id ==
|
|
169
|
+
return nil if trace_id == '0' * 32
|
|
170
170
|
|
|
171
171
|
# Validate span_id (16 hex chars, not all zeros)
|
|
172
172
|
return nil unless span_id&.match?(/\A[a-f0-9]{16}\z/i)
|
|
173
|
-
return nil if span_id ==
|
|
173
|
+
return nil if span_id == '0' * 16
|
|
174
174
|
|
|
175
175
|
sampled = flags.to_i(16) & 0x01 == 1
|
|
176
176
|
|
|
177
177
|
tracestate = headers[TRACESTATE_HEADER] ||
|
|
178
178
|
headers[HTTP_TRACESTATE] ||
|
|
179
|
-
headers[
|
|
179
|
+
headers['Tracestate']
|
|
180
180
|
|
|
181
181
|
Context.new(
|
|
182
182
|
trace_id: trace_id,
|
|
@@ -192,7 +192,7 @@ module BrainzLab
|
|
|
192
192
|
def inject_b3(headers, ctx)
|
|
193
193
|
headers[B3_TRACE_ID] = normalize_trace_id(ctx.trace_id, 32)
|
|
194
194
|
headers[B3_SPAN_ID] = normalize_trace_id(ctx.span_id, 16)
|
|
195
|
-
headers[B3_SAMPLED] = ctx.sampled ?
|
|
195
|
+
headers[B3_SAMPLED] = ctx.sampled ? '1' : '0'
|
|
196
196
|
headers[B3_PARENT_SPAN_ID] = ctx.parent_span_id if ctx.parent_span_id
|
|
197
197
|
|
|
198
198
|
headers
|
|
@@ -201,23 +201,23 @@ module BrainzLab
|
|
|
201
201
|
# B3 format extraction
|
|
202
202
|
def extract_b3(headers)
|
|
203
203
|
trace_id = headers[B3_TRACE_ID] ||
|
|
204
|
-
headers[
|
|
205
|
-
headers[
|
|
204
|
+
headers['HTTP_X_B3_TRACEID'] ||
|
|
205
|
+
headers['x-b3-traceid']
|
|
206
206
|
return nil unless trace_id
|
|
207
207
|
|
|
208
208
|
span_id = headers[B3_SPAN_ID] ||
|
|
209
|
-
headers[
|
|
210
|
-
headers[
|
|
209
|
+
headers['HTTP_X_B3_SPANID'] ||
|
|
210
|
+
headers['x-b3-spanid']
|
|
211
211
|
return nil unless span_id
|
|
212
212
|
|
|
213
213
|
sampled_header = headers[B3_SAMPLED] ||
|
|
214
|
-
headers[
|
|
215
|
-
headers[
|
|
216
|
-
sampled = sampled_header !=
|
|
214
|
+
headers['HTTP_X_B3_SAMPLED'] ||
|
|
215
|
+
headers['x-b3-sampled']
|
|
216
|
+
sampled = sampled_header != '0'
|
|
217
217
|
|
|
218
218
|
parent_span_id = headers[B3_PARENT_SPAN_ID] ||
|
|
219
|
-
headers[
|
|
220
|
-
headers[
|
|
219
|
+
headers['HTTP_X_B3_PARENTSPANID'] ||
|
|
220
|
+
headers['x-b3-parentspanid']
|
|
221
221
|
|
|
222
222
|
Context.new(
|
|
223
223
|
trace_id: trace_id,
|
|
@@ -232,8 +232,8 @@ module BrainzLab
|
|
|
232
232
|
def normalize_trace_id(id, length)
|
|
233
233
|
return nil unless id
|
|
234
234
|
|
|
235
|
-
hex = id.to_s.gsub(
|
|
236
|
-
hex.rjust(length,
|
|
235
|
+
hex = id.to_s.gsub('-', '').downcase
|
|
236
|
+
hex.rjust(length, '0').slice(0, length)
|
|
237
237
|
end
|
|
238
238
|
end
|
|
239
239
|
end
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
4
|
-
require
|
|
5
|
-
require
|
|
6
|
-
require
|
|
3
|
+
require 'net/http'
|
|
4
|
+
require 'uri'
|
|
5
|
+
require 'json'
|
|
6
|
+
require 'fileutils'
|
|
7
7
|
|
|
8
8
|
module BrainzLab
|
|
9
9
|
module Pulse
|
|
10
10
|
class Provisioner
|
|
11
|
-
CACHE_DIR = ENV.fetch(
|
|
11
|
+
CACHE_DIR = ENV.fetch('BRAINZLAB_CACHE_DIR') { File.join(Dir.home, '.brainzlab') }
|
|
12
12
|
|
|
13
13
|
def initialize(config)
|
|
14
14
|
@config = config
|
|
@@ -38,10 +38,10 @@ module BrainzLab
|
|
|
38
38
|
|
|
39
39
|
def should_provision?
|
|
40
40
|
return false unless @config.pulse_auto_provision
|
|
41
|
-
return false unless @config.app_name.to_s.strip.length
|
|
41
|
+
return false unless @config.app_name.to_s.strip.length.positive?
|
|
42
42
|
# Only skip if pulse_api_key is already set
|
|
43
|
-
return false if @config.pulse_api_key.to_s.strip.length
|
|
44
|
-
return false unless @config.pulse_master_key.to_s.strip.length
|
|
43
|
+
return false if @config.pulse_api_key.to_s.strip.length.positive?
|
|
44
|
+
return false unless @config.pulse_master_key.to_s.strip.length.positive?
|
|
45
45
|
|
|
46
46
|
true
|
|
47
47
|
end
|
|
@@ -49,9 +49,9 @@ module BrainzLab
|
|
|
49
49
|
def provision_project
|
|
50
50
|
uri = URI.parse("#{@config.pulse_url}/api/v1/projects/provision")
|
|
51
51
|
request = Net::HTTP::Post.new(uri)
|
|
52
|
-
request[
|
|
53
|
-
request[
|
|
54
|
-
request[
|
|
52
|
+
request['Content-Type'] = 'application/json'
|
|
53
|
+
request['X-Master-Key'] = @config.pulse_master_key
|
|
54
|
+
request['User-Agent'] = "brainzlab-sdk-ruby/#{BrainzLab::VERSION}"
|
|
55
55
|
request.body = JSON.generate({ name: @config.app_name })
|
|
56
56
|
|
|
57
57
|
response = execute(uri, request)
|
|
@@ -98,7 +98,7 @@ module BrainzLab
|
|
|
98
98
|
|
|
99
99
|
def execute(uri, request)
|
|
100
100
|
http = Net::HTTP.new(uri.host, uri.port)
|
|
101
|
-
http.use_ssl = uri.scheme ==
|
|
101
|
+
http.use_ssl = uri.scheme == 'https'
|
|
102
102
|
http.open_timeout = 5
|
|
103
103
|
http.read_timeout = 10
|
|
104
104
|
http.request(request)
|
|
@@ -16,7 +16,7 @@ module BrainzLab
|
|
|
16
16
|
Thread.current[:brainzlab_pulse_spans] ||= []
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
-
def start_trace(name, kind:
|
|
19
|
+
def start_trace(name, kind: 'custom', **attributes)
|
|
20
20
|
trace = {
|
|
21
21
|
trace_id: SecureRandom.uuid,
|
|
22
22
|
name: name,
|
|
@@ -64,7 +64,7 @@ module BrainzLab
|
|
|
64
64
|
payload
|
|
65
65
|
end
|
|
66
66
|
|
|
67
|
-
def span(name, kind:
|
|
67
|
+
def span(name, kind: 'custom', **data)
|
|
68
68
|
span_data = {
|
|
69
69
|
span_id: SecureRandom.uuid,
|
|
70
70
|
name: name,
|
|
@@ -91,7 +91,7 @@ module BrainzLab
|
|
|
91
91
|
|
|
92
92
|
private
|
|
93
93
|
|
|
94
|
-
def format_span(span,
|
|
94
|
+
def format_span(span, _trace_started_at)
|
|
95
95
|
{
|
|
96
96
|
span_id: span[:span_id],
|
|
97
97
|
parent_span_id: span[:parent_span_id],
|
data/lib/brainzlab/pulse.rb
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative
|
|
4
|
-
require_relative
|
|
5
|
-
require_relative
|
|
6
|
-
require_relative
|
|
7
|
-
require_relative
|
|
3
|
+
require_relative 'pulse/client'
|
|
4
|
+
require_relative 'pulse/provisioner'
|
|
5
|
+
require_relative 'pulse/tracer'
|
|
6
|
+
require_relative 'pulse/instrumentation'
|
|
7
|
+
require_relative 'pulse/propagation'
|
|
8
8
|
|
|
9
9
|
module BrainzLab
|
|
10
10
|
module Pulse
|
|
@@ -13,7 +13,7 @@ module BrainzLab
|
|
|
13
13
|
# @param name [String] the trace name
|
|
14
14
|
# @param kind [String] trace kind (request, job, custom)
|
|
15
15
|
# @param parent_context [Propagation::Context] optional parent context for distributed tracing
|
|
16
|
-
def start_trace(name, kind:
|
|
16
|
+
def start_trace(name, kind: 'custom', parent_context: nil, **attributes)
|
|
17
17
|
return nil unless enabled?
|
|
18
18
|
|
|
19
19
|
ensure_provisioned!
|
|
@@ -36,15 +36,15 @@ module BrainzLab
|
|
|
36
36
|
end
|
|
37
37
|
|
|
38
38
|
# Add a span to the current trace
|
|
39
|
-
def span(name, kind:
|
|
39
|
+
def span(name, kind: 'custom', **data, &)
|
|
40
40
|
return yield unless enabled?
|
|
41
41
|
return yield unless tracer.current_trace
|
|
42
42
|
|
|
43
|
-
tracer.span(name, kind: kind, **data)
|
|
43
|
+
tracer.span(name, kind: kind, **data, &)
|
|
44
44
|
end
|
|
45
45
|
|
|
46
46
|
# Record a complete trace (for when you have all data upfront)
|
|
47
|
-
def record_trace(name, kind:
|
|
47
|
+
def record_trace(name, started_at:, ended_at:, kind: 'request', **attributes)
|
|
48
48
|
return unless enabled?
|
|
49
49
|
|
|
50
50
|
ensure_provisioned!
|
|
@@ -55,7 +55,7 @@ module BrainzLab
|
|
|
55
55
|
end
|
|
56
56
|
|
|
57
57
|
# Record a custom metric
|
|
58
|
-
def record_metric(name, value:, kind:
|
|
58
|
+
def record_metric(name, value:, kind: 'gauge', tags: {})
|
|
59
59
|
return unless enabled?
|
|
60
60
|
|
|
61
61
|
ensure_provisioned!
|
|
@@ -74,15 +74,15 @@ module BrainzLab
|
|
|
74
74
|
|
|
75
75
|
# Convenience methods for metrics
|
|
76
76
|
def gauge(name, value, tags: {})
|
|
77
|
-
record_metric(name, value: value, kind:
|
|
77
|
+
record_metric(name, value: value, kind: 'gauge', tags: tags)
|
|
78
78
|
end
|
|
79
79
|
|
|
80
80
|
def counter(name, value = 1, tags: {})
|
|
81
|
-
record_metric(name, value: value, kind:
|
|
81
|
+
record_metric(name, value: value, kind: 'counter', tags: tags)
|
|
82
82
|
end
|
|
83
83
|
|
|
84
84
|
def histogram(name, value, tags: {})
|
|
85
|
-
record_metric(name, value: value, kind:
|
|
85
|
+
record_metric(name, value: value, kind: 'histogram', tags: tags)
|
|
86
86
|
end
|
|
87
87
|
|
|
88
88
|
def ensure_provisioned!
|