lapsoss 0.1.0

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.
data/README.md ADDED
@@ -0,0 +1,855 @@
1
+ # Lapsoss 🧬
2
+
3
+ **Adaptive Trait Selection for Error Tracking**
4
+
5
+ Lapsoss is a vendor-neutral error tracking library for Ruby that applies the principle of "Adaptive Trait Selection" - intelligently selecting the best features from each error tracking ecosystem to create a superior, unified solution.
6
+
7
+ ## Philosophy
8
+
9
+ Lapsoss is built on the principle of absolute vendor neutrality and control. Unlike traditional error tracking libraries that often bundle proprietary SDKs, Lapsoss provides a pure Ruby implementation for error reporting. This ensures:
10
+
11
+ - **No External SDK Dependencies**: Lapsoss handles payload construction and transport directly, eliminating the need for any third-party error tracking gems.
12
+ - **Zero Monkey-Patching**: Your application's core behavior remains untouched.
13
+ - **Complete Control**: You dictate how errors are processed and sent, without hidden telemetry or unwanted features.
14
+ - **True Vendor Agnosticism**: Switch or combine error tracking services seamlessly, without changing your application's code.
15
+
16
+ ## Rails-First Architecture
17
+
18
+ Lapsoss is designed **primarily for Rails applications** and modern Ruby projects. This architectural choice provides clear benefits:
19
+
20
+ ### Why ActiveSupport?
21
+
22
+ Lapsoss depends on ActiveSupport (Rails 7.2+) as a deliberate design decision:
23
+
24
+ - **Rails Integration**: Seamless integration with Rails' parameter filtering, configuration patterns, and error reporting API
25
+ - **Essential Utilities**: ActiveSupport provides utilities we need anyway: `concurrent-ruby`, `zeitwerk`, inflection, configuration handling
26
+ - **No Namespace Pollution**: Unlike vendor SDKs that bring Redis, Elasticsearch, and other external namespaces, ActiveSupport provides clean Ruby utilities
27
+ - **Your Choice**: Use Lapsoss with ActiveSupport, or use official vendor SDKs that monkey-patch your entire application
28
+
29
+ ### The Real Bloat Problem
30
+
31
+ The issue isn't dependency count - it's **namespace pollution** and **monkey-patching**:
32
+
33
+ - **Vendor SDKs**: Force Redis, Elasticsearch, proprietary gems, and monkey-patch core Ruby classes
34
+ - **Lapsoss + ActiveSupport**: Clean utilities that enhance Ruby without breaking your application's behavior
35
+
36
+ ### Ruby Implementation Support
37
+
38
+ Lapsoss is built and tested exclusively for **CRuby (MRI) 3.2+**. Other Ruby implementations (JRuby, TruffleRuby) are not supported. This focused approach allows us to:
39
+
40
+ - Optimize for the most common Ruby implementation
41
+ - Avoid complexity of cross-implementation compatibility
42
+ - Provide reliable backtrace processing and code context extraction
43
+
44
+ ### Rails Version Support
45
+
46
+ Lapsoss targets **Rails 7.2+** applications. If you're running an older Rails version, upgrade first. We follow Rails' release support policy and focus on modern Rails applications.
47
+
48
+ ### What Lapsoss Is (and Isn't)
49
+
50
+ **Lapsoss is not a full replacement for vendor SDKs.** It focuses on core error tracking functionality, providing a Rails-optimized alternative for teams that:
51
+
52
+ - Want clean, vendor-neutral error reporting without external namespace pollution
53
+ - Need to use multiple error tracking services simultaneously
54
+ - Are tired of vendor SDKs that monkey-patch core Ruby classes
55
+ - Want to avoid the complexity of legacy support and premium features you don't use
56
+
57
+ **What's included:**
58
+ - ✅ Exception and error message capture
59
+ - ✅ Contextual data (user, tags, extra data)
60
+ - ✅ Breadcrumbs and error grouping
61
+ - ✅ Deploy markers and release tracking
62
+ - ✅ Basic health checks/heartbeats
63
+ - ✅ **Custom fingerprinting for intelligent error grouping**
64
+ - ✅ **Automatic data scrubbing with Rails parameter filtering**
65
+ - ✅ **Transport reliability with retry logic and client-side rate limiting**
66
+ - ✅ **Configuration validation for all adapter settings**
67
+ - ✅ **Advanced backtrace processing with code context extraction**
68
+ - ✅ **Intelligent frame filtering and normalization**
69
+ - ✅ **Performance-optimized file caching for backtrace processing**
70
+
71
+ **What's NOT included:**
72
+ - ❌ Application Performance Monitoring (APM)
73
+ - ❌ Distributed tracing
74
+ - ❌ Host metrics and system monitoring
75
+ - ❌ Advanced profiling
76
+ - ❌ Database query analysis
77
+
78
+ Most vendor SDKs contain significant boilerplate to support legacy Ruby versions, deprecated features, and premium functionality that requires additional subscriptions. Lapsoss strips away this complexity, focusing on what most applications actually need: reliable error tracking.
79
+
80
+ > 📖 **Want the full story?** Read [STORY.md](STORY.md) for detailed research on SDK bloat, including actual gem sizes and feature creep analysis across 25+ releases of major error tracking libraries.
81
+
82
+ ## Core Principles (COSS-Compliant)
83
+
84
+ Lapsoss adheres strictly to the [Contriboss (COSS) standard](https://www.contriboss.com), ensuring software neutrality and freedom from vendor lock-in.
85
+
86
+ - 🔓 **Absolute Vendor Neutrality**: Lapsoss provides its own pure Ruby implementations for error reporting, eliminating the need for any external vendor SDKs.
87
+ - 🔌 **Pluggable Adapters**: Configure and use one or multiple built-in or custom adapters simultaneously.
88
+ - 🚀 **Rails 7.2+ Native Integration**: Seamlessly integrates with Rails' native error reporting API, without any monkey-patching.
89
+ - 🧬 **Adaptive Trait Selection**: I've carefully selected and implemented the most valuable error reporting features directly within Lapsoss, providing a unified, best-of-breed solution.
90
+
91
+ ## Installation
92
+
93
+ ```ruby
94
+ gem 'lapsoss'
95
+ ```
96
+
97
+ ## Quick Start
98
+
99
+ Lapsoss currently provides 4 built-in adapters:
100
+ - **Sentry** - Full error tracking support with pure Ruby implementation
101
+ - **AppSignal** - Error tracking, deploy markers, and check-ins support (messages limited to :error, :fatal, :critical levels)
102
+ - **Rollbar** - Complete error tracking with grouping and person tracking
103
+ - **Insight Hub** (formerly Bugsnag) - Error tracking with breadcrumbs and session support
104
+
105
+ All adapters are pure Ruby implementations with no external SDK dependencies or monkey-patching. Additional adapters can be easily added by the community or vendors.
106
+
107
+ ### Single Adapter (Simple Mode)
108
+ ```ruby
109
+ # config/initializers/lapsoss.rb
110
+ Lapsoss.configure do |config|
111
+ # Configure the built-in Sentry adapter
112
+ config.use_sentry(dsn: ENV["SENTRY_DSN"])
113
+ end
114
+ ```
115
+
116
+ ### Multi-Adapter (Advanced Mode)
117
+ ```ruby
118
+ # config/initializers/lapsoss.rb
119
+ Lapsoss.configure do |config|
120
+ # Run multiple built-in adapters simultaneously!
121
+ config.use_sentry(name: :sentry_us, dsn: ENV['SENTRY_US_DSN'])
122
+ config.use_sentry(name: :sentry_eu, dsn: ENV['SENTRY_EU_DSN'])
123
+ config.use_appsignal(name: :appsignal, api_key: ENV['APPSIGNAL_API_KEY'])
124
+ config.use_rollbar(name: :rollbar, access_token: ENV['ROLLBAR_ACCESS_TOKEN'])
125
+ config.use_insight_hub(name: :insight_hub, api_key: ENV['INSIGHT_HUB_API_KEY'])
126
+ config.use_logger(name: :local_backup) # Example: log errors to a local file
127
+ end
128
+
129
+ # For Rails applications, errors are automatically captured via the Rails error reporting API.
130
+ # For other Ruby applications, use Lapsoss.capture_exception or Lapsoss.capture_message.
131
+ ```
132
+
133
+ ## Usage
134
+
135
+ ### Core API
136
+
137
+ Lapsoss provides a simple, intuitive API for error tracking:
138
+
139
+ ```ruby
140
+ # Capture exceptions
141
+ Lapsoss.capture_exception(exception, **context)
142
+
143
+ # Capture messages
144
+ Lapsoss.capture_message(message, level: :info, **context)
145
+
146
+ # Add breadcrumbs for debugging context
147
+ Lapsoss.add_breadcrumb(message, type: :default, **metadata)
148
+
149
+ # Work with scoped context
150
+ Lapsoss.with_scope(context = {}, &block)
151
+ Lapsoss.current_scope
152
+ ```
153
+
154
+ ### Rails Integration
155
+
156
+ For Rails applications, errors are automatically captured:
157
+
158
+ ```ruby
159
+ # config/initializers/lapsoss.rb
160
+ Lapsoss.configure do |config|
161
+ config.use_sentry(dsn: ENV["SENTRY_DSN"])
162
+ end
163
+
164
+ # That's it! All unhandled exceptions are automatically captured
165
+ # No need to modify your controllers or models
166
+ ```
167
+
168
+ ### Manual Error Capture
169
+
170
+ For non-Rails applications or custom error handling:
171
+
172
+ ```ruby
173
+ # Basic exception capture
174
+ begin
175
+ risky_operation
176
+ rescue => e
177
+ Lapsoss.capture_exception(e)
178
+ end
179
+
180
+ # With additional context
181
+ begin
182
+ process_payment(user, amount)
183
+ rescue PaymentError => e
184
+ Lapsoss.capture_exception(e,
185
+ user: { id: user.id, email: user.email },
186
+ tags: { payment_method: "credit_card", amount: amount },
187
+ extra: { order_id: order.id, retry_count: 3 }
188
+ )
189
+ end
190
+ ```
191
+
192
+ ### Message Logging
193
+
194
+ For important events or custom alerts:
195
+
196
+ ```ruby
197
+ # Simple message
198
+ Lapsoss.capture_message("Payment processing started", level: :info)
199
+
200
+ # With context
201
+ Lapsoss.capture_message("High CPU usage detected",
202
+ level: :warning,
203
+ tags: { server: "web-01", cpu_usage: "85%" },
204
+ extra: { pid: Process.pid, memory_usage: "2.1GB" }
205
+ )
206
+ ```
207
+
208
+ ### Breadcrumbs for Debugging
209
+
210
+ Track user actions and system events leading up to errors:
211
+
212
+ ```ruby
213
+ # User actions
214
+ Lapsoss.add_breadcrumb("User logged in",
215
+ type: :user,
216
+ user_id: user.id,
217
+ ip: request.remote_ip
218
+ )
219
+
220
+ # System events
221
+ Lapsoss.add_breadcrumb("Database connection established",
222
+ type: :system,
223
+ host: "db-primary",
224
+ latency: "45ms"
225
+ )
226
+
227
+ # Navigation
228
+ Lapsoss.add_breadcrumb("User visited checkout",
229
+ type: :navigation,
230
+ url: "/checkout",
231
+ referrer: "/cart"
232
+ )
233
+
234
+ # When an error occurs, all breadcrumbs are included automatically
235
+ begin
236
+ complete_checkout
237
+ rescue => e
238
+ Lapsoss.capture_exception(e) # Includes all breadcrumbs above
239
+ end
240
+ ```
241
+
242
+ ### Scoped Context
243
+
244
+ Use scoped context to apply data to multiple operations:
245
+
246
+ ```ruby
247
+ # Request-scoped context
248
+ Lapsoss.with_scope(
249
+ user: { id: current_user.id, email: current_user.email },
250
+ tags: { request_id: request.id, controller: "checkout" }
251
+ ) do
252
+
253
+ # Any errors in this block will include the scope context
254
+ process_payment
255
+ update_inventory
256
+ send_confirmation_email
257
+
258
+ end
259
+
260
+ # Background job context
261
+ Lapsoss.with_scope(
262
+ tags: { job: "invoice_generator", queue: "high_priority" },
263
+ extra: { batch_size: invoices.count }
264
+ ) do
265
+
266
+ invoices.each do |invoice|
267
+ Lapsoss.add_breadcrumb("Processing invoice #{invoice.id}")
268
+ generate_invoice(invoice)
269
+ end
270
+
271
+ end
272
+ ```
273
+
274
+ ### Real-World Examples
275
+
276
+ #### E-commerce Checkout Flow
277
+ ```ruby
278
+ class CheckoutController < ApplicationController
279
+ def create
280
+ Lapsoss.with_scope(
281
+ user: { id: current_user.id, email: current_user.email },
282
+ tags: { controller: "checkout", action: "create" },
283
+ extra: { cart_total: cart.total, item_count: cart.items.count }
284
+ ) do
285
+
286
+ Lapsoss.add_breadcrumb("Checkout initiated", type: :user)
287
+
288
+ begin
289
+ payment = process_payment(cart.total)
290
+ Lapsoss.add_breadcrumb("Payment processed", type: :system,
291
+ payment_id: payment.id, method: payment.method)
292
+
293
+ order = create_order(cart, payment)
294
+ Lapsoss.add_breadcrumb("Order created", type: :system, order_id: order.id)
295
+
296
+ redirect_to order_path(order)
297
+
298
+ rescue PaymentError => e
299
+ Lapsoss.capture_exception(e,
300
+ tags: { error_type: "payment_failure" },
301
+ extra: { payment_method: params[:payment_method] }
302
+ )
303
+ redirect_to checkout_path, alert: "Payment failed"
304
+
305
+ rescue InventoryError => e
306
+ Lapsoss.capture_exception(e,
307
+ tags: { error_type: "inventory_failure" },
308
+ extra: { requested_items: cart.items.pluck(:id) }
309
+ )
310
+ redirect_to cart_path, alert: "Item no longer available"
311
+ end
312
+
313
+ end
314
+ end
315
+ end
316
+ ```
317
+
318
+ #### Background Job Error Handling
319
+ ```ruby
320
+ class InvoiceGeneratorJob < ApplicationJob
321
+ def perform(batch_id)
322
+ Lapsoss.with_scope(
323
+ tags: { job: "invoice_generator", batch_id: batch_id },
324
+ extra: { queue: queue_name, priority: priority }
325
+ ) do
326
+
327
+ invoices = Invoice.where(batch_id: batch_id)
328
+
329
+ invoices.each_with_index do |invoice, index|
330
+ Lapsoss.add_breadcrumb("Processing invoice #{invoice.id}",
331
+ type: :system,
332
+ progress: "#{index + 1}/#{invoices.count}"
333
+ )
334
+
335
+ begin
336
+ generate_pdf(invoice)
337
+ send_email(invoice)
338
+ invoice.update!(status: :sent)
339
+
340
+ rescue => e
341
+ Lapsoss.capture_exception(e,
342
+ tags: { error_type: "invoice_generation_failure" },
343
+ extra: { invoice_id: invoice.id, customer_id: invoice.customer_id }
344
+ )
345
+
346
+ invoice.update!(status: :failed)
347
+ end
348
+ end
349
+
350
+ end
351
+ end
352
+ end
353
+ ```
354
+
355
+ #### API Error Tracking
356
+ ```ruby
357
+ class ApiController < ApplicationController
358
+ around_action :track_api_errors
359
+
360
+ private
361
+
362
+ def track_api_errors
363
+ Lapsoss.with_scope(
364
+ tags: {
365
+ api_version: request.headers["API-Version"],
366
+ endpoint: "#{params[:controller]}##{params[:action]}"
367
+ },
368
+ extra: {
369
+ user_agent: request.user_agent,
370
+ ip_address: request.remote_ip
371
+ }
372
+ ) do
373
+
374
+ Lapsoss.add_breadcrumb("API request started",
375
+ type: :http,
376
+ url: request.path,
377
+ method: request.method
378
+ )
379
+
380
+ begin
381
+ yield
382
+
383
+ rescue RateLimitError => e
384
+ Lapsoss.capture_exception(e,
385
+ tags: { error_type: "rate_limit_exceeded" },
386
+ extra: { limit: e.limit, reset_time: e.reset_time }
387
+ )
388
+ render json: { error: "Rate limit exceeded" }, status: 429
389
+
390
+ rescue AuthenticationError => e
391
+ Lapsoss.capture_exception(e,
392
+ tags: { error_type: "authentication_failure" },
393
+ extra: { auth_method: request.headers["Authorization"]&.split(" ")&.first }
394
+ )
395
+ render json: { error: "Authentication required" }, status: 401
396
+
397
+ rescue => e
398
+ Lapsoss.capture_exception(e,
399
+ tags: { error_type: "unexpected_api_error" }
400
+ )
401
+ render json: { error: "Internal server error" }, status: 500
402
+ end
403
+
404
+ end
405
+ end
406
+ end
407
+ ```
408
+
409
+ > 💡 **Pro Tip**: Check out the `/examples` directory for more comprehensive configuration examples and use cases.
410
+
411
+ ### Rollbar Integration
412
+ ```ruby
413
+ # Traditional Rollbar setup:
414
+ # rails generate rollbar YOUR_ACCESS_TOKEN
415
+
416
+ # With Lapsoss:
417
+ config.use_rollbar(
418
+ name: :rollbar,
419
+ access_token: ENV['ROLLBAR_ACCESS_TOKEN'] # or your token directly
420
+ )
421
+ ```
422
+
423
+ ### Insight Hub Integration
424
+ ```ruby
425
+ config.use_insight_hub(
426
+ name: :insight_hub,
427
+ api_key: ENV['INSIGHT_HUB_API_KEY'],
428
+ release_stage: Rails.env,
429
+ app_version: '1.0.0'
430
+ )
431
+
432
+ # For backwards compatibility, you can still use:
433
+ # config.use_bugsnag(...) which maps to Insight Hub
434
+ ```
435
+
436
+ ## Advanced Features
437
+
438
+ ### Custom Fingerprinting for Intelligent Error Grouping
439
+
440
+ Lapsoss provides sophisticated error fingerprinting to group related errors together, reducing noise and improving debugging efficiency.
441
+
442
+ #### Built-in Smart Patterns
443
+ ```ruby
444
+ # These errors get automatically grouped:
445
+ "User 123 not found" } → "user-lookup-error"
446
+ "User 456 not found" }
447
+
448
+ "Payment processing failed for order #123" } → "payment-failure"
449
+ "Payment failed for card ending in 4567" }
450
+
451
+ "Database connection lost" } → "database-connection-error"
452
+ "PG::ConnectionBad: timeout" }
453
+ ```
454
+
455
+ #### Custom Fingerprint Callbacks
456
+ ```ruby
457
+ Lapsoss.configure do |config|
458
+ config.fingerprint_callback = lambda do |event|
459
+ case event.exception&.class&.name
460
+ when "ActiveRecord::RecordNotFound"
461
+ # Group all record not found errors
462
+ "database-record-error"
463
+ when /Net::/
464
+ # Group all network errors
465
+ "network-error"
466
+ when "Redis::ConnectionError", "Redis::TimeoutError"
467
+ # Group Redis issues
468
+ "redis-error"
469
+ else
470
+ nil # Use default fingerprinting
471
+ end
472
+ end
473
+ end
474
+ ```
475
+
476
+ #### Pattern-Based Fingerprinting
477
+ ```ruby
478
+ Lapsoss.configure do |config|
479
+ config.fingerprint_patterns = [
480
+ # E-commerce patterns
481
+ {
482
+ pattern: /Payment.*failed/i,
483
+ fingerprint: "payment-failure"
484
+ },
485
+ {
486
+ pattern: /Order \d+ (invalid|missing|not found)/i,
487
+ fingerprint: "order-lookup-error"
488
+ },
489
+
490
+ # API patterns
491
+ {
492
+ pattern: %r{/api/v\d+/users/\d+},
493
+ fingerprint: "api-user-endpoint-error"
494
+ },
495
+ {
496
+ pattern: /Rate limit exceeded/i,
497
+ fingerprint: "rate-limit-exceeded"
498
+ }
499
+ ]
500
+ end
501
+ ```
502
+
503
+ #### Smart Normalization
504
+ ```ruby
505
+ Lapsoss.configure do |config|
506
+ # Normalize IDs: "User 12345 not found" → "User :id not found"
507
+ config.normalize_fingerprint_ids = true
508
+
509
+ # Normalize paths: "/home/user/file.txt" → ":filepath"
510
+ config.normalize_fingerprint_paths = true
511
+
512
+ # Include environment in fingerprint (useful for staging vs production)
513
+ config.fingerprint_include_environment = false
514
+ end
515
+ ```
516
+
517
+ #### Advanced Use Cases
518
+ ```ruby
519
+ # Environment-specific fingerprinting
520
+ config.fingerprint_callback = lambda do |event|
521
+ if Rails.env.development?
522
+ # More detailed fingerprints for debugging
523
+ "#{event.exception.class.name}-#{event.exception.backtrace&.first}"
524
+ else
525
+ # Simpler fingerprints for production
526
+ case event.exception&.class&.name
527
+ when /ActiveRecord/ then "database-error"
528
+ when /Net::/ then "network-error"
529
+ else nil
530
+ end
531
+ end
532
+ end
533
+
534
+ # Group by controller/model for Rails apps
535
+ config.fingerprint_callback = lambda do |event|
536
+ backtrace = event.exception&.backtrace || []
537
+
538
+ if controller_line = backtrace.find { |line| line.include?("app/controllers/") }
539
+ controller = controller_line.match(%r{app/controllers/(\w+)_controller\.rb})[1]
540
+ "controller-#{controller}-error"
541
+ elsif model_line = backtrace.find { |line| line.include?("app/models/") }
542
+ model = model_line.match(%r{app/models/(\w+)\.rb})[1]
543
+ "model-#{model}-error"
544
+ else
545
+ nil
546
+ end
547
+ end
548
+ ```
549
+
550
+ ### Transport Reliability & Rate Limiting
551
+
552
+ Lapsoss includes built-in transport reliability to ensure your errors reach their destination even under adverse conditions.
553
+
554
+ ```ruby
555
+ Lapsoss.configure do |config|
556
+ # Transport reliability settings
557
+ config.transport_timeout = 10 # Request timeout in seconds
558
+ config.transport_max_retries = 3 # Number of retry attempts
559
+ config.transport_initial_backoff = 1.0 # Initial backoff delay
560
+ config.transport_max_backoff = 64.0 # Maximum backoff delay
561
+ config.transport_backoff_multiplier = 2.0 # Exponential backoff multiplier
562
+ config.transport_jitter = true # Add random jitter to prevent thundering herd
563
+ end
564
+ ```
565
+
566
+ **Features:**
567
+ - **Exponential Backoff**: Intelligent retry timing to avoid overwhelming services (transport layer)
568
+ - **Rate Limiting**: Pipeline middleware with time-window and token bucket algorithms
569
+ - **Jitter**: Random delays to prevent synchronized retry storms (transport layer)
570
+ - **Circuit Breaking**: Automatic failure detection and recovery (transport layer)
571
+
572
+ ### Backtrace Processing
573
+
574
+ Lapsoss includes advanced backtrace processing that enhances error reports across all adapters:
575
+
576
+ ```ruby
577
+ Lapsoss.configure do |config|
578
+ # Code context extraction
579
+ config.backtrace_context_lines = 3 # Lines of code context (before/after)
580
+ config.backtrace_enable_code_context = true # Enable/disable context extraction
581
+
582
+ # Path normalization
583
+ config.backtrace_strip_load_path = true # Strip Ruby load paths for cleaner traces
584
+
585
+ # Frame limiting (for deep stack traces)
586
+ config.backtrace_max_frames = 100 # Prevent memory issues with stack overflows
587
+
588
+ # Application code detection
589
+ config.backtrace_in_app_patterns = [
590
+ %r{^/app/}, # Rails app directory
591
+ %r{^lib/}, # Custom libraries
592
+ %r{/my_company/} # Company code
593
+ ]
594
+
595
+ # Noise filtering
596
+ config.backtrace_exclude_patterns = [
597
+ %r{/ruby/gems/.*/rack-}, # Rack internals
598
+ %r{/activesupport-.*/notifications}, # AS internals
599
+ %r{/newrelic_rpm/} # Monitoring gems
600
+ ]
601
+ end
602
+ ```
603
+
604
+ **Features:**
605
+ - **Code Context**: Include source code snippets around error locations
606
+ - **Smart Filtering**: Remove framework noise, focus on your code
607
+ - **In-App Detection**: Automatically identify application vs library code
608
+ - **Performance Optimized**: LRU file caching for efficient processing
609
+ - **Format Agnostic**: Consistent processing across all adapters
610
+
611
+ ### Configuration Validation
612
+
613
+ All adapter settings are validated to catch configuration errors early:
614
+
615
+ ```ruby
616
+ # ✅ Valid configurations
617
+ config.use_sentry(dsn: "https://public_key@sentry.io/project_id")
618
+ config.use_rollbar(access_token: "abc123def456")
619
+ config.use_appsignal(push_api_key: "12345678-1234-1234-1234-123456789abc")
620
+
621
+ # ❌ Invalid configurations (caught at startup)
622
+ config.use_sentry(dsn: "invalid-dsn") # ValidationError: DSN scheme is required
623
+ config.use_rollbar(access_token: "invalid@token") # ValidationError: must be alphanumeric
624
+ config.use_appsignal(push_api_key: "not-a-uuid") # ValidationError: must be valid UUID
625
+ ```
626
+
627
+ ## Data Security & Privacy
628
+
629
+ Lapsoss automatically protects sensitive data by integrating with Rails' parameter filtering system.
630
+
631
+ ### Automatic Rails Integration
632
+ ```ruby
633
+ # config/initializers/filter_parameter_logging.rb (Standard Rails)
634
+ Rails.application.config.filter_parameters += [
635
+ :passw, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn
636
+ ]
637
+
638
+ # Lapsoss automatically uses these filters - no additional configuration needed!
639
+ Lapsoss.configure do |config|
640
+ config.use_sentry(dsn: ENV['SENTRY_DSN'])
641
+ # Sensitive fields are automatically scrubbed using Rails filter_parameters
642
+ end
643
+ ```
644
+
645
+ ### Custom Data Scrubbing
646
+ ```ruby
647
+ Lapsoss.configure do |config|
648
+ # Add custom fields to scrub (in addition to Rails filters)
649
+ config.scrub_fields = %w[internal_token custom_secret]
650
+
651
+ # Override Rails filters completely
652
+ config.scrub_fields = %w[password api_key credit_card] # Ignores Rails config
653
+
654
+ # Scrub everything except whitelisted fields
655
+ config.scrub_all = true
656
+ config.whitelist_fields = %w[debug_info safe_field]
657
+
658
+ # Randomize scrubbed value lengths (security through obscurity)
659
+ config.randomize_scrub_length = true # "******" to "*********"
660
+ end
661
+ ```
662
+
663
+ ### What Gets Protected
664
+ - **Passwords**: `password`, `passwd`, `pwd`
665
+ - **Tokens**: `token`, `access_token`, `auth_token`, `csrf_token`
666
+ - **Keys**: `key`, `api_key`, `secret_key`
667
+ - **PII**: `ssn`, `social_security_number`, `credit_card`, `phone`
668
+ - **File Uploads**: Metadata extracted, content scrubbed
669
+ - **Rails filter_parameters**: Automatically respected
670
+
671
+ ## Adaptive Traits We've Selected
672
+
673
+ ### From Sentry 🔍
674
+ - **Custom fingerprinting** for intelligent error grouping
675
+ - Robust error capture with context
676
+ - Release tracking and environment awareness
677
+
678
+ ### From Rollbar 🎲
679
+ - **Advanced data scrubbing** with Rails parameter filter integration
680
+ - **Transport reliability** with exponential backoff and retry logic
681
+ - Person tracking and user context
682
+
683
+ ### From AppSignal 📊
684
+ - **Configuration validation** to catch setup errors early
685
+ - Check-in monitoring for cron jobs
686
+ - Deploy markers and health checks
687
+
688
+ ### From Insight Hub (formerly Bugsnag) 🐛
689
+ - Feature flag correlation with errors
690
+ - Session tracking for crash-free rates
691
+ - Typed breadcrumbs for debugging context
692
+
693
+
694
+ ### Lapsoss Innovations 🧬
695
+ - **Pure Ruby implementations** - no external SDK dependencies
696
+ - **Multi-adapter architecture** - use multiple services simultaneously
697
+ - **Vendor-neutral configuration** - switch providers without code changes
698
+ - **Zero monkey-patching** - your application remains untouched
699
+
700
+ ## Usage Examples
701
+
702
+ ### Basic Error Capture
703
+ ```ruby
704
+ begin
705
+ risky_operation
706
+ rescue => e
707
+ Lapsoss.capture_exception(e, user: current_user)
708
+ end
709
+ ```
710
+
711
+ ### Custom Fingerprinting in Action
712
+ ```ruby
713
+ # These errors will be automatically grouped:
714
+ begin
715
+ User.find(123) # → "user-lookup-error"
716
+ rescue ActiveRecord::RecordNotFound => e
717
+ Lapsoss.capture_exception(e)
718
+ end
719
+
720
+ begin
721
+ User.find(456) # → Same "user-lookup-error" group
722
+ rescue ActiveRecord::RecordNotFound => e
723
+ Lapsoss.capture_exception(e)
724
+ end
725
+ ```
726
+
727
+ ### Advanced Configuration Example
728
+ ```ruby
729
+ Lapsoss.configure do |config|
730
+ # Multi-vendor setup with custom fingerprinting
731
+ config.use_sentry(name: :sentry, dsn: ENV['SENTRY_DSN'])
732
+ config.use_rollbar(name: :rollbar, access_token: ENV['ROLLBAR_TOKEN'])
733
+
734
+ # Custom fingerprinting for your domain
735
+ config.fingerprint_callback = lambda do |event|
736
+ case event.exception&.message
737
+ when /payment.*failed/i
738
+ "payment-processing-error"
739
+ when /user.*not.*found/i
740
+ "user-lookup-error"
741
+ else
742
+ nil # Use built-in patterns and defaults
743
+ end
744
+ end
745
+
746
+ # Enhanced data protection
747
+ config.scrub_fields = %w[credit_card_number api_token internal_id]
748
+ config.randomize_scrub_length = true
749
+
750
+ # Reliable transport
751
+ config.transport_max_retries = 5
752
+ config.transport_timeout = 15
753
+ end
754
+ ```
755
+
756
+
757
+ ## Creating Custom Adapters
758
+
759
+ ```ruby
760
+ class MyCustomAdapter < Lapsoss::Adapters::Base
761
+ def capture(event)
762
+ # Send to your service
763
+ end
764
+ end
765
+
766
+ Lapsoss::Registry.register(:custom, MyCustomAdapter)
767
+ ```
768
+
769
+ ## Multi-Adapter Use Cases
770
+
771
+ ### GDPR Region Migration
772
+ ```ruby
773
+ # Step 1: Start with US
774
+ config.use_sentry(name: :sentry_us, dsn: ENV['SENTRY_US_DSN'])
775
+
776
+ # Step 2: Add EU, run both
777
+ config.use_sentry(name: :sentry_us, dsn: ENV['SENTRY_US_DSN'])
778
+ config.use_sentry(name: :sentry_eu, dsn: ENV['SENTRY_EU_DSN'])
779
+
780
+ # Step 3: Complete migration
781
+ config.use_sentry(name: :sentry_eu, dsn: ENV['SENTRY_EU_DSN'])
782
+ ```
783
+
784
+ ### Vendor Migration
785
+ ```ruby
786
+ # Gradual migration with zero downtime
787
+ config.use_bugsnag(name: :old_vendor, api_key: ENV['BUGSNAG_KEY'])
788
+ config.use_sentry(name: :new_vendor, dsn: ENV['SENTRY_DSN'])
789
+ # Remove old vendor when ready
790
+ ```
791
+
792
+ ### AppSignal Integration
793
+ ```ruby
794
+ # config/initializers/lapsoss.rb
795
+ config.use_appsignal(
796
+ name: :appsignal,
797
+ push_api_key: ENV['APPSIGNAL_PUSH_API_KEY'], # For markers & check-ins
798
+ frontend_api_key: ENV['APPSIGNAL_FRONTEND_API_KEY'], # For error tracking
799
+ app_name: 'my-app'
800
+ )
801
+ ```
802
+
803
+ **AppSignal API Keys**: AppSignal uses two different API keys:
804
+ - **Push API Key**: For deploy markers and check-ins (found in Push & Deploy settings)
805
+ - **Frontend API Key**: For error tracking via public API (found in App settings > "Front-end error monitoring")
806
+
807
+ The Lapsoss AppSignal adapter provides:
808
+ - ✅ Error tracking (via public `/errors` endpoint with frontend key)
809
+ - ✅ Deploy markers (via `/markers` endpoint with push key)
810
+ - ✅ Check-ins/Heartbeats (via `/heartbeats` endpoint with push key)
811
+ - ✅ Breadcrumbs (included with errors)
812
+ - ❌ Performance monitoring (requires native extension)
813
+ - ❌ Host metrics (requires native extension)
814
+
815
+ ### High Availability
816
+ ```ruby
817
+ # Multiple regions + vendors for redundancy
818
+ config.use_sentry(name: :primary, dsn: ENV['PRIMARY_DSN'])
819
+ config.use_sentry(name: :backup, dsn: ENV['BACKUP_DSN'])
820
+ config.use_rollbar(name: :backup_service, access_token: ENV['ROLLBAR_TOKEN'])
821
+ ```
822
+
823
+ ## Why "Adaptive Trait Selection"?
824
+
825
+ Traditional error tracking gems lock you into their ecosystem. Lapsoss applies evolutionary principles:
826
+
827
+ 1. **Observation**: Each vendor evolved unique strengths
828
+ 2. **Selection**: I identify the most beneficial traits
829
+ 3. **Adaptation**: I create vendor-neutral interfaces
830
+ 4. **Evolution**: Your app gains the best of all worlds
831
+
832
+ ### The Multi-Adapter Advantage
833
+
834
+ - **Zero-downtime migrations** between providers
835
+ - **Regional compliance** (GDPR, data residency)
836
+ - **Vendor independence** - never locked in
837
+ - **Cost optimization** - route by importance
838
+ - **A/B testing** different services
839
+
840
+ ## Contributing
841
+
842
+ Help me evolve! I'm actively selecting new adaptive traits:
843
+
844
+ 1. Fork the repo
845
+ 2. Create your feature branch
846
+ 3. Add your trait selection
847
+ 4. Submit a PR
848
+
849
+ ## License
850
+
851
+ MIT License - Because good traits should spread freely
852
+
853
+ ---
854
+
855
+ Built with ❤️ and evolutionary principles