dead_bro 0.2.18 → 0.2.19

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: aa43ba99a6fb0fd4007b856a24ac5844236f2d0102f9ec71175c81981a91bb17
4
- data.tar.gz: c91f7fee25858bafd2edabfb162239ea8d8833405a3b4965f55e403a06dbfd05
3
+ metadata.gz: edddcaa5684cac479f815b4d8e1a377e30f039c6ba910daa6f30b2322538c64c
4
+ data.tar.gz: 4841c2bcadcd841a61dafc79216e3324fa87a239dea2be7d3cce038934ba28cb
5
5
  SHA512:
6
- metadata.gz: b436b94d8d36d0b3407b09481326e443aa342c4398d4973fb517016bd3ee1f4a159a163d12a76b2294f2e4de36505b0cb568010bd8e0aecbbd0e3b4dc544069e
7
- data.tar.gz: 7981b5ea511dad34ce67c0a71afe8a09f12045a0ae778311fa42ae0426f3a689d38377528939c6f757192bd973c3d3c782f9f2124831cfac5505d4bf1ab2d177
6
+ metadata.gz: 2dd9071e6620fad08ee1e700ac48199f1b3b62119e68a3d52b2b381eba6152e3a311d28bc64aeb81855a5adb9edacab73decc8ce4c71243eb71f8680cdd41cc1
7
+ data.tar.gz: 4a1319b9b8f32b56f24a76e4681b7c55fa7b299258b590bffee686fc82ee7d8ad642df890593bf6c62e049225d9dcfc364877fe2ebc20dd6db1262836e9fc1ac
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "digest"
3
4
  require "rack"
4
5
 
5
6
  module DeadBro
@@ -35,6 +36,8 @@ module DeadBro
35
36
  exception_class: exception.class.name,
36
37
  message: truncate(exception.message.to_s, 1000),
37
38
  backtrace: safe_backtrace(exception),
39
+ fingerprint: compute_fingerprint(exception),
40
+ cause_chain: build_cause_chain(exception),
38
41
  occurred_at: Time.now.utc.to_i,
39
42
  rack:
40
43
  {
@@ -67,6 +70,42 @@ module DeadBro
67
70
  []
68
71
  end
69
72
 
73
+ def normalize_message(msg)
74
+ msg.to_s
75
+ .gsub(/\b[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\b/i, "UUID")
76
+ .gsub(/\b\d+\b/, "N")
77
+ .gsub(/"[^"]*"/, '"?"')
78
+ .gsub(/'[^']*'/, "'?'")
79
+ .strip
80
+ end
81
+
82
+ def compute_fingerprint(exception)
83
+ top_frame = Array(exception.backtrace).first.to_s.gsub(/:\d+:in /, ":N:in ")
84
+ input = "#{exception.class.name}|#{normalize_message(exception.message)}|#{top_frame}"
85
+ Digest::SHA256.hexdigest(input)[0, 16]
86
+ rescue
87
+ nil
88
+ end
89
+
90
+ def build_cause_chain(exception)
91
+ return [] unless exception
92
+ chain = []
93
+ cause = exception.cause
94
+ depth = 0
95
+ while cause && depth < 5
96
+ chain << {
97
+ exception_class: cause.class.name,
98
+ message: truncate(cause.message.to_s, 500),
99
+ backtrace_top: Array(cause.backtrace).first(3)
100
+ }
101
+ cause = cause.cause
102
+ depth += 1
103
+ end
104
+ chain
105
+ rescue
106
+ []
107
+ end
108
+
70
109
  def safe_params(req)
71
110
  return {} unless req
72
111
 
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "digest"
3
4
  require "active_support/notifications"
4
5
 
5
6
  module DeadBro
@@ -139,6 +140,8 @@ module DeadBro
139
140
  exception_class: exception_class || exception_obj&.class&.name,
140
141
  message: (exception_message || exception_obj&.message).to_s[0, 1000],
141
142
  backtrace: backtrace,
143
+ fingerprint: compute_error_fingerprint(exception_obj),
144
+ cause_chain: build_cause_chain(exception_obj),
142
145
  error: true,
143
146
  logs: DeadBro.logger.logs
144
147
  }
@@ -401,5 +404,42 @@ module DeadBro
401
404
  rescue
402
405
  nil
403
406
  end
407
+
408
+ def self.normalize_error_message(msg)
409
+ msg.to_s
410
+ .gsub(/\b[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\b/i, "UUID")
411
+ .gsub(/\b\d+\b/, "N")
412
+ .gsub(/"[^"]*"/, '"?"')
413
+ .gsub(/'[^']*'/, "'?'")
414
+ .strip
415
+ end
416
+
417
+ def self.compute_error_fingerprint(exception)
418
+ return nil unless exception
419
+ top_frame = Array(exception.backtrace).first.to_s.gsub(/:\d+:in /, ":N:in ")
420
+ input = "#{exception.class.name}|#{normalize_error_message(exception.message)}|#{top_frame}"
421
+ Digest::SHA256.hexdigest(input)[0, 16]
422
+ rescue
423
+ nil
424
+ end
425
+
426
+ def self.build_cause_chain(exception)
427
+ return [] unless exception
428
+ chain = []
429
+ cause = exception.cause
430
+ depth = 0
431
+ while cause && depth < 5
432
+ chain << {
433
+ exception_class: cause.class.name,
434
+ message: cause.message.to_s[0, 500],
435
+ backtrace_top: Array(cause.backtrace).first(3)
436
+ }
437
+ cause = cause.cause
438
+ depth += 1
439
+ end
440
+ chain
441
+ rescue
442
+ []
443
+ end
404
444
  end
405
445
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DeadBro
4
- VERSION = "0.2.18"
4
+ VERSION = "0.2.19"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dead_bro
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.18
4
+ version: 0.2.19
5
5
  platform: ruby
6
6
  authors:
7
7
  - Emanuel Comsa