rails_error_dashboard 0.5.6 → 0.5.7
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:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0cfea703e2d74b6771503d098e3bc5f048ec781923ee08a1692e34bbf28c9734
|
|
4
|
+
data.tar.gz: 4b77fb5c2dd00920d2eaca85b92d35dcbb19282408dee936584deffd2e7126a6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1bcc5f0f868d3e864deccdfbe23a0a3c3e1da03f3cfb49208724f61deceaf7047bba7c1d3f19358a75e1a254336059894a55bec79656f67e55217eec18c34d19
|
|
7
|
+
data.tar.gz: 810aa6c9a5db5300d4f6f5964ce92aa06dada34dfc7b513e782a914de8a3f0baf7e35b8b03056b9a1060b018b8dca0d6b51534f528211e779c008a77060fa10d
|
|
@@ -36,6 +36,7 @@ module RailsErrorDashboard
|
|
|
36
36
|
|
|
37
37
|
sections << heading_section
|
|
38
38
|
sections << backtrace_section
|
|
39
|
+
sections << source_code_section
|
|
39
40
|
sections << cause_chain_section
|
|
40
41
|
sections << local_variables_section
|
|
41
42
|
sections << instance_variables_section
|
|
@@ -69,6 +70,45 @@ module RailsErrorDashboard
|
|
|
69
70
|
"## Backtrace\n\n```\n#{app_lines.join("\n")}\n```"
|
|
70
71
|
end
|
|
71
72
|
|
|
73
|
+
def source_code_section
|
|
74
|
+
return nil unless defined?(RailsErrorDashboard) &&
|
|
75
|
+
RailsErrorDashboard.configuration.enable_source_code_integration
|
|
76
|
+
|
|
77
|
+
raw = @error.backtrace
|
|
78
|
+
return nil if raw.blank?
|
|
79
|
+
|
|
80
|
+
lines = raw.split("\n")
|
|
81
|
+
app_lines = lines.reject { |l| l.include?("/gems/") || l.include?("/ruby/") || l.include?("/vendor/") }
|
|
82
|
+
return nil if app_lines.empty?
|
|
83
|
+
|
|
84
|
+
snippets = []
|
|
85
|
+
app_lines.first(3).each do |frame|
|
|
86
|
+
# Parse "file:line:in 'method'" format
|
|
87
|
+
match = frame.match(/^(.+?):(\d+)/)
|
|
88
|
+
next unless match
|
|
89
|
+
|
|
90
|
+
file_path = match[1]
|
|
91
|
+
line_number = match[2].to_i
|
|
92
|
+
|
|
93
|
+
reader = Services::SourceCodeReader.new(file_path, line_number)
|
|
94
|
+
source_lines = reader.read_lines(context: 3)
|
|
95
|
+
next unless source_lines&.any?
|
|
96
|
+
|
|
97
|
+
snippet = source_lines.map { |sl|
|
|
98
|
+
marker = sl[:highlight] ? ">" : " "
|
|
99
|
+
"#{marker} #{sl[:number].to_s.rjust(4)} | #{sl[:content]}"
|
|
100
|
+
}.join("\n")
|
|
101
|
+
|
|
102
|
+
snippets << "**#{file_path}:#{line_number}**\n```ruby\n#{snippet}\n```"
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
return nil if snippets.empty?
|
|
106
|
+
|
|
107
|
+
"## Source Code\n\n#{snippets.join("\n\n")}"
|
|
108
|
+
rescue => e
|
|
109
|
+
nil
|
|
110
|
+
end
|
|
111
|
+
|
|
72
112
|
def cause_chain_section
|
|
73
113
|
raw = @error.exception_cause
|
|
74
114
|
return nil if raw.blank?
|
|
@@ -135,12 +175,18 @@ module RailsErrorDashboard
|
|
|
135
175
|
return nil if @error.request_url.blank?
|
|
136
176
|
|
|
137
177
|
items = []
|
|
178
|
+
items << "- **Controller:** #{@error.controller_name}##{@error.action_name}" if @error.controller_name.present?
|
|
138
179
|
items << "- **Method:** #{@error.http_method}" if @error.http_method.present?
|
|
139
180
|
items << "- **URL:** #{@error.request_url}"
|
|
140
181
|
items << "- **Hostname:** #{@error.hostname}" if @error.hostname.present?
|
|
141
182
|
items << "- **Content-Type:** #{@error.content_type}" if @error.content_type.present?
|
|
142
183
|
items << "- **Duration:** #{@error.request_duration_ms}ms" if @error.request_duration_ms.present?
|
|
143
|
-
items << "- **
|
|
184
|
+
items << "- **User-Agent:** #{@error.user_agent}" if @error.user_agent.present?
|
|
185
|
+
|
|
186
|
+
params = parse_json(@error.request_params) if @error.request_params.present?
|
|
187
|
+
if params.is_a?(Hash) && params.any?
|
|
188
|
+
items << "\n**Request Params:**\n```json\n#{JSON.pretty_generate(params)}\n```"
|
|
189
|
+
end
|
|
144
190
|
|
|
145
191
|
"## Request Context\n\n#{items.join("\n")}"
|
|
146
192
|
end
|
|
@@ -196,19 +242,81 @@ module RailsErrorDashboard
|
|
|
196
242
|
return nil unless health.is_a?(Hash) && health.any?
|
|
197
243
|
|
|
198
244
|
items = []
|
|
199
|
-
|
|
245
|
+
|
|
246
|
+
# Process memory
|
|
247
|
+
mem = health["process_memory"]
|
|
248
|
+
if mem.is_a?(Hash)
|
|
249
|
+
parts = []
|
|
250
|
+
parts << "#{mem["rss_mb"]} MB RSS" if mem["rss_mb"]
|
|
251
|
+
parts << "peak #{mem["rss_peak_mb"]} MB" if mem["rss_peak_mb"]
|
|
252
|
+
parts << "swap #{mem["swap_mb"]} MB" if mem["swap_mb"] && mem["swap_mb"] > 0
|
|
253
|
+
parts << "#{mem["os_threads"]} OS threads" if mem["os_threads"]
|
|
254
|
+
items << "- **Memory:** #{parts.join(", ")}" if parts.any?
|
|
255
|
+
elsif health["process_memory_mb"]
|
|
256
|
+
items << "- **Memory:** #{health["process_memory_mb"]} MB RSS"
|
|
257
|
+
end
|
|
258
|
+
|
|
200
259
|
items << "- **Threads:** #{health["thread_count"]}" if health["thread_count"]
|
|
201
260
|
|
|
261
|
+
# DB connection pool
|
|
202
262
|
pool = health["connection_pool"]
|
|
203
|
-
if pool.is_a?(Hash)
|
|
204
|
-
|
|
263
|
+
if pool.is_a?(Hash) && pool["size"]
|
|
264
|
+
pool_parts = [ "#{pool["busy"]}/#{pool["size"]} busy" ]
|
|
265
|
+
pool_parts << "#{pool["dead"]} dead" if pool["dead"].to_i > 0
|
|
266
|
+
pool_parts << "#{pool["waiting"]} waiting" if pool["waiting"].to_i > 0
|
|
267
|
+
items << "- **DB Pool:** #{pool_parts.join(", ")}"
|
|
205
268
|
end
|
|
206
269
|
|
|
207
|
-
|
|
270
|
+
# GC stats
|
|
271
|
+
gc = health["gc"] || health["gc_stats"]
|
|
208
272
|
if gc.is_a?(Hash)
|
|
209
|
-
|
|
273
|
+
gc_parts = []
|
|
274
|
+
gc_parts << "#{gc["major_gc_count"]} major" if gc["major_gc_count"]
|
|
275
|
+
gc_parts << "#{gc["heap_live_slots"]} live slots" if gc["heap_live_slots"]
|
|
276
|
+
gc_parts << "#{gc["total_allocated_objects"]} total allocated" if gc["total_allocated_objects"]
|
|
277
|
+
items << "- **GC:** #{gc_parts.join(", ")}" if gc_parts.any?
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
# GC latest
|
|
281
|
+
gc_latest = health["gc_latest"]
|
|
282
|
+
if gc_latest.is_a?(Hash)
|
|
283
|
+
latest_parts = []
|
|
284
|
+
latest_parts << "triggered by #{gc_latest["gc_by"]}" if gc_latest["gc_by"]
|
|
285
|
+
latest_parts << "state: #{gc_latest["state"]}" if gc_latest["state"]
|
|
286
|
+
items << "- **Last GC:** #{latest_parts.join(", ")}" if latest_parts.any?
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
# Note: Puma and job queue stats are omitted — they are server-wide metrics,
|
|
290
|
+
# not error-specific. The LLM can infer job context from the backtrace.
|
|
291
|
+
|
|
292
|
+
# File descriptors
|
|
293
|
+
fd = health["file_descriptors"]
|
|
294
|
+
if fd.is_a?(Hash) && fd["open"]
|
|
295
|
+
items << "- **File Descriptors:** #{fd["open"]}/#{fd["limit"]} (#{fd["utilization_pct"]}%)"
|
|
210
296
|
end
|
|
211
297
|
|
|
298
|
+
# System load
|
|
299
|
+
load = health["system_load"]
|
|
300
|
+
if load.is_a?(Hash) && load["load_1m"]
|
|
301
|
+
items << "- **System Load:** #{load["load_1m"]}/#{load["load_5m"]}/#{load["load_15m"]} (#{load["cpu_count"]} CPUs)"
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
# System memory
|
|
305
|
+
sys_mem = health["system_memory"]
|
|
306
|
+
if sys_mem.is_a?(Hash) && sys_mem["total_mb"]
|
|
307
|
+
items << "- **System Memory:** #{sys_mem["available_mb"]}/#{sys_mem["total_mb"]} MB available (#{sys_mem["used_pct"]}% used)"
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
# TCP connections
|
|
311
|
+
tcp = health["tcp_connections"]
|
|
312
|
+
if tcp.is_a?(Hash) && tcp.values.any? { |v| v.to_i > 0 }
|
|
313
|
+
tcp_parts = tcp.map { |state, count| "#{state}: #{count}" if count.to_i > 0 }.compact
|
|
314
|
+
items << "- **TCP:** #{tcp_parts.join(", ")}"
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
# Note: RubyVM, YJIT, and ActionCable stats are omitted — they are process-wide
|
|
318
|
+
# counters, not error-specific context. They add noise for LLM debugging.
|
|
319
|
+
|
|
212
320
|
return nil if items.empty?
|
|
213
321
|
|
|
214
322
|
"## System Health at Error Time\n\n#{items.join("\n")}"
|
|
@@ -233,13 +341,12 @@ module RailsErrorDashboard
|
|
|
233
341
|
|
|
234
342
|
def metadata_section
|
|
235
343
|
items = []
|
|
236
|
-
items << "- **Severity:** #{@error.severity}" if @error.severity.present?
|
|
237
|
-
items << "- **Status:** #{@error.status}" if @error.status.present?
|
|
238
|
-
items << "- **Priority:** P#{3 - @error.priority_level}" if @error.priority_level.present?
|
|
239
344
|
items << "- **Platform:** #{@error.platform}" if @error.platform.present?
|
|
240
345
|
items << "- **First seen:** #{@error.first_seen_at&.utc&.strftime("%Y-%m-%d %H:%M:%S UTC")}" if @error.first_seen_at
|
|
241
346
|
items << "- **Occurrences:** #{@error.occurrence_count}" if @error.occurrence_count
|
|
242
|
-
items << "- **
|
|
347
|
+
items << "- **User ID:** #{@error.user_id}" if @error.user_id.present?
|
|
348
|
+
|
|
349
|
+
return nil if items.empty?
|
|
243
350
|
|
|
244
351
|
"## Metadata\n\n#{items.join("\n")}"
|
|
245
352
|
end
|
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.5.
|
|
4
|
+
version: 0.5.7
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Anjan Jagirdar
|
|
@@ -467,7 +467,7 @@ metadata:
|
|
|
467
467
|
bug_tracker_uri: https://github.com/AnjanJ/rails_error_dashboard/issues
|
|
468
468
|
funding_uri: https://buymeacoffee.com/anjanj
|
|
469
469
|
post_install_message: "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n
|
|
470
|
-
\ Rails Error Dashboard v0.5.
|
|
470
|
+
\ Rails Error Dashboard v0.5.7\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n\U0001F195
|
|
471
471
|
First time? Quick start:\n rails generate rails_error_dashboard:install\n rails
|
|
472
472
|
db:migrate\n # Add to config/routes.rb:\n mount RailsErrorDashboard::Engine
|
|
473
473
|
=> '/error_dashboard'\n\n\U0001F504 Upgrading from v0.1.x?\n rails db:migrate\n
|