rails_error_dashboard 0.1.19 → 0.1.20

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6669208b7836af38629663689984679194531516952a81b6d512f3cdd22d3104
4
- data.tar.gz: bd8e1ba61465fd5845d98459717c6fa5380b29428a284cf77cfa8262cb40bf16
3
+ metadata.gz: e25820931efde6d62173ac5455658d05799202e5a3b7bc745ee5368880079ef2
4
+ data.tar.gz: 9cfc00e8a78eb876d64a1908df201b05231d2ec1ff538c8bbda391198e7c1947
5
5
  SHA512:
6
- metadata.gz: f8620948152b3457008b0f020f7d7608fcb5822390e30e205c790502d3860fd7fe2aa0797d8f9742f78f90f6720fac013b0d124d876c06ac410571202c69b961
7
- data.tar.gz: a518ea6dbd9cac88f59050bbc5d419ec270daef0682b958f82020f06ec6de8b66dc3346a61bf79e27e10d95838ecb811e7c8976111c27c8926d0545bd4b61f52
6
+ metadata.gz: db9e01290004af02ae9a5b9f55039ddeec858f1761c9ec685be1e7a5ec91590f8ed4ca1b5a7c1a1b57babf1e6cfb1b394afcb70504175949c0c8480fc7cb47f3
7
+ data.tar.gz: 7c04e609a1b700c51d634f932f20ab1ed448603e9390141f5cd5ba78c86415fda2bb413ef457a73d290967da998407b7f51a3655f425b2833462472212dc97e5
@@ -0,0 +1,185 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsErrorDashboard
4
+ # ManualErrorReporter: Report errors manually from frontend, mobile apps, or custom sources
5
+ #
6
+ # This class provides a clean API for logging errors that don't originate from Ruby exceptions,
7
+ # such as JavaScript errors from the frontend, mobile app crashes, or manually constructed errors.
8
+ #
9
+ # @example Frontend JavaScript error
10
+ # RailsErrorDashboard::ManualErrorReporter.report(
11
+ # error_type: "TypeError",
12
+ # message: "Cannot read property 'foo' of undefined",
13
+ # backtrace: ["at handleClick (app.js:42)", "at onClick (button.js:15)"],
14
+ # platform: "Web",
15
+ # user_id: current_user&.id,
16
+ # request_url: request.url,
17
+ # user_agent: request.user_agent,
18
+ # metadata: { component: "ShoppingCart", action: "checkout" }
19
+ # )
20
+ #
21
+ # @example Mobile app crash
22
+ # RailsErrorDashboard::ManualErrorReporter.report(
23
+ # error_type: "NSException",
24
+ # message: "Fatal crash in payment processing",
25
+ # backtrace: stacktrace_array,
26
+ # platform: "iOS",
27
+ # app_version: "2.1.0",
28
+ # user_id: user_id,
29
+ # metadata: { device: "iPhone 14", os_version: "17.2" }
30
+ # )
31
+ class ManualErrorReporter
32
+ # Report a manual error to the dashboard
33
+ #
34
+ # @param error_type [String] The error class/type (e.g., "TypeError", "NetworkError")
35
+ # @param message [String] The error message
36
+ # @param backtrace [Array<String>, String, nil] Stack trace as array of strings or newline-separated string
37
+ # @param platform [String, nil] Platform where error occurred ("Web", "iOS", "Android", "API")
38
+ # @param user_id [String, Integer, nil] ID of the user who experienced the error
39
+ # @param request_url [String, nil] URL where the error occurred
40
+ # @param user_agent [String, nil] User agent string
41
+ # @param ip_address [String, nil] IP address of the requester
42
+ # @param app_version [String, nil] Version of the app where error occurred
43
+ # @param metadata [Hash, nil] Additional custom metadata about the error
44
+ # @param occurred_at [Time, nil] When the error occurred (defaults to Time.current)
45
+ # @param severity [Symbol, nil] Severity level (:critical, :high, :medium, :low)
46
+ # @param source [String, nil] Source identifier (e.g., "frontend", "mobile_app")
47
+ #
48
+ # @return [ErrorLog, nil] The created error log record, or nil if filtered/ignored
49
+ #
50
+ # @example Basic usage
51
+ # ManualErrorReporter.report(
52
+ # error_type: "ValidationError",
53
+ # message: "Email format is invalid",
54
+ # platform: "Web"
55
+ # )
56
+ #
57
+ # @example With full context
58
+ # ManualErrorReporter.report(
59
+ # error_type: "PaymentError",
60
+ # message: "Credit card declined",
61
+ # backtrace: ["checkout.js:123", "payment.js:45"],
62
+ # platform: "Web",
63
+ # user_id: current_user.id,
64
+ # request_url: checkout_url,
65
+ # user_agent: request.user_agent,
66
+ # ip_address: request.remote_ip,
67
+ # app_version: "1.2.3",
68
+ # metadata: { card_type: "visa", amount: 99.99 },
69
+ # severity: :high
70
+ # )
71
+ def self.report(
72
+ error_type:,
73
+ message:,
74
+ backtrace: nil,
75
+ platform: nil,
76
+ user_id: nil,
77
+ request_url: nil,
78
+ user_agent: nil,
79
+ ip_address: nil,
80
+ app_version: nil,
81
+ metadata: nil,
82
+ occurred_at: nil,
83
+ severity: nil,
84
+ source: nil
85
+ )
86
+ # Create a synthetic exception object that quacks like a Ruby exception
87
+ synthetic_exception = SyntheticException.new(
88
+ error_type: error_type,
89
+ message: message,
90
+ backtrace: normalize_backtrace(backtrace)
91
+ )
92
+
93
+ # Build context hash for LogError
94
+ context = {
95
+ source: source || "manual",
96
+ user_id: user_id,
97
+ request_url: request_url,
98
+ user_agent: user_agent,
99
+ ip_address: ip_address,
100
+ platform: platform,
101
+ app_version: app_version,
102
+ metadata: metadata,
103
+ occurred_at: occurred_at || Time.current,
104
+ severity: severity
105
+ }.compact # Remove nil values
106
+
107
+ # Use the existing LogError command
108
+ Commands::LogError.call(synthetic_exception, context)
109
+ end
110
+
111
+ # Normalize backtrace to array of strings
112
+ # @param backtrace [Array<String>, String, nil]
113
+ # @return [Array<String>]
114
+ private_class_method def self.normalize_backtrace(backtrace)
115
+ return [] if backtrace.nil?
116
+ return backtrace if backtrace.is_a?(Array)
117
+ return backtrace.split("\n") if backtrace.is_a?(String)
118
+ []
119
+ end
120
+
121
+ # SyntheticException: A fake exception object for manual error reporting
122
+ #
123
+ # This class mimics a Ruby Exception to work with the existing LogError command,
124
+ # but represents errors from non-Ruby sources (frontend, mobile, etc.)
125
+ #
126
+ # @api private
127
+ class SyntheticException
128
+ attr_reader :message, :backtrace
129
+
130
+ # @param error_type [String] The error class name
131
+ # @param message [String] The error message
132
+ # @param backtrace [Array<String>] The stack trace
133
+ def initialize(error_type:, message:, backtrace:)
134
+ @error_type = error_type
135
+ @message = message
136
+ @backtrace = backtrace
137
+ end
138
+
139
+ # Returns a mock class object that represents the error type
140
+ # @return [Object] A class-like object with the error type as its name
141
+ def class
142
+ # Return a simple object that quacks like a class
143
+ # This allows the error type to be stored correctly in the database
144
+ @class ||= MockClass.new(@error_type)
145
+ end
146
+
147
+ # MockClass: A simple class-like object for error typing
148
+ # @api private
149
+ class MockClass
150
+ def initialize(error_type)
151
+ @error_type = error_type
152
+ end
153
+
154
+ def name
155
+ @error_type
156
+ end
157
+
158
+ def to_s
159
+ @error_type
160
+ end
161
+ end
162
+
163
+ # Check if this is a specific error type
164
+ # @param klass [Class, String] The class to check against
165
+ # @return [Boolean]
166
+ def is_a?(klass)
167
+ return true if klass == self.class
168
+ return true if klass == SyntheticException
169
+ return true if klass.to_s == @error_type
170
+ false
171
+ end
172
+
173
+ # Inspect for debugging
174
+ # @return [String]
175
+ def inspect
176
+ "#<#{@error_type}: #{@message}>"
177
+ end
178
+ end
179
+
180
+ # Namespace for dynamically created manual error classes
181
+ # This keeps them separate from real Ruby exceptions
182
+ module ManualErrors
183
+ end
184
+ end
185
+ end
@@ -121,6 +121,9 @@ module RailsErrorDashboard
121
121
  end
122
122
 
123
123
  def detect_platform
124
+ # If platform is explicitly provided in context, use it
125
+ return @context[:platform] if @context[:platform].present?
126
+
124
127
  # Check if it's from a mobile request
125
128
  user_agent = extract_user_agent
126
129
 
@@ -1,3 +1,3 @@
1
1
  module RailsErrorDashboard
2
- VERSION = "0.1.19"
2
+ VERSION = "0.1.20"
3
3
  end
@@ -2,6 +2,7 @@ require "rails_error_dashboard/version"
2
2
  require "rails_error_dashboard/engine"
3
3
  require "rails_error_dashboard/configuration"
4
4
  require "rails_error_dashboard/logger"
5
+ require "rails_error_dashboard/manual_error_reporter"
5
6
 
6
7
  # External dependencies
7
8
  require "pagy"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails_error_dashboard
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.19
4
+ version: 0.1.20
5
5
  platform: ruby
6
6
  authors:
7
7
  - Anjan Jagirdar
@@ -342,6 +342,7 @@ files:
342
342
  - lib/rails_error_dashboard/engine.rb
343
343
  - lib/rails_error_dashboard/error_reporter.rb
344
344
  - lib/rails_error_dashboard/logger.rb
345
+ - lib/rails_error_dashboard/manual_error_reporter.rb
345
346
  - lib/rails_error_dashboard/middleware/error_catcher.rb
346
347
  - lib/rails_error_dashboard/middleware/rate_limiter.rb
347
348
  - lib/rails_error_dashboard/plugin.rb
@@ -379,7 +380,7 @@ metadata:
379
380
  source_code_uri: https://github.com/AnjanJ/rails_error_dashboard
380
381
  changelog_uri: https://github.com/AnjanJ/rails_error_dashboard/blob/main/CHANGELOG.md
381
382
  post_install_message: "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n
382
- \ Rails Error Dashboard v0.1.19\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n\U0001F195
383
+ \ Rails Error Dashboard v0.1.20\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n\U0001F195
383
384
  First time? Quick start:\n rails generate rails_error_dashboard:install\n rails
384
385
  db:migrate\n # Add to config/routes.rb:\n mount RailsErrorDashboard::Engine
385
386
  => '/error_dashboard'\n\n\U0001F504 Upgrading from v0.1.x?\n rails db:migrate\n