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
|
@@ -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,
|
|
@@ -140,61 +142,61 @@ module BrainzLab
|
|
|
140
142
|
|
|
141
143
|
# Services that should not track themselves to avoid circular dependencies
|
|
142
144
|
SELF_TRACKING_SERVICES = {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
145
|
+
'recall' => :recall_enabled,
|
|
146
|
+
'reflex' => :reflex_enabled,
|
|
147
|
+
'pulse' => :pulse_enabled,
|
|
148
|
+
'flux' => :flux_enabled,
|
|
149
|
+
'signal' => :signal_enabled
|
|
148
150
|
}.freeze
|
|
149
151
|
|
|
150
152
|
def initialize
|
|
151
153
|
# Authentication
|
|
152
|
-
@secret_key = ENV
|
|
154
|
+
@secret_key = ENV.fetch('BRAINZLAB_SECRET_KEY', nil)
|
|
153
155
|
|
|
154
156
|
# Environment
|
|
155
|
-
@environment = ENV[
|
|
156
|
-
@service = ENV
|
|
157
|
-
@host = ENV[
|
|
157
|
+
@environment = ENV['BRAINZLAB_ENVIRONMENT'] || detect_environment
|
|
158
|
+
@service = ENV.fetch('BRAINZLAB_SERVICE', nil)
|
|
159
|
+
@host = ENV['BRAINZLAB_HOST'] || detect_host
|
|
158
160
|
|
|
159
161
|
# App name for auto-provisioning
|
|
160
|
-
@app_name = ENV
|
|
162
|
+
@app_name = ENV.fetch('BRAINZLAB_APP_NAME', nil)
|
|
161
163
|
|
|
162
164
|
# Git context
|
|
163
|
-
@commit = ENV[
|
|
164
|
-
@branch = ENV[
|
|
165
|
+
@commit = ENV['GIT_COMMIT'] || ENV['COMMIT_SHA'] || detect_git_commit
|
|
166
|
+
@branch = ENV['GIT_BRANCH'] || ENV['BRANCH_NAME'] || detect_git_branch
|
|
165
167
|
|
|
166
168
|
# Debug mode - enables verbose logging
|
|
167
|
-
@debug = ENV[
|
|
169
|
+
@debug = ENV['BRAINZLAB_DEBUG'] == 'true'
|
|
168
170
|
|
|
169
171
|
# Disable self-tracking - prevents services from tracking to themselves
|
|
170
172
|
# e.g., Recall won't log to itself, Reflex won't track errors to itself
|
|
171
|
-
@disable_self_tracking = ENV.fetch(
|
|
173
|
+
@disable_self_tracking = ENV.fetch('BRAINZLAB_DISABLE_SELF_TRACKING', 'true') == 'true'
|
|
172
174
|
|
|
173
175
|
# Recall settings
|
|
174
176
|
@recall_enabled = true
|
|
175
|
-
@recall_url = ENV[
|
|
177
|
+
@recall_url = ENV['RECALL_URL'] || 'https://recall.brainzlab.ai'
|
|
176
178
|
@recall_min_level = :debug
|
|
177
179
|
@recall_buffer_size = 50
|
|
178
180
|
@recall_flush_interval = 5
|
|
179
|
-
@recall_master_key = ENV
|
|
181
|
+
@recall_master_key = ENV.fetch('RECALL_MASTER_KEY', nil)
|
|
180
182
|
@recall_auto_provision = true
|
|
181
183
|
|
|
182
184
|
# Reflex settings
|
|
183
185
|
@reflex_enabled = true
|
|
184
|
-
@reflex_url = ENV[
|
|
185
|
-
@reflex_api_key = ENV
|
|
186
|
-
@reflex_master_key = ENV
|
|
186
|
+
@reflex_url = ENV['REFLEX_URL'] || 'https://reflex.brainzlab.ai'
|
|
187
|
+
@reflex_api_key = ENV.fetch('REFLEX_API_KEY', nil)
|
|
188
|
+
@reflex_master_key = ENV.fetch('REFLEX_MASTER_KEY', nil)
|
|
187
189
|
@reflex_auto_provision = true
|
|
188
190
|
@reflex_excluded_exceptions = []
|
|
189
191
|
@reflex_before_send = nil
|
|
190
192
|
@reflex_sample_rate = nil
|
|
191
|
-
@reflex_fingerprint = nil
|
|
193
|
+
@reflex_fingerprint = nil # Custom fingerprint callback
|
|
192
194
|
|
|
193
195
|
# Pulse settings
|
|
194
196
|
@pulse_enabled = true
|
|
195
|
-
@pulse_url = ENV[
|
|
196
|
-
@pulse_api_key = ENV
|
|
197
|
-
@pulse_master_key = ENV
|
|
197
|
+
@pulse_url = ENV['PULSE_URL'] || 'https://pulse.brainzlab.ai'
|
|
198
|
+
@pulse_api_key = ENV.fetch('PULSE_API_KEY', nil)
|
|
199
|
+
@pulse_master_key = ENV.fetch('PULSE_MASTER_KEY', nil)
|
|
198
200
|
@pulse_auto_provision = true
|
|
199
201
|
@pulse_buffer_size = 50
|
|
200
202
|
@pulse_flush_interval = 5
|
|
@@ -203,86 +205,86 @@ module BrainzLab
|
|
|
203
205
|
|
|
204
206
|
# Flux settings
|
|
205
207
|
@flux_enabled = true
|
|
206
|
-
@flux_url = ENV[
|
|
207
|
-
@flux_api_key = ENV
|
|
208
|
-
@flux_ingest_key = ENV
|
|
209
|
-
@flux_master_key = ENV
|
|
208
|
+
@flux_url = ENV['FLUX_URL'] || 'https://flux.brainzlab.ai'
|
|
209
|
+
@flux_api_key = ENV.fetch('FLUX_API_KEY', nil)
|
|
210
|
+
@flux_ingest_key = ENV.fetch('FLUX_INGEST_KEY', nil)
|
|
211
|
+
@flux_master_key = ENV.fetch('FLUX_MASTER_KEY', nil)
|
|
210
212
|
@flux_auto_provision = true
|
|
211
213
|
@flux_buffer_size = 100
|
|
212
214
|
@flux_flush_interval = 5
|
|
213
215
|
|
|
214
216
|
# Signal settings
|
|
215
217
|
@signal_enabled = true
|
|
216
|
-
@signal_url = ENV[
|
|
217
|
-
@signal_api_key = ENV
|
|
218
|
-
@signal_master_key = ENV
|
|
218
|
+
@signal_url = ENV['SIGNAL_URL'] || 'https://signal.brainzlab.ai'
|
|
219
|
+
@signal_api_key = ENV.fetch('SIGNAL_API_KEY', nil)
|
|
220
|
+
@signal_master_key = ENV.fetch('SIGNAL_MASTER_KEY', nil)
|
|
219
221
|
@signal_auto_provision = true
|
|
220
222
|
|
|
221
223
|
# Vault settings
|
|
222
224
|
@vault_enabled = true
|
|
223
|
-
@vault_url = ENV[
|
|
224
|
-
@vault_api_key = ENV
|
|
225
|
-
@vault_master_key = ENV
|
|
225
|
+
@vault_url = ENV['VAULT_URL'] || 'https://vault.brainzlab.ai'
|
|
226
|
+
@vault_api_key = ENV.fetch('VAULT_API_KEY', nil)
|
|
227
|
+
@vault_master_key = ENV.fetch('VAULT_MASTER_KEY', nil)
|
|
226
228
|
@vault_auto_provision = true
|
|
227
229
|
@vault_cache_enabled = true
|
|
228
|
-
@vault_cache_ttl = 300
|
|
229
|
-
@vault_auto_load = ENV.fetch(
|
|
230
|
-
@vault_load_provider_keys = true
|
|
230
|
+
@vault_cache_ttl = 300 # 5 minutes
|
|
231
|
+
@vault_auto_load = ENV.fetch('VAULT_AUTO_LOAD', 'false') == 'true' # Auto-load secrets into ENV
|
|
232
|
+
@vault_load_provider_keys = true # Also load provider keys (OpenAI, etc.)
|
|
231
233
|
|
|
232
234
|
# Vision settings (AI browser automation)
|
|
233
235
|
@vision_enabled = true
|
|
234
|
-
@vision_url = ENV[
|
|
235
|
-
@vision_api_key = ENV
|
|
236
|
-
@vision_ingest_key = ENV
|
|
237
|
-
@vision_master_key = ENV
|
|
236
|
+
@vision_url = ENV['VISION_URL'] || 'https://vision.brainzlab.ai'
|
|
237
|
+
@vision_api_key = ENV.fetch('VISION_API_KEY', nil)
|
|
238
|
+
@vision_ingest_key = ENV.fetch('VISION_INGEST_KEY', nil)
|
|
239
|
+
@vision_master_key = ENV.fetch('VISION_MASTER_KEY', nil)
|
|
238
240
|
@vision_auto_provision = true
|
|
239
|
-
@vision_default_model = ENV[
|
|
240
|
-
@vision_default_browser_provider = ENV[
|
|
241
|
+
@vision_default_model = ENV['VISION_DEFAULT_MODEL'] || 'claude-sonnet-4'
|
|
242
|
+
@vision_default_browser_provider = ENV['VISION_DEFAULT_BROWSER_PROVIDER'] || 'local'
|
|
241
243
|
|
|
242
244
|
# Cortex settings (feature flags)
|
|
243
245
|
@cortex_enabled = true
|
|
244
|
-
@cortex_url = ENV[
|
|
245
|
-
@cortex_api_key = ENV
|
|
246
|
-
@cortex_master_key = ENV
|
|
246
|
+
@cortex_url = ENV['CORTEX_URL'] || 'https://cortex.brainzlab.ai'
|
|
247
|
+
@cortex_api_key = ENV.fetch('CORTEX_API_KEY', nil)
|
|
248
|
+
@cortex_master_key = ENV.fetch('CORTEX_MASTER_KEY', nil)
|
|
247
249
|
@cortex_auto_provision = true
|
|
248
250
|
@cortex_cache_enabled = true
|
|
249
|
-
@cortex_cache_ttl = 60
|
|
251
|
+
@cortex_cache_ttl = 60 # 1 minute
|
|
250
252
|
@cortex_default_context = {}
|
|
251
253
|
|
|
252
254
|
# Beacon settings (uptime monitoring)
|
|
253
255
|
@beacon_enabled = true
|
|
254
|
-
@beacon_url = ENV[
|
|
255
|
-
@beacon_api_key = ENV
|
|
256
|
-
@beacon_master_key = ENV
|
|
256
|
+
@beacon_url = ENV['BEACON_URL'] || 'https://beacon.brainzlab.ai'
|
|
257
|
+
@beacon_api_key = ENV.fetch('BEACON_API_KEY', nil)
|
|
258
|
+
@beacon_master_key = ENV.fetch('BEACON_MASTER_KEY', nil)
|
|
257
259
|
@beacon_auto_provision = true
|
|
258
260
|
|
|
259
261
|
# Nerve settings (job monitoring)
|
|
260
262
|
@nerve_enabled = true
|
|
261
|
-
@nerve_url = ENV[
|
|
262
|
-
@nerve_api_key = ENV
|
|
263
|
-
@nerve_master_key = ENV
|
|
263
|
+
@nerve_url = ENV['NERVE_URL'] || 'https://nerve.brainzlab.ai'
|
|
264
|
+
@nerve_api_key = ENV.fetch('NERVE_API_KEY', nil)
|
|
265
|
+
@nerve_master_key = ENV.fetch('NERVE_MASTER_KEY', nil)
|
|
264
266
|
@nerve_auto_provision = true
|
|
265
267
|
|
|
266
268
|
# Dendrite settings (AI documentation)
|
|
267
269
|
@dendrite_enabled = true
|
|
268
|
-
@dendrite_url = ENV[
|
|
269
|
-
@dendrite_api_key = ENV
|
|
270
|
-
@dendrite_master_key = ENV
|
|
270
|
+
@dendrite_url = ENV['DENDRITE_URL'] || 'https://dendrite.brainzlab.ai'
|
|
271
|
+
@dendrite_api_key = ENV.fetch('DENDRITE_API_KEY', nil)
|
|
272
|
+
@dendrite_master_key = ENV.fetch('DENDRITE_MASTER_KEY', nil)
|
|
271
273
|
@dendrite_auto_provision = true
|
|
272
274
|
|
|
273
275
|
# Sentinel settings (host monitoring)
|
|
274
276
|
@sentinel_enabled = true
|
|
275
|
-
@sentinel_url = ENV[
|
|
276
|
-
@sentinel_api_key = ENV
|
|
277
|
-
@sentinel_agent_key = ENV
|
|
278
|
-
@sentinel_master_key = ENV
|
|
277
|
+
@sentinel_url = ENV['SENTINEL_URL'] || 'https://sentinel.brainzlab.ai'
|
|
278
|
+
@sentinel_api_key = ENV.fetch('SENTINEL_API_KEY', nil)
|
|
279
|
+
@sentinel_agent_key = ENV.fetch('SENTINEL_AGENT_KEY', nil)
|
|
280
|
+
@sentinel_master_key = ENV.fetch('SENTINEL_MASTER_KEY', nil)
|
|
279
281
|
@sentinel_auto_provision = true
|
|
280
282
|
|
|
281
283
|
# Synapse settings (AI development orchestration)
|
|
282
284
|
@synapse_enabled = true
|
|
283
|
-
@synapse_url = ENV[
|
|
284
|
-
@synapse_api_key = ENV
|
|
285
|
-
@synapse_master_key = ENV
|
|
285
|
+
@synapse_url = ENV['SYNAPSE_URL'] || 'https://synapse.brainzlab.ai'
|
|
286
|
+
@synapse_api_key = ENV.fetch('SYNAPSE_API_KEY', nil)
|
|
287
|
+
@synapse_master_key = ENV.fetch('SYNAPSE_MASTER_KEY', nil)
|
|
286
288
|
@synapse_auto_provision = true
|
|
287
289
|
|
|
288
290
|
# Filtering
|
|
@@ -292,26 +294,26 @@ module BrainzLab
|
|
|
292
294
|
@logger = nil
|
|
293
295
|
|
|
294
296
|
# Instrumentation
|
|
295
|
-
@instrument_http = true
|
|
296
|
-
@instrument_active_record = true
|
|
297
|
-
@instrument_redis = true
|
|
297
|
+
@instrument_http = true # Enable HTTP client instrumentation (Net::HTTP, Faraday, HTTParty)
|
|
298
|
+
@instrument_active_record = true # AR breadcrumbs for Reflex
|
|
299
|
+
@instrument_redis = true # Redis command instrumentation
|
|
298
300
|
@instrument_sidekiq = true # Sidekiq job instrumentation
|
|
299
301
|
@instrument_graphql = true # GraphQL query instrumentation
|
|
300
302
|
@instrument_mongodb = true # MongoDB/Mongoid instrumentation
|
|
301
303
|
@instrument_elasticsearch = true # Elasticsearch instrumentation
|
|
302
304
|
@instrument_action_mailer = true # ActionMailer instrumentation
|
|
303
|
-
@instrument_delayed_job = true
|
|
304
|
-
@instrument_grape = true
|
|
305
|
-
@instrument_solid_queue = true
|
|
306
|
-
@instrument_good_job = true
|
|
307
|
-
@instrument_resque = true
|
|
308
|
-
@instrument_excon = true
|
|
309
|
-
@instrument_typhoeus = true
|
|
310
|
-
@instrument_dalli = true
|
|
311
|
-
@instrument_aws = true
|
|
312
|
-
@instrument_stripe = true
|
|
305
|
+
@instrument_delayed_job = true # Delayed::Job instrumentation
|
|
306
|
+
@instrument_grape = true # Grape API instrumentation
|
|
307
|
+
@instrument_solid_queue = true # Solid Queue job instrumentation
|
|
308
|
+
@instrument_good_job = true # GoodJob instrumentation
|
|
309
|
+
@instrument_resque = true # Resque instrumentation
|
|
310
|
+
@instrument_excon = true # Excon HTTP client instrumentation
|
|
311
|
+
@instrument_typhoeus = true # Typhoeus HTTP client instrumentation
|
|
312
|
+
@instrument_dalli = true # Dalli/Memcached instrumentation
|
|
313
|
+
@instrument_aws = true # AWS SDK instrumentation
|
|
314
|
+
@instrument_stripe = true # Stripe API instrumentation
|
|
313
315
|
@http_ignore_hosts = %w[localhost 127.0.0.1]
|
|
314
|
-
@redis_ignore_commands = %w[ping info]
|
|
316
|
+
@redis_ignore_commands = %w[ping info] # Commands to skip tracking
|
|
315
317
|
|
|
316
318
|
# Log formatter settings
|
|
317
319
|
@log_formatter_enabled = true
|
|
@@ -325,9 +327,9 @@ module BrainzLab
|
|
|
325
327
|
@devtools_error_page_enabled = true
|
|
326
328
|
@devtools_debug_panel_enabled = true
|
|
327
329
|
@devtools_allowed_environments = %w[development test]
|
|
328
|
-
@devtools_allowed_ips = [
|
|
329
|
-
@devtools_asset_path =
|
|
330
|
-
@devtools_panel_position =
|
|
330
|
+
@devtools_allowed_ips = ['127.0.0.1', '::1', '172.16.0.0/12', '192.168.0.0/16', '10.0.0.0/8']
|
|
331
|
+
@devtools_asset_path = '/__brainzlab__'
|
|
332
|
+
@devtools_panel_position = 'bottom-right'
|
|
331
333
|
@devtools_expand_by_default = false
|
|
332
334
|
end
|
|
333
335
|
|
|
@@ -465,7 +467,7 @@ module BrainzLab
|
|
|
465
467
|
|
|
466
468
|
# Disable if this is the Recall service itself
|
|
467
469
|
normalized_app_name = @app_name.to_s.downcase.strip
|
|
468
|
-
normalized_app_name !=
|
|
470
|
+
normalized_app_name != 'recall'
|
|
469
471
|
end
|
|
470
472
|
|
|
471
473
|
# Check if reflex is effectively enabled (considering self-tracking)
|
|
@@ -475,7 +477,7 @@ module BrainzLab
|
|
|
475
477
|
|
|
476
478
|
# Disable if this is the Reflex service itself
|
|
477
479
|
normalized_app_name = @app_name.to_s.downcase.strip
|
|
478
|
-
normalized_app_name !=
|
|
480
|
+
normalized_app_name != 'reflex'
|
|
479
481
|
end
|
|
480
482
|
|
|
481
483
|
# Check if pulse is effectively enabled (considering self-tracking)
|
|
@@ -485,7 +487,7 @@ module BrainzLab
|
|
|
485
487
|
|
|
486
488
|
# Disable if this is the Pulse service itself
|
|
487
489
|
normalized_app_name = @app_name.to_s.downcase.strip
|
|
488
|
-
normalized_app_name !=
|
|
490
|
+
normalized_app_name != 'pulse'
|
|
489
491
|
end
|
|
490
492
|
|
|
491
493
|
# Check if flux is effectively enabled (considering self-tracking)
|
|
@@ -495,7 +497,7 @@ module BrainzLab
|
|
|
495
497
|
|
|
496
498
|
# Disable if this is the Flux service itself
|
|
497
499
|
normalized_app_name = @app_name.to_s.downcase.strip
|
|
498
|
-
normalized_app_name !=
|
|
500
|
+
normalized_app_name != 'flux'
|
|
499
501
|
end
|
|
500
502
|
|
|
501
503
|
# Check if signal is effectively enabled (considering self-tracking)
|
|
@@ -505,7 +507,7 @@ module BrainzLab
|
|
|
505
507
|
|
|
506
508
|
# Disable if this is the Signal service itself
|
|
507
509
|
normalized_app_name = @app_name.to_s.downcase.strip
|
|
508
|
-
normalized_app_name !=
|
|
510
|
+
normalized_app_name != 'signal'
|
|
509
511
|
end
|
|
510
512
|
|
|
511
513
|
def debug_log(message)
|
|
@@ -515,7 +517,7 @@ module BrainzLab
|
|
|
515
517
|
if logger
|
|
516
518
|
logger.debug(log_message)
|
|
517
519
|
else
|
|
518
|
-
|
|
520
|
+
warn(log_message)
|
|
519
521
|
end
|
|
520
522
|
end
|
|
521
523
|
|
|
@@ -523,14 +525,14 @@ module BrainzLab
|
|
|
523
525
|
|
|
524
526
|
def detect_environment
|
|
525
527
|
return ::Rails.env.to_s if defined?(::Rails) && ::Rails.respond_to?(:env)
|
|
526
|
-
return ENV[
|
|
527
|
-
return ENV[
|
|
528
|
+
return ENV['RACK_ENV'] if ENV['RACK_ENV']
|
|
529
|
+
return ENV['RUBY_ENV'] if ENV['RUBY_ENV']
|
|
528
530
|
|
|
529
|
-
|
|
531
|
+
'development'
|
|
530
532
|
end
|
|
531
533
|
|
|
532
534
|
def detect_host
|
|
533
|
-
require
|
|
535
|
+
require 'socket'
|
|
534
536
|
Socket.gethostname
|
|
535
537
|
rescue StandardError
|
|
536
538
|
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
|