fluyenta-ruby 0.1.14

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.
Files changed (121) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +68 -0
  3. data/LICENSE +11 -0
  4. data/README.md +571 -0
  5. data/lib/brainzlab/beacon/client.rb +227 -0
  6. data/lib/brainzlab/beacon/provisioner.rb +44 -0
  7. data/lib/brainzlab/beacon.rb +215 -0
  8. data/lib/brainzlab/configuration.rb +676 -0
  9. data/lib/brainzlab/context.rb +90 -0
  10. data/lib/brainzlab/cortex/cache.rb +59 -0
  11. data/lib/brainzlab/cortex/client.rb +159 -0
  12. data/lib/brainzlab/cortex/provisioner.rb +49 -0
  13. data/lib/brainzlab/cortex.rb +223 -0
  14. data/lib/brainzlab/debug.rb +305 -0
  15. data/lib/brainzlab/dendrite/client.rb +250 -0
  16. data/lib/brainzlab/dendrite/provisioner.rb +44 -0
  17. data/lib/brainzlab/dendrite.rb +195 -0
  18. data/lib/brainzlab/development/logger.rb +150 -0
  19. data/lib/brainzlab/development/store.rb +121 -0
  20. data/lib/brainzlab/development.rb +72 -0
  21. data/lib/brainzlab/devtools/assets/devtools.css +1329 -0
  22. data/lib/brainzlab/devtools/assets/devtools.js +396 -0
  23. data/lib/brainzlab/devtools/assets/logo.svg +6 -0
  24. data/lib/brainzlab/devtools/assets/templates/debug_panel.html.erb +511 -0
  25. data/lib/brainzlab/devtools/assets/templates/error_page.html.erb +1086 -0
  26. data/lib/brainzlab/devtools/data/collector.rb +248 -0
  27. data/lib/brainzlab/devtools/middleware/asset_server.rb +63 -0
  28. data/lib/brainzlab/devtools/middleware/database_handler.rb +177 -0
  29. data/lib/brainzlab/devtools/middleware/debug_panel.rb +126 -0
  30. data/lib/brainzlab/devtools/middleware/error_page.rb +377 -0
  31. data/lib/brainzlab/devtools/renderers/debug_panel_renderer.rb +159 -0
  32. data/lib/brainzlab/devtools/renderers/error_page_renderer.rb +98 -0
  33. data/lib/brainzlab/devtools.rb +75 -0
  34. data/lib/brainzlab/errors.rb +490 -0
  35. data/lib/brainzlab/flux/buffer.rb +96 -0
  36. data/lib/brainzlab/flux/client.rb +68 -0
  37. data/lib/brainzlab/flux/provisioner.rb +124 -0
  38. data/lib/brainzlab/flux.rb +184 -0
  39. data/lib/brainzlab/instrumentation/action_cable.rb +351 -0
  40. data/lib/brainzlab/instrumentation/action_controller.rb +649 -0
  41. data/lib/brainzlab/instrumentation/action_dispatch.rb +259 -0
  42. data/lib/brainzlab/instrumentation/action_mailbox.rb +197 -0
  43. data/lib/brainzlab/instrumentation/action_mailer.rb +182 -0
  44. data/lib/brainzlab/instrumentation/action_view.rb +380 -0
  45. data/lib/brainzlab/instrumentation/active_job.rb +569 -0
  46. data/lib/brainzlab/instrumentation/active_record.rb +559 -0
  47. data/lib/brainzlab/instrumentation/active_storage.rb +541 -0
  48. data/lib/brainzlab/instrumentation/active_support_cache.rb +730 -0
  49. data/lib/brainzlab/instrumentation/aws.rb +183 -0
  50. data/lib/brainzlab/instrumentation/dalli.rb +108 -0
  51. data/lib/brainzlab/instrumentation/delayed_job.rb +234 -0
  52. data/lib/brainzlab/instrumentation/elasticsearch.rb +209 -0
  53. data/lib/brainzlab/instrumentation/excon.rb +152 -0
  54. data/lib/brainzlab/instrumentation/faraday.rb +181 -0
  55. data/lib/brainzlab/instrumentation/good_job.rb +102 -0
  56. data/lib/brainzlab/instrumentation/grape.rb +293 -0
  57. data/lib/brainzlab/instrumentation/graphql.rb +252 -0
  58. data/lib/brainzlab/instrumentation/httparty.rb +193 -0
  59. data/lib/brainzlab/instrumentation/mongodb.rb +187 -0
  60. data/lib/brainzlab/instrumentation/net_http.rb +114 -0
  61. data/lib/brainzlab/instrumentation/rails_deprecation.rb +139 -0
  62. data/lib/brainzlab/instrumentation/railties.rb +134 -0
  63. data/lib/brainzlab/instrumentation/redis.rb +324 -0
  64. data/lib/brainzlab/instrumentation/resque.rb +114 -0
  65. data/lib/brainzlab/instrumentation/sidekiq.rb +265 -0
  66. data/lib/brainzlab/instrumentation/solid_queue.rb +194 -0
  67. data/lib/brainzlab/instrumentation/stripe.rb +163 -0
  68. data/lib/brainzlab/instrumentation/typhoeus.rb +106 -0
  69. data/lib/brainzlab/instrumentation.rb +360 -0
  70. data/lib/brainzlab/nerve/client.rb +235 -0
  71. data/lib/brainzlab/nerve/provisioner.rb +44 -0
  72. data/lib/brainzlab/nerve.rb +219 -0
  73. data/lib/brainzlab/pulse/client.rb +203 -0
  74. data/lib/brainzlab/pulse/instrumentation.rb +401 -0
  75. data/lib/brainzlab/pulse/propagation.rb +241 -0
  76. data/lib/brainzlab/pulse/provisioner.rb +114 -0
  77. data/lib/brainzlab/pulse/tracer.rb +111 -0
  78. data/lib/brainzlab/pulse.rb +294 -0
  79. data/lib/brainzlab/rails/log_formatter.rb +807 -0
  80. data/lib/brainzlab/rails/log_subscriber.rb +334 -0
  81. data/lib/brainzlab/rails/railtie.rb +606 -0
  82. data/lib/brainzlab/recall/buffer.rb +66 -0
  83. data/lib/brainzlab/recall/client.rb +158 -0
  84. data/lib/brainzlab/recall/logger.rb +116 -0
  85. data/lib/brainzlab/recall/provisioner.rb +130 -0
  86. data/lib/brainzlab/recall.rb +175 -0
  87. data/lib/brainzlab/reflex/breadcrumbs.rb +55 -0
  88. data/lib/brainzlab/reflex/client.rb +150 -0
  89. data/lib/brainzlab/reflex/provisioner.rb +116 -0
  90. data/lib/brainzlab/reflex.rb +421 -0
  91. data/lib/brainzlab/sentinel/client.rb +236 -0
  92. data/lib/brainzlab/sentinel/provisioner.rb +44 -0
  93. data/lib/brainzlab/sentinel.rb +165 -0
  94. data/lib/brainzlab/signal/client.rb +60 -0
  95. data/lib/brainzlab/signal/provisioner.rb +115 -0
  96. data/lib/brainzlab/signal.rb +136 -0
  97. data/lib/brainzlab/synapse/client.rb +308 -0
  98. data/lib/brainzlab/synapse/provisioner.rb +44 -0
  99. data/lib/brainzlab/synapse.rb +270 -0
  100. data/lib/brainzlab/testing/event_store.rb +377 -0
  101. data/lib/brainzlab/testing/helpers.rb +650 -0
  102. data/lib/brainzlab/testing/matchers.rb +391 -0
  103. data/lib/brainzlab/testing.rb +327 -0
  104. data/lib/brainzlab/utilities/circuit_breaker.rb +290 -0
  105. data/lib/brainzlab/utilities/health_check.rb +294 -0
  106. data/lib/brainzlab/utilities/log_formatter.rb +254 -0
  107. data/lib/brainzlab/utilities/rate_limiter.rb +230 -0
  108. data/lib/brainzlab/utilities.rb +17 -0
  109. data/lib/brainzlab/vault/cache.rb +80 -0
  110. data/lib/brainzlab/vault/client.rb +216 -0
  111. data/lib/brainzlab/vault/provisioner.rb +49 -0
  112. data/lib/brainzlab/vault.rb +262 -0
  113. data/lib/brainzlab/version.rb +5 -0
  114. data/lib/brainzlab/vision/client.rb +175 -0
  115. data/lib/brainzlab/vision/provisioner.rb +136 -0
  116. data/lib/brainzlab/vision.rb +155 -0
  117. data/lib/brainzlab-sdk.rb +3 -0
  118. data/lib/brainzlab.rb +306 -0
  119. data/lib/generators/brainzlab/install/install_generator.rb +63 -0
  120. data/lib/generators/brainzlab/install/templates/brainzlab.rb.tt +77 -0
  121. metadata +251 -0
@@ -0,0 +1,155 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'vision/client'
4
+ require_relative 'vision/provisioner'
5
+
6
+ module BrainzLab
7
+ module Vision
8
+ class << self
9
+ # Execute an autonomous AI task
10
+ # @param instruction [String] Natural language instruction for the AI
11
+ # @param start_url [String] URL to start from
12
+ # @param model [String] LLM model to use (default: claude-sonnet-4)
13
+ # @param browser_provider [String] Browser provider (default: local)
14
+ # @param max_steps [Integer] Maximum steps to execute (default: 50)
15
+ # @param timeout [Integer] Timeout in seconds (default: 300)
16
+ # @return [Hash] Task result with extracted data
17
+ def execute_task(instruction:, start_url:, model: nil, browser_provider: nil, max_steps: 50, timeout: 300)
18
+ config = BrainzLab.configuration
19
+ return { error: 'Vision is not enabled' } unless config.vision_enabled
20
+
21
+ ensure_provisioned!
22
+ return { error: 'Vision credentials not configured' } unless config.vision_valid?
23
+
24
+ client.execute_task(
25
+ instruction: instruction,
26
+ start_url: start_url,
27
+ model: model,
28
+ browser_provider: browser_provider,
29
+ max_steps: max_steps,
30
+ timeout: timeout
31
+ )
32
+ end
33
+
34
+ # Create a browser session
35
+ # @param url [String] Optional initial URL
36
+ # @param viewport [Hash] Viewport dimensions { width:, height: }
37
+ # @param browser_provider [String] Browser provider to use
38
+ # @return [Hash] Session info with session_id
39
+ def create_session(url: nil, viewport: nil, browser_provider: nil)
40
+ config = BrainzLab.configuration
41
+ return { error: 'Vision is not enabled' } unless config.vision_enabled
42
+
43
+ ensure_provisioned!
44
+ return { error: 'Vision credentials not configured' } unless config.vision_valid?
45
+
46
+ client.create_session(
47
+ url: url,
48
+ viewport: viewport,
49
+ browser_provider: browser_provider
50
+ )
51
+ end
52
+
53
+ # Perform an AI-powered action in a session
54
+ # @param session_id [String] Session ID
55
+ # @param instruction [String] Natural language instruction
56
+ # @param model [String] LLM model to use
57
+ # @return [Hash] Action result
58
+ def ai_action(session_id:, instruction:, model: nil)
59
+ config = BrainzLab.configuration
60
+ return { error: 'Vision is not enabled' } unless config.vision_enabled
61
+ return { error: 'Vision credentials not configured' } unless config.vision_valid?
62
+
63
+ client.ai_action(
64
+ session_id: session_id,
65
+ instruction: instruction,
66
+ model: model
67
+ )
68
+ end
69
+
70
+ # Perform a direct browser action
71
+ # @param session_id [String] Session ID
72
+ # @param action [Symbol] Action type (:click, :type, :scroll, etc.)
73
+ # @param selector [String] Element selector
74
+ # @param value [String] Value for type/fill actions
75
+ # @return [Hash] Action result
76
+ def perform(session_id:, action:, selector: nil, value: nil)
77
+ config = BrainzLab.configuration
78
+ return { error: 'Vision is not enabled' } unless config.vision_enabled
79
+ return { error: 'Vision credentials not configured' } unless config.vision_valid?
80
+
81
+ client.perform(
82
+ session_id: session_id,
83
+ action: action,
84
+ selector: selector,
85
+ value: value
86
+ )
87
+ end
88
+
89
+ # Extract structured data from the page
90
+ # @param session_id [String] Session ID
91
+ # @param schema [Hash] JSON schema for extraction
92
+ # @param instruction [String] Optional instruction for extraction
93
+ # @return [Hash] Extracted data
94
+ def extract(session_id:, schema:, instruction: nil)
95
+ config = BrainzLab.configuration
96
+ return { error: 'Vision is not enabled' } unless config.vision_enabled
97
+ return { error: 'Vision credentials not configured' } unless config.vision_valid?
98
+
99
+ client.extract(
100
+ session_id: session_id,
101
+ schema: schema,
102
+ instruction: instruction
103
+ )
104
+ end
105
+
106
+ # Close a browser session
107
+ # @param session_id [String] Session ID
108
+ # @return [Hash] Close result
109
+ def close_session(session_id:)
110
+ config = BrainzLab.configuration
111
+ return { error: 'Vision is not enabled' } unless config.vision_enabled
112
+ return { error: 'Vision credentials not configured' } unless config.vision_valid?
113
+
114
+ client.close_session(session_id: session_id)
115
+ end
116
+
117
+ # Take a screenshot
118
+ # @param session_id [String] Session ID
119
+ # @param full_page [Boolean] Capture full page (default: true)
120
+ # @return [Hash] Screenshot data
121
+ def screenshot(session_id:, full_page: true)
122
+ config = BrainzLab.configuration
123
+ return { error: 'Vision is not enabled' } unless config.vision_enabled
124
+ return { error: 'Vision credentials not configured' } unless config.vision_valid?
125
+
126
+ client.screenshot(session_id: session_id, full_page: full_page)
127
+ end
128
+
129
+ # Ensure project is auto-provisioned
130
+ def ensure_provisioned!
131
+ config = BrainzLab.configuration
132
+ puts "[BrainzLab::Debug] Vision.ensure_provisioned! called, @provisioned=#{@provisioned}" if config.debug
133
+
134
+ return if @provisioned
135
+
136
+ @provisioned = true
137
+ provisioner.ensure_project!
138
+ end
139
+
140
+ def provisioner
141
+ @provisioner ||= Provisioner.new(BrainzLab.configuration)
142
+ end
143
+
144
+ def client
145
+ @client ||= Client.new(BrainzLab.configuration)
146
+ end
147
+
148
+ def reset!
149
+ @client = nil
150
+ @provisioner = nil
151
+ @provisioned = false
152
+ end
153
+ end
154
+ end
155
+ end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'brainzlab'
data/lib/brainzlab.rb ADDED
@@ -0,0 +1,306 @@
1
+ # frozen_string_literal: true
2
+
3
+ # BrainzLab SDK - Official Ruby SDK for BrainzLab products
4
+ #
5
+ # For testing utilities, require 'brainzlab/testing' in your test helper:
6
+ #
7
+ # require 'brainzlab/testing'
8
+ #
9
+ # RSpec.configure do |config|
10
+ # config.include BrainzLab::Testing::Helpers
11
+ # end
12
+ #
13
+ # See BrainzLab::Testing for more details.
14
+
15
+ require_relative 'brainzlab/version'
16
+ require_relative 'brainzlab/errors'
17
+ require_relative 'brainzlab/configuration'
18
+ require_relative 'brainzlab/debug'
19
+ require_relative 'brainzlab/context'
20
+ require_relative 'brainzlab/recall'
21
+ require_relative 'brainzlab/reflex'
22
+ require_relative 'brainzlab/pulse'
23
+ require_relative 'brainzlab/flux'
24
+ require_relative 'brainzlab/signal'
25
+ require_relative 'brainzlab/vault'
26
+ require_relative 'brainzlab/vision'
27
+ require_relative 'brainzlab/cortex'
28
+ require_relative 'brainzlab/beacon'
29
+ require_relative 'brainzlab/nerve'
30
+ require_relative 'brainzlab/dendrite'
31
+ require_relative 'brainzlab/sentinel'
32
+ require_relative 'brainzlab/synapse'
33
+ require_relative 'brainzlab/instrumentation'
34
+ require_relative 'brainzlab/utilities'
35
+ require_relative 'brainzlab/development'
36
+
37
+ module BrainzLab
38
+ # Thread-local re-entrancy guard for instrumentation.
39
+ # When true, SDK operations that would make HTTP calls are skipped
40
+ # to prevent recursive instrumentation from blocking the host app.
41
+ INSTRUMENTING_KEY = :brainzlab_instrumenting
42
+
43
+ class << self
44
+ # Returns true when inside an instrumentation handler.
45
+ # Used by Recall.log, Pulse.record_metric, etc. to skip HTTP calls
46
+ # that would block the host app during notification callbacks.
47
+ def instrumenting?
48
+ Thread.current[INSTRUMENTING_KEY] == true
49
+ end
50
+
51
+ # Executes a block within the instrumentation guard.
52
+ # Prevents recursive/cascading SDK HTTP calls from instrumentation handlers.
53
+ def with_instrumentation_guard
54
+ return if Thread.current[INSTRUMENTING_KEY]
55
+
56
+ Thread.current[INSTRUMENTING_KEY] = true
57
+ begin
58
+ yield
59
+ ensure
60
+ Thread.current[INSTRUMENTING_KEY] = nil
61
+ end
62
+ end
63
+
64
+ def configure
65
+ yield(configuration) if block_given?
66
+ configuration
67
+ end
68
+
69
+ def configuration
70
+ @configuration ||= Configuration.new
71
+ end
72
+
73
+ def reset_configuration!
74
+ @configuration = Configuration.new
75
+ Recall.reset!
76
+ Reflex.reset!
77
+ Pulse.reset!
78
+ Flux.reset!
79
+ Signal.reset!
80
+ Vault.reset!
81
+ Vision.reset!
82
+ Cortex.reset!
83
+ Beacon.reset!
84
+ Nerve.reset!
85
+ Dendrite.reset!
86
+ Sentinel.reset!
87
+ Synapse.reset!
88
+ Development.reset!
89
+ end
90
+
91
+ # Context management
92
+ def set_user(id: nil, email: nil, name: nil, **extra)
93
+ Context.current.set_user(id: id, email: email, name: name, **extra)
94
+ end
95
+
96
+ def set_context(**data)
97
+ Context.current.set_context(**data)
98
+ end
99
+
100
+ def set_tags(**data)
101
+ Context.current.set_tags(**data)
102
+ end
103
+
104
+ def with_context(**data, &)
105
+ Context.current.with_context(**data, &)
106
+ end
107
+
108
+ def clear_context!
109
+ Context.clear!
110
+ end
111
+
112
+ # Breadcrumb helpers
113
+ def add_breadcrumb(message, category: 'default', level: :info, data: nil)
114
+ Reflex.add_breadcrumb(message, category: category, level: level, data: data)
115
+ end
116
+
117
+ def clear_breadcrumbs!
118
+ Reflex.clear_breadcrumbs!
119
+ end
120
+
121
+ # Create a logger that can replace Rails.logger
122
+ # @param broadcast_to [Logger] Optional logger to also send logs to (e.g., original Rails.logger)
123
+ # @return [BrainzLab::Recall::Logger]
124
+ def logger(broadcast_to: nil)
125
+ Recall::Logger.new(nil, broadcast_to: broadcast_to)
126
+ end
127
+
128
+ # Debug logging helper
129
+ def debug_log(message)
130
+ configuration.debug_log(message)
131
+ end
132
+
133
+ # Check if debug mode is enabled
134
+ def debug?
135
+ configuration.debug?
136
+ end
137
+
138
+ # Query events stored in development mode
139
+ # @param service [Symbol, nil] filter by service (:recall, :reflex, :pulse, etc.)
140
+ # @param event_type [String, nil] filter by event type ('log', 'error', 'trace', etc.)
141
+ # @param since [Time, nil] filter events after this time
142
+ # @param limit [Integer] max number of events to return (default: 100)
143
+ # @return [Array<Hash>] matching events
144
+ # @example
145
+ # BrainzLab.development_events # All events
146
+ # BrainzLab.development_events(service: :recall) # Only Recall logs
147
+ # BrainzLab.development_events(service: :reflex, limit: 10) # Last 10 errors
148
+ # BrainzLab.development_events(since: 1.hour.ago) # Events from last hour
149
+ def development_events(service: nil, event_type: nil, since: nil, limit: 100)
150
+ Development.events(service: service, event_type: event_type, since: since, limit: limit)
151
+ end
152
+
153
+ # Clear all events stored in development mode
154
+ def clear_development_events!
155
+ Development.clear!
156
+ end
157
+
158
+ # Get stats about stored development events
159
+ # @return [Hash] counts by service
160
+ def development_stats
161
+ Development.stats
162
+ end
163
+
164
+ # Health check - verifies connectivity to all enabled services
165
+ # @return [Hash] Status of each service
166
+ def health_check
167
+ results = { status: 'ok', services: {} }
168
+
169
+ # Check Recall
170
+ if configuration.recall_enabled
171
+ results[:services][:recall] = check_service_health(
172
+ url: configuration.recall_url,
173
+ name: 'Recall'
174
+ )
175
+ end
176
+
177
+ # Check Reflex
178
+ if configuration.reflex_enabled
179
+ results[:services][:reflex] = check_service_health(
180
+ url: configuration.reflex_url,
181
+ name: 'Reflex'
182
+ )
183
+ end
184
+
185
+ # Check Pulse
186
+ if configuration.pulse_enabled
187
+ results[:services][:pulse] = check_service_health(
188
+ url: configuration.pulse_url,
189
+ name: 'Pulse'
190
+ )
191
+ end
192
+
193
+ # Check Flux
194
+ if configuration.flux_enabled
195
+ results[:services][:flux] = check_service_health(
196
+ url: configuration.flux_url,
197
+ name: 'Flux'
198
+ )
199
+ end
200
+
201
+ # Check Signal
202
+ if configuration.signal_enabled
203
+ results[:services][:signal] = check_service_health(
204
+ url: configuration.signal_url,
205
+ name: 'Signal'
206
+ )
207
+ end
208
+
209
+ # Check Vault
210
+ if configuration.vault_enabled
211
+ results[:services][:vault] = check_service_health(
212
+ url: configuration.vault_url,
213
+ name: 'Vault'
214
+ )
215
+ end
216
+
217
+ # Check Vision
218
+ if configuration.vision_enabled
219
+ results[:services][:vision] = check_service_health(
220
+ url: configuration.vision_url,
221
+ name: 'Vision'
222
+ )
223
+ end
224
+
225
+ # Check Cortex
226
+ if configuration.cortex_enabled
227
+ results[:services][:cortex] = check_service_health(
228
+ url: configuration.cortex_url,
229
+ name: 'Cortex'
230
+ )
231
+ end
232
+
233
+ # Check Beacon
234
+ if configuration.beacon_enabled
235
+ results[:services][:beacon] = check_service_health(
236
+ url: configuration.beacon_url,
237
+ name: 'Beacon'
238
+ )
239
+ end
240
+
241
+ # Check Nerve
242
+ if configuration.nerve_enabled
243
+ results[:services][:nerve] = check_service_health(
244
+ url: configuration.nerve_url,
245
+ name: 'Nerve'
246
+ )
247
+ end
248
+
249
+ # Check Dendrite
250
+ if configuration.dendrite_enabled
251
+ results[:services][:dendrite] = check_service_health(
252
+ url: configuration.dendrite_url,
253
+ name: 'Dendrite'
254
+ )
255
+ end
256
+
257
+ # Check Sentinel
258
+ if configuration.sentinel_enabled
259
+ results[:services][:sentinel] = check_service_health(
260
+ url: configuration.sentinel_url,
261
+ name: 'Sentinel'
262
+ )
263
+ end
264
+
265
+ # Check Synapse
266
+ if configuration.synapse_enabled
267
+ results[:services][:synapse] = check_service_health(
268
+ url: configuration.synapse_url,
269
+ name: 'Synapse'
270
+ )
271
+ end
272
+
273
+ # Overall status
274
+ has_failure = results[:services].values.any? { |s| s[:status] == 'error' }
275
+ results[:status] = has_failure ? 'degraded' : 'ok'
276
+
277
+ results
278
+ end
279
+
280
+ private
281
+
282
+ def check_service_health(url:, name:)
283
+ require 'net/http'
284
+ require 'uri'
285
+
286
+ uri = URI.parse("#{url}/up")
287
+ http = Net::HTTP.new(uri.host, uri.port)
288
+ http.use_ssl = uri.scheme == 'https'
289
+ http.open_timeout = 5
290
+ http.read_timeout = 5
291
+
292
+ response = http.get(uri.request_uri)
293
+
294
+ if response.is_a?(Net::HTTPSuccess)
295
+ { status: 'ok', latency_ms: 0 }
296
+ else
297
+ { status: 'error', message: "HTTP #{response.code}" }
298
+ end
299
+ rescue StandardError => e
300
+ { status: 'error', message: e.message }
301
+ end
302
+ end
303
+ end
304
+
305
+ # Auto-load Rails integration if Rails is available
306
+ require_relative 'brainzlab/rails/railtie' if defined?(Rails::Railtie)
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails/generators/base'
4
+
5
+ module Brainzlab
6
+ module Generators
7
+ class InstallGenerator < Rails::Generators::Base
8
+ source_root File.expand_path('templates', __dir__)
9
+
10
+ desc 'Creates a BrainzLab initializer for your Rails application'
11
+
12
+ class_option :key, type: :string, desc: 'Your BrainzLab secret key'
13
+ class_option :replace_logger, type: :boolean, default: false, desc: 'Replace Rails.logger with BrainzLab logger'
14
+
15
+ def copy_initializer
16
+ template 'brainzlab.rb.tt', 'config/initializers/brainzlab.rb'
17
+ end
18
+
19
+ def show_post_install_message
20
+ say ''
21
+ say 'BrainzLab SDK installed successfully!', :green
22
+ say ''
23
+ say 'Next steps:'
24
+ say ' 1. Set your environment variables:'
25
+ say ' BRAINZLAB_SECRET_KEY - Your API key from https://brainzlab.ai/dashboard'
26
+ say ''
27
+ say ' Or for auto-provisioning:'
28
+ say ' RECALL_MASTER_KEY - Master key for Recall auto-provisioning'
29
+ say ' REFLEX_MASTER_KEY - Master key for Reflex auto-provisioning'
30
+ say ''
31
+ say ' 2. Start logging:'
32
+ say " BrainzLab::Recall.info('Hello from BrainzLab!')"
33
+ say ''
34
+ say ' 3. Capture errors (automatic with Rails, or manual):'
35
+ say ' BrainzLab::Reflex.capture(exception)'
36
+ say ''
37
+ if options[:replace_logger]
38
+ say ' Rails.logger is now connected to Recall!', :yellow
39
+ else
40
+ say ' To send all Rails logs to Recall, add to your initializer:'
41
+ say ' Rails.logger = BrainzLab.logger(broadcast_to: Rails.logger)'
42
+ end
43
+ say ''
44
+ end
45
+
46
+ private
47
+
48
+ def secret_key_value
49
+ if options[:key].present?
50
+ %("#{options[:key]}")
51
+ else
52
+ 'ENV["BRAINZLAB_SECRET_KEY"]'
53
+ end
54
+ end
55
+
56
+ def app_name
57
+ Rails.application.class.module_parent_name.underscore
58
+ rescue StandardError
59
+ 'my-app'
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ BrainzLab.configure do |config|
4
+ # Your secret key from https://brainzlab.ai/dashboard
5
+ # If using auto-provisioning, you can omit this and set master keys instead
6
+ config.secret_key = <%= secret_key_value %>
7
+
8
+ # App name for auto-provisioning (required for auto-provision)
9
+ config.app_name = "<%= app_name %>"
10
+
11
+ # Environment (defaults to Rails.env)
12
+ # config.environment = Rails.env
13
+
14
+ # Service name (defaults to app name)
15
+ config.service = "<%= app_name %>"
16
+
17
+ # ============================================================================
18
+ # Recall - Logging
19
+ # ============================================================================
20
+
21
+ # Enable/disable Recall logging
22
+ # config.recall_enabled = true
23
+
24
+ # Recall URL (defaults to https://recall.brainzlab.ai)
25
+ # config.recall_url = ENV.fetch("RECALL_URL", "https://recall.brainzlab.ai")
26
+
27
+ # Master key for auto-provisioning (set in environment)
28
+ # config.recall_master_key = ENV["RECALL_MASTER_KEY"]
29
+
30
+ # Minimum log level to send to Recall
31
+ # config.recall_min_level = :debug # :debug, :info, :warn, :error, :fatal
32
+
33
+ # Buffer settings for batching logs
34
+ # config.recall_buffer_size = 50 # Flush after 50 logs
35
+ # config.recall_flush_interval = 5 # Or every 5 seconds
36
+
37
+ # ============================================================================
38
+ # Reflex - Error Tracking
39
+ # ============================================================================
40
+
41
+ # Enable/disable Reflex error tracking
42
+ # config.reflex_enabled = true
43
+
44
+ # Reflex URL (defaults to https://reflex.brainzlab.ai)
45
+ # config.reflex_url = ENV.fetch("REFLEX_URL", "https://reflex.brainzlab.ai")
46
+
47
+ # Master key for auto-provisioning (set in environment)
48
+ # config.reflex_master_key = ENV["REFLEX_MASTER_KEY"]
49
+
50
+ # Exceptions to exclude from Reflex error tracking
51
+ # config.reflex_excluded_exceptions = [
52
+ # "ActionController::RoutingError",
53
+ # "ActionController::InvalidAuthenticityToken",
54
+ # "ActiveRecord::RecordNotFound"
55
+ # ]
56
+
57
+ # Sample rate for errors (1.0 = 100%, 0.5 = 50%)
58
+ # config.reflex_sample_rate = 1.0
59
+
60
+ # Before send hook to modify or filter errors
61
+ # config.reflex_before_send = ->(payload, exception) {
62
+ # # Return nil to drop the error, or modify and return payload
63
+ # payload
64
+ # }
65
+
66
+ # ============================================================================
67
+ # General
68
+ # ============================================================================
69
+
70
+ # Fields to scrub from logs and errors
71
+ # config.scrub_fields = %i[password password_confirmation token api_key secret credit_card]
72
+ end
73
+ <% if options[:replace_logger] %>
74
+
75
+ # Send all Rails logs to Recall (keeps console output too)
76
+ Rails.logger = BrainzLab.logger(broadcast_to: Rails.logger)
77
+ <% end %>