brainzlab 0.1.33 → 0.1.35
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/README.md +38 -0
- data/lib/brainzlab/beacon/client.rb +4 -6
- data/lib/brainzlab/configuration.rb +363 -258
- data/lib/brainzlab/cortex/client.rb +4 -6
- data/lib/brainzlab/debug.rb +6 -6
- data/lib/brainzlab/dendrite/client.rb +4 -6
- data/lib/brainzlab/development/logger.rb +2 -2
- data/lib/brainzlab/development/store.rb +2 -4
- data/lib/brainzlab/devtools/middleware/error_page.rb +1 -1
- data/lib/brainzlab/errors.rb +5 -12
- data/lib/brainzlab/instrumentation/action_cable.rb +4 -4
- data/lib/brainzlab/instrumentation/action_controller.rb +12 -12
- data/lib/brainzlab/instrumentation/action_dispatch.rb +1 -1
- data/lib/brainzlab/instrumentation/action_mailbox.rb +7 -13
- data/lib/brainzlab/instrumentation/action_view.rb +29 -33
- data/lib/brainzlab/instrumentation/active_job.rb +6 -10
- data/lib/brainzlab/instrumentation/active_record.rb +53 -25
- data/lib/brainzlab/instrumentation/active_storage.rb +4 -4
- data/lib/brainzlab/instrumentation/active_support_cache.rb +6 -8
- data/lib/brainzlab/instrumentation/aws.rb +10 -7
- data/lib/brainzlab/instrumentation/grape.rb +37 -2
- data/lib/brainzlab/instrumentation/rails_deprecation.rb +1 -1
- data/lib/brainzlab/instrumentation/railties.rb +2 -2
- data/lib/brainzlab/nerve/client.rb +4 -6
- data/lib/brainzlab/pulse/client.rb +1 -1
- data/lib/brainzlab/pulse/explain_capture.rb +123 -0
- data/lib/brainzlab/pulse.rb +6 -1
- data/lib/brainzlab/rails/railtie.rb +1 -3
- data/lib/brainzlab/reflex/client.rb +1 -1
- data/lib/brainzlab/sentinel/client.rb +4 -6
- data/lib/brainzlab/signal/client.rb +16 -2
- data/lib/brainzlab/signal.rb +8 -0
- data/lib/brainzlab/synapse/client.rb +4 -6
- data/lib/brainzlab/testing/event_store.rb +3 -3
- data/lib/brainzlab/testing/matchers.rb +4 -4
- data/lib/brainzlab/testing.rb +5 -3
- data/lib/brainzlab/utilities/route_path_normalizer.rb +91 -0
- data/lib/brainzlab/utilities.rb +1 -0
- data/lib/brainzlab/vault/client.rb +4 -6
- data/lib/brainzlab/version.rb +1 -1
- data/lib/brainzlab/vision/client.rb +3 -3
- data/lib/brainzlab.rb +1 -0
- data/lib/fluyenta-ruby.rb +1 -1
- metadata +3 -1
|
@@ -112,10 +112,10 @@ module BrainzLab
|
|
|
112
112
|
"expected event '#{@event_name}' to have been tracked, but no such event was found.\n" \
|
|
113
113
|
"Tracked events: #{BrainzLab::Testing.event_store.events.map { |e| e[:name] }.inspect}"
|
|
114
114
|
else
|
|
115
|
-
"expected event '#{@event_name}' to have been tracked with properties:\n" \
|
|
116
|
-
"
|
|
117
|
-
"but was tracked with:\n" \
|
|
118
|
-
"
|
|
115
|
+
"expected event '#{@event_name}' to have been tracked with properties:\n " \
|
|
116
|
+
"#{@expected_properties.inspect}\n" \
|
|
117
|
+
"but was tracked with:\n " \
|
|
118
|
+
"#{actual_events.map { |e| e[:properties] }.inspect}"
|
|
119
119
|
end
|
|
120
120
|
end
|
|
121
121
|
|
data/lib/brainzlab/testing.rb
CHANGED
|
@@ -198,16 +198,18 @@ module BrainzLab
|
|
|
198
198
|
end
|
|
199
199
|
|
|
200
200
|
# Stub distributed tracing methods
|
|
201
|
-
BrainzLab::Pulse.define_singleton_method(:inject) do |headers, **
|
|
201
|
+
BrainzLab::Pulse.define_singleton_method(:inject) do |headers, **_opts|
|
|
202
202
|
headers['traceparent'] = '00-test-trace-id-12345-test-span-id-67890-01'
|
|
203
203
|
headers
|
|
204
204
|
end
|
|
205
205
|
|
|
206
206
|
BrainzLab::Pulse.define_singleton_method(:extract) do |headers|
|
|
207
|
+
return unless headers['traceparent']
|
|
208
|
+
|
|
207
209
|
BrainzLab::Pulse::Propagation::Context.new(
|
|
208
210
|
trace_id: 'test-trace-id-12345',
|
|
209
211
|
span_id: 'test-span-id-67890'
|
|
210
|
-
)
|
|
212
|
+
)
|
|
211
213
|
end
|
|
212
214
|
|
|
213
215
|
BrainzLab::Pulse.define_singleton_method(:extract!) do |headers|
|
|
@@ -304,7 +306,7 @@ module BrainzLab
|
|
|
304
306
|
BrainzLab::Cortex.define_singleton_method(:read) { |*| nil }
|
|
305
307
|
BrainzLab::Cortex.define_singleton_method(:write) { |*| true }
|
|
306
308
|
BrainzLab::Cortex.define_singleton_method(:delete) { |*| true }
|
|
307
|
-
BrainzLab::Cortex.define_singleton_method(:fetch) { |
|
|
309
|
+
BrainzLab::Cortex.define_singleton_method(:fetch) { |_key, **_opts, &block| block&.call }
|
|
308
310
|
end
|
|
309
311
|
|
|
310
312
|
def stub_vault!
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module BrainzLab
|
|
4
|
+
module Utilities
|
|
5
|
+
# Collapses concrete request paths into route patterns, so that
|
|
6
|
+
# /users/1, /users/2 ... /users/99999 aggregate as a single /users/:id
|
|
7
|
+
# endpoint instead of one endpoint per record.
|
|
8
|
+
#
|
|
9
|
+
# Rails instrumentation names traces by controller#action and does not need
|
|
10
|
+
# this. Grape and plain Rack do: when the router does not expose a route
|
|
11
|
+
# pattern the SDK falls back to the raw PATH_INFO, which is where the
|
|
12
|
+
# cardinality blowup comes from.
|
|
13
|
+
#
|
|
14
|
+
# Two modes:
|
|
15
|
+
# * with path params — substitute the exact values the router resolved
|
|
16
|
+
# * without them — fall back to recognising id-shaped segments
|
|
17
|
+
module RoutePathNormalizer
|
|
18
|
+
# Params that describe the dispatch rather than the path itself.
|
|
19
|
+
SKIP_PARAMS = %i[controller action format].freeze
|
|
20
|
+
|
|
21
|
+
UUID_PATTERN = /\A\h{8}-\h{4}-\h{4}-\h{4}-\h{12}\z/
|
|
22
|
+
NUMERIC_PATTERN = /\A\d+\z/
|
|
23
|
+
# 16+ hex chars: git SHAs, hex tokens. Shorter hex strings are too easily
|
|
24
|
+
# a real word segment ("beef", "cafe") to risk substituting.
|
|
25
|
+
LONG_HEX_PATTERN = /\A\h{16,}\z/
|
|
26
|
+
|
|
27
|
+
module_function
|
|
28
|
+
|
|
29
|
+
# @param path [String, nil] the concrete request path
|
|
30
|
+
# @param path_params [Hash, nil] params the router resolved, when available
|
|
31
|
+
# @return [String, nil] the path with variable segments replaced
|
|
32
|
+
def normalize(path, path_params = nil)
|
|
33
|
+
return path if path.nil? || path.empty?
|
|
34
|
+
|
|
35
|
+
params = normalize_params(path_params)
|
|
36
|
+
|
|
37
|
+
# -1 keeps trailing empty segments, so a trailing slash survives.
|
|
38
|
+
segments = path.split('/', -1)
|
|
39
|
+
normalized = segments.map do |segment|
|
|
40
|
+
next segment if segment.empty?
|
|
41
|
+
|
|
42
|
+
params.empty? ? substitute_by_shape(segment) : substitute_by_param(segment, params)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
normalized.join('/')
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def normalize_params(path_params)
|
|
49
|
+
return {} if path_params.nil? || path_params.empty?
|
|
50
|
+
|
|
51
|
+
# Map value => [param names]. A value claimed by more than one param is
|
|
52
|
+
# ambiguous, so it is left alone rather than guessed at.
|
|
53
|
+
path_params.each_with_object({}) do |(key, value), map|
|
|
54
|
+
next if SKIP_PARAMS.include?(key.to_sym)
|
|
55
|
+
|
|
56
|
+
(map[value.to_s] ||= []) << key
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def substitute_by_param(segment, params)
|
|
61
|
+
keys = params[segment]
|
|
62
|
+
return ":#{keys.first}" if keys && keys.length == 1
|
|
63
|
+
|
|
64
|
+
# "42.json" when the id param is "42"
|
|
65
|
+
if segment.include?('.')
|
|
66
|
+
base, extension = segment.split('.', 2)
|
|
67
|
+
keys = params[base]
|
|
68
|
+
return ":#{keys.first}.#{extension}" if keys && keys.length == 1
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
segment
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def substitute_by_shape(segment)
|
|
75
|
+
base, extension = segment.include?('.') ? segment.split('.', 2) : [segment, nil]
|
|
76
|
+
placeholder = placeholder_for(base)
|
|
77
|
+
return segment if placeholder.nil?
|
|
78
|
+
|
|
79
|
+
extension ? "#{placeholder}.#{extension}" : placeholder
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def placeholder_for(segment)
|
|
83
|
+
return ':uuid' if segment.match?(UUID_PATTERN)
|
|
84
|
+
return ':id' if segment.match?(NUMERIC_PATTERN)
|
|
85
|
+
return ':id' if segment.match?(LONG_HEX_PATTERN)
|
|
86
|
+
|
|
87
|
+
nil
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
data/lib/brainzlab/utilities.rb
CHANGED
|
@@ -4,6 +4,7 @@ require_relative 'utilities/rate_limiter'
|
|
|
4
4
|
require_relative 'utilities/circuit_breaker'
|
|
5
5
|
require_relative 'utilities/health_check'
|
|
6
6
|
require_relative 'utilities/log_formatter'
|
|
7
|
+
require_relative 'utilities/route_path_normalizer'
|
|
7
8
|
|
|
8
9
|
module BrainzLab
|
|
9
10
|
module Utilities
|
|
@@ -193,9 +193,9 @@ module BrainzLab
|
|
|
193
193
|
BrainzLab.debug_log("[Vault::Client] #{operation} failed: #{structured_error.message}")
|
|
194
194
|
|
|
195
195
|
# Call on_error callback if configured
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
196
|
+
return unless @config.on_error
|
|
197
|
+
|
|
198
|
+
@config.on_error.call(structured_error, { service: 'Vault', operation: operation })
|
|
199
199
|
end
|
|
200
200
|
|
|
201
201
|
def handle_response_error(response, operation)
|
|
@@ -205,9 +205,7 @@ module BrainzLab
|
|
|
205
205
|
BrainzLab.debug_log("[Vault::Client] #{operation} failed: #{structured_error.message}")
|
|
206
206
|
|
|
207
207
|
# Call on_error callback if configured
|
|
208
|
-
|
|
209
|
-
@config.on_error.call(structured_error, { service: 'Vault', operation: operation })
|
|
210
|
-
end
|
|
208
|
+
@config.on_error&.call(structured_error, { service: 'Vault', operation: operation })
|
|
211
209
|
|
|
212
210
|
structured_error
|
|
213
211
|
end
|
data/lib/brainzlab/version.rb
CHANGED
|
@@ -154,9 +154,9 @@ module BrainzLab
|
|
|
154
154
|
BrainzLab.debug_log("[Vision::Client] #{operation} failed: #{error.message}")
|
|
155
155
|
|
|
156
156
|
# Call on_error callback if configured
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
157
|
+
return unless @config.on_error
|
|
158
|
+
|
|
159
|
+
@config.on_error.call(error, { service: 'Vision', operation: operation })
|
|
160
160
|
end
|
|
161
161
|
|
|
162
162
|
def auth_key
|
data/lib/brainzlab.rb
CHANGED
data/lib/fluyenta-ruby.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: brainzlab
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.35
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- BrainzLab
|
|
@@ -177,6 +177,7 @@ files:
|
|
|
177
177
|
- lib/brainzlab/nerve/provisioner.rb
|
|
178
178
|
- lib/brainzlab/pulse.rb
|
|
179
179
|
- lib/brainzlab/pulse/client.rb
|
|
180
|
+
- lib/brainzlab/pulse/explain_capture.rb
|
|
180
181
|
- lib/brainzlab/pulse/instrumentation.rb
|
|
181
182
|
- lib/brainzlab/pulse/propagation.rb
|
|
182
183
|
- lib/brainzlab/pulse/provisioner.rb
|
|
@@ -211,6 +212,7 @@ files:
|
|
|
211
212
|
- lib/brainzlab/utilities/health_check.rb
|
|
212
213
|
- lib/brainzlab/utilities/log_formatter.rb
|
|
213
214
|
- lib/brainzlab/utilities/rate_limiter.rb
|
|
215
|
+
- lib/brainzlab/utilities/route_path_normalizer.rb
|
|
214
216
|
- lib/brainzlab/vault.rb
|
|
215
217
|
- lib/brainzlab/vault/cache.rb
|
|
216
218
|
- lib/brainzlab/vault/client.rb
|