lapsoss 0.2.0 → 0.3.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.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +153 -733
  3. data/lib/lapsoss/adapters/appsignal_adapter.rb +22 -22
  4. data/lib/lapsoss/adapters/base.rb +0 -3
  5. data/lib/lapsoss/adapters/insight_hub_adapter.rb +108 -104
  6. data/lib/lapsoss/adapters/logger_adapter.rb +1 -1
  7. data/lib/lapsoss/adapters/rollbar_adapter.rb +108 -68
  8. data/lib/lapsoss/adapters/sentry_adapter.rb +24 -24
  9. data/lib/lapsoss/backtrace_frame.rb +37 -206
  10. data/lib/lapsoss/backtrace_frame_factory.rb +228 -0
  11. data/lib/lapsoss/backtrace_processor.rb +26 -23
  12. data/lib/lapsoss/client.rb +2 -4
  13. data/lib/lapsoss/configuration.rb +28 -32
  14. data/lib/lapsoss/current.rb +10 -2
  15. data/lib/lapsoss/event.rb +28 -5
  16. data/lib/lapsoss/exception_backtrace_frame.rb +39 -0
  17. data/lib/lapsoss/exclusion_configuration.rb +30 -0
  18. data/lib/lapsoss/exclusion_filter.rb +0 -273
  19. data/lib/lapsoss/exclusion_presets.rb +249 -0
  20. data/lib/lapsoss/fingerprinter.rb +28 -28
  21. data/lib/lapsoss/http_client.rb +8 -8
  22. data/lib/lapsoss/merged_scope.rb +63 -0
  23. data/lib/lapsoss/middleware/base.rb +15 -0
  24. data/lib/lapsoss/middleware/conditional_filter.rb +18 -0
  25. data/lib/lapsoss/middleware/event_enricher.rb +19 -0
  26. data/lib/lapsoss/middleware/event_transformer.rb +19 -0
  27. data/lib/lapsoss/middleware/exception_filter.rb +43 -0
  28. data/lib/lapsoss/middleware/metrics_collector.rb +44 -0
  29. data/lib/lapsoss/middleware/rate_limiter.rb +31 -0
  30. data/lib/lapsoss/middleware/release_tracker.rb +117 -0
  31. data/lib/lapsoss/middleware/sample_filter.rb +23 -0
  32. data/lib/lapsoss/middleware/sampling_middleware.rb +18 -0
  33. data/lib/lapsoss/middleware/user_context_enhancer.rb +46 -0
  34. data/lib/lapsoss/middleware.rb +0 -339
  35. data/lib/lapsoss/pipeline.rb +0 -68
  36. data/lib/lapsoss/pipeline_builder.rb +69 -0
  37. data/lib/lapsoss/rails_error_subscriber.rb +42 -0
  38. data/lib/lapsoss/rails_middleware.rb +78 -0
  39. data/lib/lapsoss/railtie.rb +22 -50
  40. data/lib/lapsoss/registry.rb +18 -5
  41. data/lib/lapsoss/release_providers.rb +110 -0
  42. data/lib/lapsoss/release_tracker.rb +159 -232
  43. data/lib/lapsoss/sampling/adaptive_sampler.rb +46 -0
  44. data/lib/lapsoss/sampling/base.rb +11 -0
  45. data/lib/lapsoss/sampling/composite_sampler.rb +26 -0
  46. data/lib/lapsoss/sampling/consistent_hash_sampler.rb +30 -0
  47. data/lib/lapsoss/sampling/exception_type_sampler.rb +44 -0
  48. data/lib/lapsoss/sampling/health_based_sampler.rb +19 -0
  49. data/lib/lapsoss/sampling/rate_limiter.rb +32 -0
  50. data/lib/lapsoss/sampling/sampling_factory.rb +69 -0
  51. data/lib/lapsoss/sampling/time_based_sampler.rb +44 -0
  52. data/lib/lapsoss/sampling/uniform_sampler.rb +15 -0
  53. data/lib/lapsoss/sampling/user_based_sampler.rb +42 -0
  54. data/lib/lapsoss/sampling.rb +0 -322
  55. data/lib/lapsoss/scope.rb +12 -48
  56. data/lib/lapsoss/scrubber.rb +7 -7
  57. data/lib/lapsoss/user_context.rb +30 -203
  58. data/lib/lapsoss/user_context_integrations.rb +39 -0
  59. data/lib/lapsoss/user_context_middleware.rb +50 -0
  60. data/lib/lapsoss/user_context_provider.rb +93 -0
  61. data/lib/lapsoss/utils.rb +13 -0
  62. data/lib/lapsoss/validators.rb +15 -15
  63. data/lib/lapsoss/version.rb +1 -1
  64. data/lib/lapsoss.rb +3 -3
  65. metadata +54 -5
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'singleton'
4
- require 'concurrent'
3
+ require "singleton"
4
+ require "concurrent"
5
5
 
6
6
  module Lapsoss
7
7
  class Registry
@@ -36,11 +36,17 @@ module Lapsoss
36
36
  #
37
37
  # @param adapter [Adapter] The adapter instance to register
38
38
  def register_adapter(adapter)
39
+ # Ensure we're getting an adapter instance, not a config hash
40
+ raise ArgumentError, "Expected an adapter instance, got #{adapter.class}" unless adapter.respond_to?(:capture)
41
+
39
42
  name = if adapter.respond_to?(:name) && adapter.name
40
43
  adapter.name.to_sym
41
- else
42
- adapter.class.name.split('::').last.to_sym
43
- end
44
+ elsif adapter.class.name
45
+ adapter.class.name.split("::").last.to_sym
46
+ else
47
+ # Generate a unique name if class name is nil (anonymous class)
48
+ :"adapter_#{adapter.object_id}"
49
+ end
44
50
  @adapters[name] = adapter
45
51
  end
46
52
 
@@ -98,6 +104,13 @@ module Lapsoss
98
104
  @adapters.keys
99
105
  end
100
106
 
107
+ # Get all registered adapters (alias for all)
108
+ #
109
+ # @return [Array<Adapter>] All adapter instances
110
+ def adapters
111
+ all
112
+ end
113
+
101
114
  private
102
115
 
103
116
  # Resolve adapter type to class
@@ -0,0 +1,110 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+
5
+ module Lapsoss
6
+ # Built-in release providers for common scenarios
7
+ class ReleaseProviders
8
+ def self.from_file(file_path)
9
+ lambda do
10
+ return nil unless File.exist?(file_path)
11
+
12
+ content = File.read(file_path).strip
13
+ return nil if content.empty?
14
+
15
+ # Try to parse as JSON first
16
+ begin
17
+ JSON.parse(content)
18
+ rescue JSON::ParserError
19
+ # Treat as plain text version
20
+ { version: content }
21
+ end
22
+ end
23
+ end
24
+
25
+ def self.from_ruby_constant(constant_name)
26
+ lambda do
27
+ constant = Object.const_get(constant_name)
28
+ { version: constant.to_s }
29
+ rescue NameError
30
+ nil
31
+ end
32
+ end
33
+
34
+ def self.from_gemfile_lock
35
+ lambda do
36
+ return nil unless File.exist?("Gemfile.lock")
37
+
38
+ content = File.read("Gemfile.lock")
39
+
40
+ # Extract gems with versions
41
+ gems = {}
42
+ content.scan(/^\s{4}(\w+)\s+\(([^)]+)\)/).each do |name, version|
43
+ gems[name] = version
44
+ end
45
+
46
+ { gems: gems }
47
+ end
48
+ end
49
+
50
+ def self.from_package_json
51
+ lambda do
52
+ return nil unless File.exist?("package.json")
53
+
54
+ begin
55
+ package_info = JSON.parse(File.read("package.json"))
56
+ {
57
+ version: package_info["version"],
58
+ name: package_info["name"],
59
+ dependencies: package_info["dependencies"]&.keys
60
+ }.compact
61
+ rescue JSON::ParserError
62
+ nil
63
+ end
64
+ end
65
+ end
66
+
67
+ def self.from_rails_application
68
+ lambda do
69
+ return nil unless defined?(Rails) && Rails.respond_to?(:application)
70
+
71
+ app = Rails.application
72
+ return nil unless app
73
+
74
+ info = {
75
+ rails_version: Rails.version,
76
+ environment: Rails.env,
77
+ root: Rails.root.to_s
78
+ }
79
+
80
+ # Get application version if defined
81
+ info[:app_version] = app.class.version if app.class.respond_to?(:version)
82
+
83
+ # Get application name
84
+ info[:app_name] = app.class.name if app.class.respond_to?(:name)
85
+
86
+ info
87
+ end
88
+ end
89
+
90
+ def self.from_capistrano
91
+ lambda do
92
+ # Check for Capistrano deployment files
93
+ %w[REVISION current/REVISION].each do |file|
94
+ next unless File.exist?(file)
95
+
96
+ revision = File.read(file).strip
97
+ next if revision.empty?
98
+
99
+ return {
100
+ revision: revision,
101
+ deployed_at: File.mtime(file),
102
+ deployment_method: "capistrano"
103
+ }
104
+ end
105
+
106
+ nil
107
+ end
108
+ end
109
+ end
110
+ end