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
|
@@ -4,6 +4,9 @@ module BrainzLab
|
|
|
4
4
|
class Configuration
|
|
5
5
|
LEVELS = %i[debug info warn error fatal].freeze
|
|
6
6
|
|
|
7
|
+
# recall_min_level has a custom setter with validation
|
|
8
|
+
attr_reader :recall_min_level
|
|
9
|
+
|
|
7
10
|
attr_accessor :secret_key,
|
|
8
11
|
:environment,
|
|
9
12
|
:service,
|
|
@@ -14,7 +17,6 @@ module BrainzLab
|
|
|
14
17
|
:debug,
|
|
15
18
|
:recall_enabled,
|
|
16
19
|
:recall_url,
|
|
17
|
-
:recall_min_level,
|
|
18
20
|
:recall_buffer_size,
|
|
19
21
|
:recall_flush_interval,
|
|
20
22
|
:recall_master_key,
|
|
@@ -110,7 +112,11 @@ module BrainzLab
|
|
|
110
112
|
:instrument_graphql,
|
|
111
113
|
:instrument_mongodb,
|
|
112
114
|
:instrument_elasticsearch,
|
|
115
|
+
:instrument_action_controller,
|
|
116
|
+
:instrument_action_view,
|
|
113
117
|
:instrument_action_mailer,
|
|
118
|
+
:instrument_active_job,
|
|
119
|
+
:instrument_active_support_cache,
|
|
114
120
|
:instrument_delayed_job,
|
|
115
121
|
:instrument_grape,
|
|
116
122
|
:instrument_solid_queue,
|
|
@@ -121,6 +127,12 @@ module BrainzLab
|
|
|
121
127
|
:instrument_dalli,
|
|
122
128
|
:instrument_aws,
|
|
123
129
|
:instrument_stripe,
|
|
130
|
+
:instrument_active_storage,
|
|
131
|
+
:instrument_action_cable,
|
|
132
|
+
:instrument_action_dispatch,
|
|
133
|
+
:instrument_rails_deprecation,
|
|
134
|
+
:instrument_action_mailbox,
|
|
135
|
+
:instrument_railties,
|
|
124
136
|
:http_ignore_hosts,
|
|
125
137
|
:redis_ignore_commands,
|
|
126
138
|
:log_formatter_enabled,
|
|
@@ -140,61 +152,61 @@ module BrainzLab
|
|
|
140
152
|
|
|
141
153
|
# Services that should not track themselves to avoid circular dependencies
|
|
142
154
|
SELF_TRACKING_SERVICES = {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
155
|
+
'recall' => :recall_enabled,
|
|
156
|
+
'reflex' => :reflex_enabled,
|
|
157
|
+
'pulse' => :pulse_enabled,
|
|
158
|
+
'flux' => :flux_enabled,
|
|
159
|
+
'signal' => :signal_enabled
|
|
148
160
|
}.freeze
|
|
149
161
|
|
|
150
162
|
def initialize
|
|
151
163
|
# Authentication
|
|
152
|
-
@secret_key = ENV
|
|
164
|
+
@secret_key = ENV.fetch('BRAINZLAB_SECRET_KEY', nil)
|
|
153
165
|
|
|
154
166
|
# Environment
|
|
155
|
-
@environment = ENV[
|
|
156
|
-
@service = ENV
|
|
157
|
-
@host = ENV[
|
|
167
|
+
@environment = ENV['BRAINZLAB_ENVIRONMENT'] || detect_environment
|
|
168
|
+
@service = ENV.fetch('BRAINZLAB_SERVICE', nil)
|
|
169
|
+
@host = ENV['BRAINZLAB_HOST'] || detect_host
|
|
158
170
|
|
|
159
171
|
# App name for auto-provisioning
|
|
160
|
-
@app_name = ENV
|
|
172
|
+
@app_name = ENV.fetch('BRAINZLAB_APP_NAME', nil)
|
|
161
173
|
|
|
162
174
|
# Git context
|
|
163
|
-
@commit = ENV[
|
|
164
|
-
@branch = ENV[
|
|
175
|
+
@commit = ENV['GIT_COMMIT'] || ENV['COMMIT_SHA'] || detect_git_commit
|
|
176
|
+
@branch = ENV['GIT_BRANCH'] || ENV['BRANCH_NAME'] || detect_git_branch
|
|
165
177
|
|
|
166
178
|
# Debug mode - enables verbose logging
|
|
167
|
-
@debug = ENV[
|
|
179
|
+
@debug = ENV['BRAINZLAB_DEBUG'] == 'true'
|
|
168
180
|
|
|
169
181
|
# Disable self-tracking - prevents services from tracking to themselves
|
|
170
182
|
# e.g., Recall won't log to itself, Reflex won't track errors to itself
|
|
171
|
-
@disable_self_tracking = ENV.fetch(
|
|
183
|
+
@disable_self_tracking = ENV.fetch('BRAINZLAB_DISABLE_SELF_TRACKING', 'true') == 'true'
|
|
172
184
|
|
|
173
185
|
# Recall settings
|
|
174
186
|
@recall_enabled = true
|
|
175
|
-
@recall_url = ENV[
|
|
187
|
+
@recall_url = ENV['RECALL_URL'] || 'https://recall.brainzlab.ai'
|
|
176
188
|
@recall_min_level = :debug
|
|
177
189
|
@recall_buffer_size = 50
|
|
178
190
|
@recall_flush_interval = 5
|
|
179
|
-
@recall_master_key = ENV
|
|
191
|
+
@recall_master_key = ENV.fetch('RECALL_MASTER_KEY', nil)
|
|
180
192
|
@recall_auto_provision = true
|
|
181
193
|
|
|
182
194
|
# Reflex settings
|
|
183
195
|
@reflex_enabled = true
|
|
184
|
-
@reflex_url = ENV[
|
|
185
|
-
@reflex_api_key = ENV
|
|
186
|
-
@reflex_master_key = ENV
|
|
196
|
+
@reflex_url = ENV['REFLEX_URL'] || 'https://reflex.brainzlab.ai'
|
|
197
|
+
@reflex_api_key = ENV.fetch('REFLEX_API_KEY', nil)
|
|
198
|
+
@reflex_master_key = ENV.fetch('REFLEX_MASTER_KEY', nil)
|
|
187
199
|
@reflex_auto_provision = true
|
|
188
200
|
@reflex_excluded_exceptions = []
|
|
189
201
|
@reflex_before_send = nil
|
|
190
202
|
@reflex_sample_rate = nil
|
|
191
|
-
@reflex_fingerprint = nil
|
|
203
|
+
@reflex_fingerprint = nil # Custom fingerprint callback
|
|
192
204
|
|
|
193
205
|
# Pulse settings
|
|
194
206
|
@pulse_enabled = true
|
|
195
|
-
@pulse_url = ENV[
|
|
196
|
-
@pulse_api_key = ENV
|
|
197
|
-
@pulse_master_key = ENV
|
|
207
|
+
@pulse_url = ENV['PULSE_URL'] || 'https://pulse.brainzlab.ai'
|
|
208
|
+
@pulse_api_key = ENV.fetch('PULSE_API_KEY', nil)
|
|
209
|
+
@pulse_master_key = ENV.fetch('PULSE_MASTER_KEY', nil)
|
|
198
210
|
@pulse_auto_provision = true
|
|
199
211
|
@pulse_buffer_size = 50
|
|
200
212
|
@pulse_flush_interval = 5
|
|
@@ -203,86 +215,86 @@ module BrainzLab
|
|
|
203
215
|
|
|
204
216
|
# Flux settings
|
|
205
217
|
@flux_enabled = true
|
|
206
|
-
@flux_url = ENV[
|
|
207
|
-
@flux_api_key = ENV
|
|
208
|
-
@flux_ingest_key = ENV
|
|
209
|
-
@flux_master_key = ENV
|
|
218
|
+
@flux_url = ENV['FLUX_URL'] || 'https://flux.brainzlab.ai'
|
|
219
|
+
@flux_api_key = ENV.fetch('FLUX_API_KEY', nil)
|
|
220
|
+
@flux_ingest_key = ENV.fetch('FLUX_INGEST_KEY', nil)
|
|
221
|
+
@flux_master_key = ENV.fetch('FLUX_MASTER_KEY', nil)
|
|
210
222
|
@flux_auto_provision = true
|
|
211
223
|
@flux_buffer_size = 100
|
|
212
224
|
@flux_flush_interval = 5
|
|
213
225
|
|
|
214
226
|
# Signal settings
|
|
215
227
|
@signal_enabled = true
|
|
216
|
-
@signal_url = ENV[
|
|
217
|
-
@signal_api_key = ENV
|
|
218
|
-
@signal_master_key = ENV
|
|
228
|
+
@signal_url = ENV['SIGNAL_URL'] || 'https://signal.brainzlab.ai'
|
|
229
|
+
@signal_api_key = ENV.fetch('SIGNAL_API_KEY', nil)
|
|
230
|
+
@signal_master_key = ENV.fetch('SIGNAL_MASTER_KEY', nil)
|
|
219
231
|
@signal_auto_provision = true
|
|
220
232
|
|
|
221
233
|
# Vault settings
|
|
222
234
|
@vault_enabled = true
|
|
223
|
-
@vault_url = ENV[
|
|
224
|
-
@vault_api_key = ENV
|
|
225
|
-
@vault_master_key = ENV
|
|
235
|
+
@vault_url = ENV['VAULT_URL'] || 'https://vault.brainzlab.ai'
|
|
236
|
+
@vault_api_key = ENV.fetch('VAULT_API_KEY', nil)
|
|
237
|
+
@vault_master_key = ENV.fetch('VAULT_MASTER_KEY', nil)
|
|
226
238
|
@vault_auto_provision = true
|
|
227
239
|
@vault_cache_enabled = true
|
|
228
|
-
@vault_cache_ttl = 300
|
|
229
|
-
@vault_auto_load = ENV.fetch(
|
|
230
|
-
@vault_load_provider_keys = true
|
|
240
|
+
@vault_cache_ttl = 300 # 5 minutes
|
|
241
|
+
@vault_auto_load = ENV.fetch('VAULT_AUTO_LOAD', 'false') == 'true' # Auto-load secrets into ENV
|
|
242
|
+
@vault_load_provider_keys = true # Also load provider keys (OpenAI, etc.)
|
|
231
243
|
|
|
232
244
|
# Vision settings (AI browser automation)
|
|
233
245
|
@vision_enabled = true
|
|
234
|
-
@vision_url = ENV[
|
|
235
|
-
@vision_api_key = ENV
|
|
236
|
-
@vision_ingest_key = ENV
|
|
237
|
-
@vision_master_key = ENV
|
|
246
|
+
@vision_url = ENV['VISION_URL'] || 'https://vision.brainzlab.ai'
|
|
247
|
+
@vision_api_key = ENV.fetch('VISION_API_KEY', nil)
|
|
248
|
+
@vision_ingest_key = ENV.fetch('VISION_INGEST_KEY', nil)
|
|
249
|
+
@vision_master_key = ENV.fetch('VISION_MASTER_KEY', nil)
|
|
238
250
|
@vision_auto_provision = true
|
|
239
|
-
@vision_default_model = ENV[
|
|
240
|
-
@vision_default_browser_provider = ENV[
|
|
251
|
+
@vision_default_model = ENV['VISION_DEFAULT_MODEL'] || 'claude-sonnet-4'
|
|
252
|
+
@vision_default_browser_provider = ENV['VISION_DEFAULT_BROWSER_PROVIDER'] || 'local'
|
|
241
253
|
|
|
242
254
|
# Cortex settings (feature flags)
|
|
243
255
|
@cortex_enabled = true
|
|
244
|
-
@cortex_url = ENV[
|
|
245
|
-
@cortex_api_key = ENV
|
|
246
|
-
@cortex_master_key = ENV
|
|
256
|
+
@cortex_url = ENV['CORTEX_URL'] || 'https://cortex.brainzlab.ai'
|
|
257
|
+
@cortex_api_key = ENV.fetch('CORTEX_API_KEY', nil)
|
|
258
|
+
@cortex_master_key = ENV.fetch('CORTEX_MASTER_KEY', nil)
|
|
247
259
|
@cortex_auto_provision = true
|
|
248
260
|
@cortex_cache_enabled = true
|
|
249
|
-
@cortex_cache_ttl = 60
|
|
261
|
+
@cortex_cache_ttl = 60 # 1 minute
|
|
250
262
|
@cortex_default_context = {}
|
|
251
263
|
|
|
252
264
|
# Beacon settings (uptime monitoring)
|
|
253
265
|
@beacon_enabled = true
|
|
254
|
-
@beacon_url = ENV[
|
|
255
|
-
@beacon_api_key = ENV
|
|
256
|
-
@beacon_master_key = ENV
|
|
266
|
+
@beacon_url = ENV['BEACON_URL'] || 'https://beacon.brainzlab.ai'
|
|
267
|
+
@beacon_api_key = ENV.fetch('BEACON_API_KEY', nil)
|
|
268
|
+
@beacon_master_key = ENV.fetch('BEACON_MASTER_KEY', nil)
|
|
257
269
|
@beacon_auto_provision = true
|
|
258
270
|
|
|
259
271
|
# Nerve settings (job monitoring)
|
|
260
272
|
@nerve_enabled = true
|
|
261
|
-
@nerve_url = ENV[
|
|
262
|
-
@nerve_api_key = ENV
|
|
263
|
-
@nerve_master_key = ENV
|
|
273
|
+
@nerve_url = ENV['NERVE_URL'] || 'https://nerve.brainzlab.ai'
|
|
274
|
+
@nerve_api_key = ENV.fetch('NERVE_API_KEY', nil)
|
|
275
|
+
@nerve_master_key = ENV.fetch('NERVE_MASTER_KEY', nil)
|
|
264
276
|
@nerve_auto_provision = true
|
|
265
277
|
|
|
266
278
|
# Dendrite settings (AI documentation)
|
|
267
279
|
@dendrite_enabled = true
|
|
268
|
-
@dendrite_url = ENV[
|
|
269
|
-
@dendrite_api_key = ENV
|
|
270
|
-
@dendrite_master_key = ENV
|
|
280
|
+
@dendrite_url = ENV['DENDRITE_URL'] || 'https://dendrite.brainzlab.ai'
|
|
281
|
+
@dendrite_api_key = ENV.fetch('DENDRITE_API_KEY', nil)
|
|
282
|
+
@dendrite_master_key = ENV.fetch('DENDRITE_MASTER_KEY', nil)
|
|
271
283
|
@dendrite_auto_provision = true
|
|
272
284
|
|
|
273
285
|
# Sentinel settings (host monitoring)
|
|
274
286
|
@sentinel_enabled = true
|
|
275
|
-
@sentinel_url = ENV[
|
|
276
|
-
@sentinel_api_key = ENV
|
|
277
|
-
@sentinel_agent_key = ENV
|
|
278
|
-
@sentinel_master_key = ENV
|
|
287
|
+
@sentinel_url = ENV['SENTINEL_URL'] || 'https://sentinel.brainzlab.ai'
|
|
288
|
+
@sentinel_api_key = ENV.fetch('SENTINEL_API_KEY', nil)
|
|
289
|
+
@sentinel_agent_key = ENV.fetch('SENTINEL_AGENT_KEY', nil)
|
|
290
|
+
@sentinel_master_key = ENV.fetch('SENTINEL_MASTER_KEY', nil)
|
|
279
291
|
@sentinel_auto_provision = true
|
|
280
292
|
|
|
281
293
|
# Synapse settings (AI development orchestration)
|
|
282
294
|
@synapse_enabled = true
|
|
283
|
-
@synapse_url = ENV[
|
|
284
|
-
@synapse_api_key = ENV
|
|
285
|
-
@synapse_master_key = ENV
|
|
295
|
+
@synapse_url = ENV['SYNAPSE_URL'] || 'https://synapse.brainzlab.ai'
|
|
296
|
+
@synapse_api_key = ENV.fetch('SYNAPSE_API_KEY', nil)
|
|
297
|
+
@synapse_master_key = ENV.fetch('SYNAPSE_MASTER_KEY', nil)
|
|
286
298
|
@synapse_auto_provision = true
|
|
287
299
|
|
|
288
300
|
# Filtering
|
|
@@ -292,26 +304,36 @@ module BrainzLab
|
|
|
292
304
|
@logger = nil
|
|
293
305
|
|
|
294
306
|
# Instrumentation
|
|
295
|
-
@instrument_http = true
|
|
296
|
-
@instrument_active_record = true
|
|
297
|
-
@instrument_redis = true
|
|
307
|
+
@instrument_http = true # Enable HTTP client instrumentation (Net::HTTP, Faraday, HTTParty)
|
|
308
|
+
@instrument_active_record = true # AR breadcrumbs for Reflex
|
|
309
|
+
@instrument_redis = true # Redis command instrumentation
|
|
298
310
|
@instrument_sidekiq = true # Sidekiq job instrumentation
|
|
299
311
|
@instrument_graphql = true # GraphQL query instrumentation
|
|
300
312
|
@instrument_mongodb = true # MongoDB/Mongoid instrumentation
|
|
301
313
|
@instrument_elasticsearch = true # Elasticsearch instrumentation
|
|
314
|
+
@instrument_action_controller = true # ActionController instrumentation (requests, redirects, filters)
|
|
315
|
+
@instrument_action_view = true # ActionView instrumentation (templates, partials, collections)
|
|
302
316
|
@instrument_action_mailer = true # ActionMailer instrumentation
|
|
303
|
-
@
|
|
304
|
-
@
|
|
305
|
-
@
|
|
306
|
-
@
|
|
307
|
-
@
|
|
308
|
-
@
|
|
309
|
-
@
|
|
310
|
-
@
|
|
311
|
-
@
|
|
312
|
-
@
|
|
317
|
+
@instrument_active_job = true # ActiveJob instrumentation (enqueue, perform, retry, discard)
|
|
318
|
+
@instrument_active_support_cache = true # ActiveSupport::Cache instrumentation (read, write, fetch)
|
|
319
|
+
@instrument_delayed_job = true # Delayed::Job instrumentation
|
|
320
|
+
@instrument_grape = true # Grape API instrumentation
|
|
321
|
+
@instrument_solid_queue = true # Solid Queue job instrumentation
|
|
322
|
+
@instrument_good_job = true # GoodJob instrumentation
|
|
323
|
+
@instrument_resque = true # Resque instrumentation
|
|
324
|
+
@instrument_excon = true # Excon HTTP client instrumentation
|
|
325
|
+
@instrument_typhoeus = true # Typhoeus HTTP client instrumentation
|
|
326
|
+
@instrument_dalli = true # Dalli/Memcached instrumentation
|
|
327
|
+
@instrument_aws = true # AWS SDK instrumentation
|
|
328
|
+
@instrument_stripe = true # Stripe API instrumentation
|
|
329
|
+
@instrument_active_storage = true # ActiveStorage instrumentation (uploads, downloads, transforms)
|
|
330
|
+
@instrument_action_cable = true # ActionCable WebSocket instrumentation
|
|
331
|
+
@instrument_action_dispatch = true # ActionDispatch instrumentation (middleware, redirects, requests)
|
|
332
|
+
@instrument_rails_deprecation = true # Rails deprecation warnings tracking
|
|
333
|
+
@instrument_action_mailbox = true # ActionMailbox inbound email processing instrumentation
|
|
334
|
+
@instrument_railties = true # Railties config initializer loading instrumentation
|
|
313
335
|
@http_ignore_hosts = %w[localhost 127.0.0.1]
|
|
314
|
-
@redis_ignore_commands = %w[ping info]
|
|
336
|
+
@redis_ignore_commands = %w[ping info] # Commands to skip tracking
|
|
315
337
|
|
|
316
338
|
# Log formatter settings
|
|
317
339
|
@log_formatter_enabled = true
|
|
@@ -325,9 +347,9 @@ module BrainzLab
|
|
|
325
347
|
@devtools_error_page_enabled = true
|
|
326
348
|
@devtools_debug_panel_enabled = true
|
|
327
349
|
@devtools_allowed_environments = %w[development test]
|
|
328
|
-
@devtools_allowed_ips = [
|
|
329
|
-
@devtools_asset_path =
|
|
330
|
-
@devtools_panel_position =
|
|
350
|
+
@devtools_allowed_ips = ['127.0.0.1', '::1', '172.16.0.0/12', '192.168.0.0/16', '10.0.0.0/8']
|
|
351
|
+
@devtools_asset_path = '/__brainzlab__'
|
|
352
|
+
@devtools_panel_position = 'bottom-right'
|
|
331
353
|
@devtools_expand_by_default = false
|
|
332
354
|
end
|
|
333
355
|
|
|
@@ -465,7 +487,7 @@ module BrainzLab
|
|
|
465
487
|
|
|
466
488
|
# Disable if this is the Recall service itself
|
|
467
489
|
normalized_app_name = @app_name.to_s.downcase.strip
|
|
468
|
-
normalized_app_name !=
|
|
490
|
+
normalized_app_name != 'recall'
|
|
469
491
|
end
|
|
470
492
|
|
|
471
493
|
# Check if reflex is effectively enabled (considering self-tracking)
|
|
@@ -475,7 +497,7 @@ module BrainzLab
|
|
|
475
497
|
|
|
476
498
|
# Disable if this is the Reflex service itself
|
|
477
499
|
normalized_app_name = @app_name.to_s.downcase.strip
|
|
478
|
-
normalized_app_name !=
|
|
500
|
+
normalized_app_name != 'reflex'
|
|
479
501
|
end
|
|
480
502
|
|
|
481
503
|
# Check if pulse is effectively enabled (considering self-tracking)
|
|
@@ -485,7 +507,7 @@ module BrainzLab
|
|
|
485
507
|
|
|
486
508
|
# Disable if this is the Pulse service itself
|
|
487
509
|
normalized_app_name = @app_name.to_s.downcase.strip
|
|
488
|
-
normalized_app_name !=
|
|
510
|
+
normalized_app_name != 'pulse'
|
|
489
511
|
end
|
|
490
512
|
|
|
491
513
|
# Check if flux is effectively enabled (considering self-tracking)
|
|
@@ -495,7 +517,7 @@ module BrainzLab
|
|
|
495
517
|
|
|
496
518
|
# Disable if this is the Flux service itself
|
|
497
519
|
normalized_app_name = @app_name.to_s.downcase.strip
|
|
498
|
-
normalized_app_name !=
|
|
520
|
+
normalized_app_name != 'flux'
|
|
499
521
|
end
|
|
500
522
|
|
|
501
523
|
# Check if signal is effectively enabled (considering self-tracking)
|
|
@@ -505,7 +527,7 @@ module BrainzLab
|
|
|
505
527
|
|
|
506
528
|
# Disable if this is the Signal service itself
|
|
507
529
|
normalized_app_name = @app_name.to_s.downcase.strip
|
|
508
|
-
normalized_app_name !=
|
|
530
|
+
normalized_app_name != 'signal'
|
|
509
531
|
end
|
|
510
532
|
|
|
511
533
|
def debug_log(message)
|
|
@@ -515,7 +537,7 @@ module BrainzLab
|
|
|
515
537
|
if logger
|
|
516
538
|
logger.debug(log_message)
|
|
517
539
|
else
|
|
518
|
-
|
|
540
|
+
warn(log_message)
|
|
519
541
|
end
|
|
520
542
|
end
|
|
521
543
|
|
|
@@ -523,14 +545,14 @@ module BrainzLab
|
|
|
523
545
|
|
|
524
546
|
def detect_environment
|
|
525
547
|
return ::Rails.env.to_s if defined?(::Rails) && ::Rails.respond_to?(:env)
|
|
526
|
-
return ENV[
|
|
527
|
-
return ENV[
|
|
548
|
+
return ENV['RACK_ENV'] if ENV['RACK_ENV']
|
|
549
|
+
return ENV['RUBY_ENV'] if ENV['RUBY_ENV']
|
|
528
550
|
|
|
529
|
-
|
|
551
|
+
'development'
|
|
530
552
|
end
|
|
531
553
|
|
|
532
554
|
def detect_host
|
|
533
|
-
require
|
|
555
|
+
require 'socket'
|
|
534
556
|
Socket.gethostname
|
|
535
557
|
rescue StandardError
|
|
536
558
|
nil
|
data/lib/brainzlab/context.rb
CHANGED
|
@@ -14,9 +14,8 @@ module BrainzLab
|
|
|
14
14
|
end
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
-
attr_accessor :user, :request_id, :session_id
|
|
18
|
-
|
|
19
|
-
attr_accessor :controller, :action
|
|
17
|
+
attr_accessor :user, :request_id, :session_id, :request_method, :request_path, :request_url, :request_params,
|
|
18
|
+
:request_headers, :controller, :action
|
|
20
19
|
attr_reader :extra, :tags, :breadcrumbs
|
|
21
20
|
|
|
22
21
|
def initialize
|
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
4
|
-
require
|
|
5
|
-
require
|
|
6
|
-
require
|
|
3
|
+
require 'net/http'
|
|
4
|
+
require 'json'
|
|
5
|
+
require 'uri'
|
|
6
|
+
require 'cgi'
|
|
7
7
|
|
|
8
8
|
module BrainzLab
|
|
9
9
|
module Cortex
|
|
10
10
|
class Client
|
|
11
11
|
def initialize(config)
|
|
12
12
|
@config = config
|
|
13
|
-
@base_url = config.cortex_url ||
|
|
13
|
+
@base_url = config.cortex_url || 'https://cortex.brainzlab.ai'
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
# Evaluate a single flag
|
|
17
17
|
def evaluate(flag_name, context: {})
|
|
18
18
|
response = request(
|
|
19
19
|
:post,
|
|
20
|
-
|
|
20
|
+
'/api/v1/evaluate',
|
|
21
21
|
body: {
|
|
22
22
|
flag: flag_name,
|
|
23
23
|
context: context
|
|
@@ -29,7 +29,7 @@ module BrainzLab
|
|
|
29
29
|
data = JSON.parse(response.body, symbolize_names: true)
|
|
30
30
|
data[:result]
|
|
31
31
|
rescue StandardError => e
|
|
32
|
-
log_error(
|
|
32
|
+
log_error('evaluate', e)
|
|
33
33
|
nil
|
|
34
34
|
end
|
|
35
35
|
|
|
@@ -37,7 +37,7 @@ module BrainzLab
|
|
|
37
37
|
def evaluate_all(context: {})
|
|
38
38
|
response = request(
|
|
39
39
|
:post,
|
|
40
|
-
|
|
40
|
+
'/api/v1/evaluate/batch',
|
|
41
41
|
body: { context: context }
|
|
42
42
|
)
|
|
43
43
|
|
|
@@ -46,20 +46,20 @@ module BrainzLab
|
|
|
46
46
|
data = JSON.parse(response.body, symbolize_names: true)
|
|
47
47
|
data[:flags] || {}
|
|
48
48
|
rescue StandardError => e
|
|
49
|
-
log_error(
|
|
49
|
+
log_error('evaluate_all', e)
|
|
50
50
|
{}
|
|
51
51
|
end
|
|
52
52
|
|
|
53
53
|
# List all flags
|
|
54
54
|
def list
|
|
55
|
-
response = request(:get,
|
|
55
|
+
response = request(:get, '/api/v1/flags')
|
|
56
56
|
|
|
57
57
|
return [] unless response.is_a?(Net::HTTPSuccess)
|
|
58
58
|
|
|
59
59
|
data = JSON.parse(response.body, symbolize_names: true)
|
|
60
60
|
data[:flags] || []
|
|
61
61
|
rescue StandardError => e
|
|
62
|
-
log_error(
|
|
62
|
+
log_error('list', e)
|
|
63
63
|
[]
|
|
64
64
|
end
|
|
65
65
|
|
|
@@ -71,21 +71,21 @@ module BrainzLab
|
|
|
71
71
|
|
|
72
72
|
JSON.parse(response.body, symbolize_names: true)
|
|
73
73
|
rescue StandardError => e
|
|
74
|
-
log_error(
|
|
74
|
+
log_error('get_flag', e)
|
|
75
75
|
nil
|
|
76
76
|
end
|
|
77
77
|
|
|
78
78
|
def provision(project_id:, app_name:)
|
|
79
79
|
response = request(
|
|
80
80
|
:post,
|
|
81
|
-
|
|
81
|
+
'/api/v1/projects/provision',
|
|
82
82
|
body: { project_id: project_id, app_name: app_name },
|
|
83
83
|
use_service_key: true
|
|
84
84
|
)
|
|
85
85
|
|
|
86
86
|
response.is_a?(Net::HTTPSuccess) || response.is_a?(Net::HTTPCreated)
|
|
87
87
|
rescue StandardError => e
|
|
88
|
-
log_error(
|
|
88
|
+
log_error('provision', e)
|
|
89
89
|
false
|
|
90
90
|
end
|
|
91
91
|
|
|
@@ -94,35 +94,33 @@ module BrainzLab
|
|
|
94
94
|
def request(method, path, headers: {}, body: nil, params: nil, use_service_key: false)
|
|
95
95
|
uri = URI.parse("#{@base_url}#{path}")
|
|
96
96
|
|
|
97
|
-
if params
|
|
98
|
-
uri.query = URI.encode_www_form(params)
|
|
99
|
-
end
|
|
97
|
+
uri.query = URI.encode_www_form(params) if params
|
|
100
98
|
|
|
101
99
|
http = Net::HTTP.new(uri.host, uri.port)
|
|
102
|
-
http.use_ssl = uri.scheme ==
|
|
100
|
+
http.use_ssl = uri.scheme == 'https'
|
|
103
101
|
http.open_timeout = 5
|
|
104
102
|
http.read_timeout = 10
|
|
105
103
|
|
|
106
104
|
request = case method
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
105
|
+
when :get
|
|
106
|
+
Net::HTTP::Get.new(uri)
|
|
107
|
+
when :post
|
|
108
|
+
Net::HTTP::Post.new(uri)
|
|
109
|
+
when :put
|
|
110
|
+
Net::HTTP::Put.new(uri)
|
|
111
|
+
when :delete
|
|
112
|
+
Net::HTTP::Delete.new(uri)
|
|
113
|
+
end
|
|
116
114
|
|
|
117
115
|
# Set headers
|
|
118
|
-
request[
|
|
119
|
-
request[
|
|
116
|
+
request['Content-Type'] = 'application/json'
|
|
117
|
+
request['Accept'] = 'application/json'
|
|
120
118
|
|
|
121
119
|
if use_service_key
|
|
122
|
-
request[
|
|
120
|
+
request['X-Service-Key'] = @config.cortex_master_key || @config.secret_key
|
|
123
121
|
else
|
|
124
122
|
auth_key = @config.cortex_api_key || @config.secret_key
|
|
125
|
-
request[
|
|
123
|
+
request['Authorization'] = "Bearer #{auth_key}" if auth_key
|
|
126
124
|
end
|
|
127
125
|
|
|
128
126
|
headers.each { |k, v| request[k] = v }
|
|
@@ -39,7 +39,7 @@ module BrainzLab
|
|
|
39
39
|
|
|
40
40
|
def detect_project_id
|
|
41
41
|
# Try environment variable first
|
|
42
|
-
return ENV[
|
|
42
|
+
return ENV['BRAINZLAB_PROJECT_ID'] if ENV['BRAINZLAB_PROJECT_ID']
|
|
43
43
|
|
|
44
44
|
# Could also detect from Platform API if we have a secret key
|
|
45
45
|
nil
|
data/lib/brainzlab/cortex.rb
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative
|
|
4
|
-
require_relative
|
|
5
|
-
require_relative
|
|
3
|
+
require_relative 'cortex/client'
|
|
4
|
+
require_relative 'cortex/cache'
|
|
5
|
+
require_relative 'cortex/provisioner'
|
|
6
6
|
|
|
7
7
|
module BrainzLab
|
|
8
8
|
module Cortex
|
|
@@ -19,7 +19,7 @@ module BrainzLab
|
|
|
19
19
|
#
|
|
20
20
|
def enabled?(flag_name, **context)
|
|
21
21
|
result = get(flag_name, **context)
|
|
22
|
-
|
|
22
|
+
[true, 'true'].include?(result)
|
|
23
23
|
end
|
|
24
24
|
|
|
25
25
|
# Check if a feature flag is disabled
|
|
@@ -50,9 +50,7 @@ module BrainzLab
|
|
|
50
50
|
cache_key = build_cache_key(flag_key, merged_context)
|
|
51
51
|
|
|
52
52
|
# Check cache first
|
|
53
|
-
if BrainzLab.configuration.cortex_cache_enabled && cache.has?(cache_key)
|
|
54
|
-
return cache.get(cache_key)
|
|
55
|
-
end
|
|
53
|
+
return cache.get(cache_key) if BrainzLab.configuration.cortex_cache_enabled && cache.has?(cache_key)
|
|
56
54
|
|
|
57
55
|
result = client.evaluate(flag_key, context: merged_context)
|
|
58
56
|
|
|
@@ -194,9 +192,7 @@ module BrainzLab
|
|
|
194
192
|
|
|
195
193
|
# Also include user from BrainzLab context if available
|
|
196
194
|
brainzlab_context = {}
|
|
197
|
-
if BrainzLab::Context.current.user
|
|
198
|
-
brainzlab_context[:user] = BrainzLab::Context.current.user
|
|
199
|
-
end
|
|
195
|
+
brainzlab_context[:user] = BrainzLab::Context.current.user if BrainzLab::Context.current.user
|
|
200
196
|
|
|
201
197
|
# Normalize user context
|
|
202
198
|
merged = default_context.merge(brainzlab_context).merge(thread_context).merge(context)
|
|
@@ -220,7 +216,7 @@ module BrainzLab
|
|
|
220
216
|
|
|
221
217
|
parts = [env, flag_name]
|
|
222
218
|
parts << "u:#{user_id}" if user_id
|
|
223
|
-
parts.join(
|
|
219
|
+
parts.join(':')
|
|
224
220
|
end
|
|
225
221
|
end
|
|
226
222
|
end
|