enhanced_errors 0.1.0 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.yardoc/checksums +4 -0
- data/.yardoc/complete +0 -0
- data/.yardoc/object_types +0 -0
- data/.yardoc/objects/root.dat +0 -0
- data/.yardoc/proxy_types +0 -0
- data/README.md +52 -70
- data/doc/Binding.html +137 -0
- data/doc/Colors.html +384 -0
- data/doc/Debugging.html +181 -0
- data/doc/EnhancedErrors.html +2742 -0
- data/doc/ErrorEnhancements.html +252 -0
- data/doc/_index.html +151 -0
- data/doc/class_list.html +54 -0
- data/doc/css/common.css +1 -0
- data/doc/css/full_list.css +58 -0
- data/doc/css/style.css +503 -0
- data/doc/file.README.html +432 -0
- data/doc/file_list.html +59 -0
- data/doc/frames.html +22 -0
- data/doc/images/enhanced-error.png +0 -0
- data/doc/images/enhanced-spec.png +0 -0
- data/doc/index.html +432 -0
- data/doc/js/app.js +344 -0
- data/doc/js/full_list.js +242 -0
- data/doc/js/jquery.js +4 -0
- data/doc/method_list.html +286 -0
- data/doc/top-level-namespace.html +112 -0
- data/enhanced_errors.gemspec +6 -3
- data/examples/example_spec.rb +2 -2
- data/lib/enhanced_errors.rb +43 -30
- metadata +58 -6
data/doc/index.html
ADDED
@@ -0,0 +1,432 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<meta charset="UTF-8">
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
6
|
+
<title>
|
7
|
+
File: README
|
8
|
+
|
9
|
+
— Documentation by YARD 0.9.37
|
10
|
+
|
11
|
+
</title>
|
12
|
+
|
13
|
+
<link rel="stylesheet" href="css/style.css" type="text/css" />
|
14
|
+
|
15
|
+
<link rel="stylesheet" href="css/common.css" type="text/css" />
|
16
|
+
|
17
|
+
<script type="text/javascript">
|
18
|
+
pathId = "README";
|
19
|
+
relpath = '';
|
20
|
+
</script>
|
21
|
+
|
22
|
+
|
23
|
+
<script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
|
24
|
+
|
25
|
+
<script type="text/javascript" charset="utf-8" src="js/app.js"></script>
|
26
|
+
|
27
|
+
|
28
|
+
</head>
|
29
|
+
<body>
|
30
|
+
<div class="nav_wrap">
|
31
|
+
<iframe id="nav" src="class_list.html?1"></iframe>
|
32
|
+
<div id="resizer"></div>
|
33
|
+
</div>
|
34
|
+
|
35
|
+
<div id="main" tabindex="-1">
|
36
|
+
<div id="header">
|
37
|
+
<div id="menu">
|
38
|
+
|
39
|
+
<a href="_index.html">Index</a> »
|
40
|
+
<span class="title">File: README</span>
|
41
|
+
|
42
|
+
</div>
|
43
|
+
|
44
|
+
<div id="search">
|
45
|
+
|
46
|
+
<a class="full_list_link" id="class_list_link"
|
47
|
+
href="class_list.html">
|
48
|
+
|
49
|
+
<svg width="24" height="24">
|
50
|
+
<rect x="0" y="4" width="24" height="4" rx="1" ry="1"></rect>
|
51
|
+
<rect x="0" y="12" width="24" height="4" rx="1" ry="1"></rect>
|
52
|
+
<rect x="0" y="20" width="24" height="4" rx="1" ry="1"></rect>
|
53
|
+
</svg>
|
54
|
+
</a>
|
55
|
+
|
56
|
+
</div>
|
57
|
+
<div class="clear"></div>
|
58
|
+
</div>
|
59
|
+
|
60
|
+
<div id="content"><div id='filecontents'>
|
61
|
+
<h1 id="label-EnhancedErrors">EnhancedErrors</h1>
|
62
|
+
|
63
|
+
<h2 id="label-Overview">Overview</h2>
|
64
|
+
|
65
|
+
<p><strong>EnhancedErrors</strong> is a pure Ruby gem that enhances exception messages by capturing and appending variables and their values from the scope where the error was raised.</p>
|
66
|
+
|
67
|
+
<p><strong>EnhancedErrors</strong> leverages Ruby’s built-in <a href="https://ruby-doc.org/core-3.1.0/TracePoint.html">TracePoint</a> feature to provide detailed context for exceptions, making debugging easier without significant performance overhead.</p>
|
68
|
+
|
69
|
+
<p>When an exception is raised, EnhancedErrors captures the surrounding context. It works like this: <br></p>
|
70
|
+
|
71
|
+
<h4 id="label-Enhanced+Exception+In+Code-3A">Enhanced Exception In Code:</h4>
|
72
|
+
|
73
|
+
<pre class="code ruby"><code class="ruby">
|
74
|
+
<span class='id identifier rubyid_require'>require</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>enhanced_errors</span><span class='tstring_end'>'</span></span>
|
75
|
+
<span class='id identifier rubyid_require'>require</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>awesome_print</span><span class='tstring_end'>'</span></span> <span class='comment'># Optional, for better output
|
76
|
+
</span>
|
77
|
+
<span class='const'><span class='object_link'><a href="EnhancedErrors.html" title="EnhancedErrors (class)">EnhancedErrors</a></span></span><span class='period'>.</span><span class='id identifier rubyid_enhance!'><span class='object_link'><a href="EnhancedErrors.html#enhance!-class_method" title="EnhancedErrors.enhance! (method)">enhance!</a></span></span>
|
78
|
+
|
79
|
+
<span class='kw'>def</span> <span class='id identifier rubyid_foo'>foo</span>
|
80
|
+
<span class='kw'>begin</span>
|
81
|
+
<span class='id identifier rubyid_myvar'>myvar</span> <span class='op'>=</span> <span class='int'>0</span>
|
82
|
+
<span class='ivar'>@myinstance</span> <span class='op'>=</span> <span class='int'>10</span>
|
83
|
+
<span class='id identifier rubyid_foo'>foo</span> <span class='op'>=</span> <span class='ivar'>@myinstance</span> <span class='op'>/</span> <span class='id identifier rubyid_myvar'>myvar</span>
|
84
|
+
<span class='kw'>rescue</span> <span class='op'>=></span> <span class='id identifier rubyid_e'>e</span>
|
85
|
+
<span class='id identifier rubyid_puts'>puts</span> <span class='id identifier rubyid_e'>e</span><span class='period'>.</span><span class='id identifier rubyid_message'>message</span>
|
86
|
+
<span class='kw'>end</span>
|
87
|
+
<span class='kw'>end</span>
|
88
|
+
|
89
|
+
<span class='id identifier rubyid_foo'>foo</span>
|
90
|
+
</code></pre>
|
91
|
+
|
92
|
+
<h5 id="label-Output-3A">Output:</h5>
|
93
|
+
|
94
|
+
<p><img src=“./doc/images/enhanced-error.png” style=“height: 171px; width: 440px;”></img></p>
|
95
|
+
|
96
|
+
<p><br></p>
|
97
|
+
|
98
|
+
<h4 id="label-Enhanced+Exception+In+Specs-3A">Enhanced Exception In Specs:</h4>
|
99
|
+
|
100
|
+
<pre class="code ruby"><code class="ruby"><span class='id identifier rubyid_describe'>describe</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>attains enlightenment</span><span class='tstring_end'>'</span></span> <span class='kw'>do</span>
|
101
|
+
<span class='id identifier rubyid_let'>let</span><span class='lparen'>(</span><span class='symbol'>:the_matrix</span><span class='rparen'>)</span> <span class='lbrace'>{</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>code rains, dramatically</span><span class='tstring_end'>'</span></span> <span class='rbrace'>}</span>
|
102
|
+
|
103
|
+
<span class='id identifier rubyid_before'>before</span><span class='lparen'>(</span><span class='symbol'>:each</span><span class='rparen'>)</span> <span class='kw'>do</span>
|
104
|
+
<span class='ivar'>@spoon</span> <span class='op'>=</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>there is no spoon</span><span class='tstring_end'>'</span></span>
|
105
|
+
<span class='kw'>end</span>
|
106
|
+
|
107
|
+
<span class='id identifier rubyid_it'>it</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>in the matrix</span><span class='tstring_end'>'</span></span> <span class='kw'>do</span>
|
108
|
+
<span class='comment'>#activate memoized item
|
109
|
+
</span> <span class='id identifier rubyid_the_matrix'>the_matrix</span>
|
110
|
+
<span class='id identifier rubyid_stop'>stop</span> <span class='op'>=</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>bullets</span><span class='tstring_end'>'</span></span>
|
111
|
+
<span class='id identifier rubyid_raise'>raise</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>No!</span><span class='tstring_end'>'</span></span>
|
112
|
+
<span class='kw'>end</span>
|
113
|
+
<span class='kw'>end</span>
|
114
|
+
</code></pre>
|
115
|
+
|
116
|
+
<h4 id="label-Output-3A">Output:</h4>
|
117
|
+
|
118
|
+
<p><img src=“./doc/images/enhanced-spec.png” style=“height: 426px; width: 712px;”></img></p>
|
119
|
+
|
120
|
+
<h2 id="label-Features">Features</h2>
|
121
|
+
<ul><li>
|
122
|
+
<p><strong>Pure Ruby</strong>: No external dependencies or C extensions.</p>
|
123
|
+
</li><li>
|
124
|
+
<p><strong>Standalone</strong>: Does not rely on any external libraries.</p>
|
125
|
+
</li><li>
|
126
|
+
<p><strong>Lightweight</strong>: Minimal performance impact, as tracing is only active during exception raising.</p>
|
127
|
+
</li><li>
|
128
|
+
<p><strong>Customizable Output</strong>: Supports multiple output formats (<code>:json</code>, <code>:plaintext</code>, <code>:terminal</code>).</p>
|
129
|
+
</li><li>
|
130
|
+
<p><strong>Flexible Hooks</strong>: Redact or modifying captured data via the <code>on_capture</code> hook.</p>
|
131
|
+
</li><li>
|
132
|
+
<p><strong>Environment-Based Defaults</strong>: For Rails apps, automatically adjusts settings based on the environment (<code>development</code>, <code>test</code>, <code>production</code>, <code>ci</code>).</p>
|
133
|
+
</li><li>
|
134
|
+
<p><strong>Pre-Populated Skip List</strong>: Comes with predefined skip lists to exclude irrelevant variables from being captured.</p>
|
135
|
+
</li><li>
|
136
|
+
<p><strong>Capture Levels</strong>: Supports <code>info</code> and <code>debug</code> levels, where <code>debug</code> level ignores the skip lists for more comprehensive data capture.</p>
|
137
|
+
</li><li>
|
138
|
+
<p><strong>Capture Types</strong>: Captures variables from the first <code>raise</code> and the last <code>rescue</code> for an exception by default.</p>
|
139
|
+
</li><li>
|
140
|
+
<p><strong>No dependencies</strong>: EnhancedErrors does not <strong><em>require</em></strong> any dependencies–it uses <a href="https://github.com/awesome-print/awesome_print">awesome_print</a> for nicer output if it is installed and available.</p>
|
141
|
+
</li></ul>
|
142
|
+
|
143
|
+
<p>EnhancedErrors has a few big use-cases:</p>
|
144
|
+
<ul><li>
|
145
|
+
<p><strong>Catch Data-driven bugs</strong>. For example, if, while processing a 10 gig file, you get an error, you can’t just re-run the code with a debugger. You also can’t just print out all the data, because it’s too big. You want to know what the data was the cause of the error. Ideally, without long instrument-re-run-fix loops. If your logging didn’t capture the data, normally, you’d be stuck.</p>
|
146
|
+
</li><li>
|
147
|
+
<p><strong>Debug</strong> a complex application erroring deep in the stack when you can’t tell where the error originates</p>
|
148
|
+
</li><li>
|
149
|
+
<p><strong>Faster TDD</strong> - Often, you won’t have to re-run to see an error–you can go straight to the fix.</p>
|
150
|
+
</li><li>
|
151
|
+
<p><strong>Faster CI -> Fix loop</strong>. When a bug happens in CI, usually there’s a step where you first reproduce it locally. EnhancedErrors can help you skip that step.</p>
|
152
|
+
</li><li>
|
153
|
+
<p><strong>Faster debugging</strong>. In general, you can skip the add-instrumentation step and jump to the fix.</p>
|
154
|
+
</li><li>
|
155
|
+
<p><strong>Heisenbugs</strong> - bugs that disappear when you try to debug them. EnhancedErrors can help you capture the data that causes the bug before it disappears.</p>
|
156
|
+
</li><li>
|
157
|
+
<p><strong>Unknown Unknowns</strong> - you can’t pre-emptively log variables from failure cases you never imagined.</p>
|
158
|
+
</li><li>
|
159
|
+
<p><strong>Cron jobs</strong> and <strong>daemons</strong> - when it fails for unknown reasons at 4am, check the log and fix–it probably has what you need.</p>
|
160
|
+
</li></ul>
|
161
|
+
|
162
|
+
<h2 id="label-Installation">Installation</h2>
|
163
|
+
|
164
|
+
<p>Add this line to your <code>Gemfile</code>:</p>
|
165
|
+
|
166
|
+
<pre class="code ruby"><code class="ruby"><span class='id identifier rubyid_gem'>gem</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>enhanced_errors</span><span class='tstring_end'>'</span></span>
|
167
|
+
</code></pre>
|
168
|
+
|
169
|
+
<p>Then execute:</p>
|
170
|
+
|
171
|
+
<pre class="code ruby"><code class="ruby">$ bundle install
|
172
|
+
</code></pre>
|
173
|
+
|
174
|
+
<p>Or install it yourself with:</p>
|
175
|
+
|
176
|
+
<pre class="code ruby"><code class="ruby">$ gem install enhanced_errors
|
177
|
+
</code></pre>
|
178
|
+
|
179
|
+
<h2 id="label-Basic+Usage">Basic Usage</h2>
|
180
|
+
|
181
|
+
<p>To enable EnhancedErrors, call the <code>enhance!</code> method:</p>
|
182
|
+
|
183
|
+
<pre class="code ruby"><code class="ruby"><span class='comment'># For a rails app, put this in an initializer, or spec_helper.rb
|
184
|
+
</span><span class='comment'># ex: config/initializers/enhanced_errors.rb
|
185
|
+
</span>
|
186
|
+
<span class='id identifier rubyid_require'>require</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>awesome_print</span><span class='tstring_end'>'</span></span> <span class='comment'># Optional, for better output
|
187
|
+
</span><span class='const'><span class='object_link'><a href="EnhancedErrors.html" title="EnhancedErrors (class)">EnhancedErrors</a></span></span><span class='period'>.</span><span class='id identifier rubyid_enhance!'><span class='object_link'><a href="EnhancedErrors.html#enhance!-class_method" title="EnhancedErrors.enhance! (method)">enhance!</a></span></span>
|
188
|
+
|
189
|
+
<span class='comment'># -> now your error messages will have variables and their values appended to them.
|
190
|
+
</span></code></pre>
|
191
|
+
|
192
|
+
<p>This activates the TracePoint to start capturing exceptions and their surrounding context.</p>
|
193
|
+
|
194
|
+
<h3 id="label-Configuration+Options">Configuration Options</h3>
|
195
|
+
|
196
|
+
<p>You can pass configuration options to <code>enhance!</code>:</p>
|
197
|
+
|
198
|
+
<pre class="code ruby"><code class="ruby"><span class='const'><span class='object_link'><a href="EnhancedErrors.html" title="EnhancedErrors (class)">EnhancedErrors</a></span></span><span class='period'>.</span><span class='id identifier rubyid_enhance!'><span class='object_link'><a href="EnhancedErrors.html#enhance!-class_method" title="EnhancedErrors.enhance! (method)">enhance!</a></span></span><span class='lparen'>(</span><span class='label'>enabled:</span> <span class='kw'>true</span><span class='comma'>,</span> <span class='label'>max_length:</span> <span class='int'>2000</span><span class='rparen'>)</span> <span class='kw'>do</span>
|
199
|
+
<span class='comment'># Additional configuration here
|
200
|
+
</span> <span class='id identifier rubyid_add_to_skip_list'>add_to_skip_list</span> <span class='symbol'>:@instance_variable_to_skip</span><span class='comma'>,</span> <span class='symbol'>:local_to_skip</span>
|
201
|
+
<span class='kw'>end</span>
|
202
|
+
</code></pre>
|
203
|
+
<ul><li>
|
204
|
+
<p><code>add_to_skip_list</code>: Variables to ignore, as symbols. ex: :@instance_variable_to_skip, :local_to_skip`</p>
|
205
|
+
</li><li>
|
206
|
+
<p><code>enabled</code>: Enables or disables the enhancement (default: <code>true</code>).</p>
|
207
|
+
</li><li>
|
208
|
+
<p><code>max_length</code>: Sets the maximum length of the enhanced message (default: <code>2500</code>).</p>
|
209
|
+
</li></ul>
|
210
|
+
|
211
|
+
<h3 id="label-Environment-Based+Defaults">Environment-Based Defaults</h3>
|
212
|
+
|
213
|
+
<p>EnhancedErrors adjusts its default settings based on the environment:</p>
|
214
|
+
<ul><li>
|
215
|
+
<p><strong>Development/Test</strong>:</p>
|
216
|
+
<ul><li>
|
217
|
+
<p>Default Output format: <code>:terminal</code></p>
|
218
|
+
</li><li>
|
219
|
+
<p>Terminal Color output: Enabled</p>
|
220
|
+
</li></ul>
|
221
|
+
</li><li>
|
222
|
+
<p><strong>Production</strong>:</p>
|
223
|
+
<ul><li>
|
224
|
+
<p>Output format: <code>:json</code></p>
|
225
|
+
</li><li>
|
226
|
+
<p>Terminal Color output: Disabled</p>
|
227
|
+
</li></ul>
|
228
|
+
</li><li>
|
229
|
+
<p><strong>CI Environment</strong>:</p>
|
230
|
+
<ul><li>
|
231
|
+
<p>Output format: <code>:plaintext</code></p>
|
232
|
+
</li><li>
|
233
|
+
<p>Color output: Disabled</p>
|
234
|
+
</li></ul>
|
235
|
+
</li></ul>
|
236
|
+
|
237
|
+
<p>The environment is determined by <code>ENV['RAILS_ENV']</code>, <code>ENV['RACK_ENV']</code>, or detected CI environment variables like: - <code>CI=true</code></p>
|
238
|
+
|
239
|
+
<h3 id="label-Output+Formats">Output Formats</h3>
|
240
|
+
|
241
|
+
<p>You can customize the output format:</p>
|
242
|
+
<ul><li>
|
243
|
+
<p><strong><code>:json</code></strong>: Outputs the captured data in JSON format.</p>
|
244
|
+
</li><li>
|
245
|
+
<p><strong><code>:plaintext</code></strong>: Outputs plain text without color codes.</p>
|
246
|
+
</li><li>
|
247
|
+
<p><strong><code>:terminal</code></strong>: Outputs text with terminal color codes.</p>
|
248
|
+
</li></ul>
|
249
|
+
|
250
|
+
<p>Example:</p>
|
251
|
+
|
252
|
+
<pre class="code ruby"><code class="ruby"><span class='const'><span class='object_link'><a href="EnhancedErrors.html" title="EnhancedErrors (class)">EnhancedErrors</a></span></span><span class='period'>.</span><span class='id identifier rubyid_format'><span class='object_link'><a href="EnhancedErrors.html#format-class_method" title="EnhancedErrors.format (method)">format</a></span></span><span class='lparen'>(</span><span class='id identifier rubyid_captured_bindings'>captured_bindings</span><span class='comma'>,</span> <span class='symbol'>:json</span><span class='rparen'>)</span>
|
253
|
+
</code></pre>
|
254
|
+
|
255
|
+
<h3 id="label-Customizing+Data+Capture">Customizing Data Capture</h3>
|
256
|
+
|
257
|
+
<h4 id="label-Using+on_capture">Using <code>on_capture</code></h4>
|
258
|
+
|
259
|
+
<p>The <code>on_capture</code> hook allows you to modify or redact data as it is captured. For each captured binding it yields out a hash with the structure below. Modify it as needed and return the modified hash.</p>
|
260
|
+
|
261
|
+
<pre class="code ruby"><code class="ruby">{
|
262
|
+
source: source_location,
|
263
|
+
object: Object source of error,
|
264
|
+
library: true or false,
|
265
|
+
method_and_args: method_and_args,
|
266
|
+
variables: {
|
267
|
+
locals: locals,
|
268
|
+
instances: instances,
|
269
|
+
lets: lets,
|
270
|
+
globals: globals
|
271
|
+
},
|
272
|
+
exception: exception.class.name,
|
273
|
+
capture_type: capture_type # 'raise' or 'rescue'
|
274
|
+
}
|
275
|
+
</code></pre>
|
276
|
+
|
277
|
+
<pre class="code ruby"><code class="ruby"><span class='const'><span class='object_link'><a href="EnhancedErrors.html" title="EnhancedErrors (class)">EnhancedErrors</a></span></span><span class='period'>.</span><span class='id identifier rubyid_on_capture'><span class='object_link'><a href="EnhancedErrors.html#on_capture-class_method" title="EnhancedErrors.on_capture (method)">on_capture</a></span></span> <span class='kw'>do</span> <span class='op'>|</span><span class='id identifier rubyid_binding_info'>binding_info</span><span class='op'>|</span>
|
278
|
+
<span class='comment'># Redact sensitive data
|
279
|
+
</span> <span class='kw'>if</span> <span class='id identifier rubyid_binding_info'>binding_info</span><span class='lbracket'>[</span><span class='symbol'>:variables</span><span class='rbracket'>]</span><span class='lbracket'>[</span><span class='symbol'>:locals</span><span class='rbracket'>]</span><span class='lbracket'>[</span><span class='symbol'>:password</span><span class='rbracket'>]</span>
|
280
|
+
<span class='id identifier rubyid_binding_info'>binding_info</span><span class='lbracket'>[</span><span class='symbol'>:variables</span><span class='rbracket'>]</span><span class='lbracket'>[</span><span class='symbol'>:locals</span><span class='rbracket'>]</span><span class='lbracket'>[</span><span class='symbol'>:password</span><span class='rbracket'>]</span> <span class='op'>=</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>[REDACTED]</span><span class='tstring_end'>'</span></span>
|
281
|
+
<span class='kw'>end</span>
|
282
|
+
<span class='id identifier rubyid_binding_info'>binding_info</span> <span class='comment'># Return the modified binding_info
|
283
|
+
</span><span class='kw'>end</span>
|
284
|
+
</code></pre>
|
285
|
+
|
286
|
+
<h4 id="label-Using+eligible_for_capture">Using <code>eligible_for_capture</code></h4>
|
287
|
+
|
288
|
+
<p>The <code>eligible_for_capture</code> hook yields an Exception, and allows you to decide whether you want to capture it or not. By default, all exceptions are captured. When the block result is true, the error will be captured. Error capture is relatively cheap, but ignoring errors you don’t care about makes it almost totally free. One use-case for eligible_for_capture is to run a string or regexp off a setting flag, which lets you turn on and off what you capture without redeploying.</p>
|
289
|
+
|
290
|
+
<pre class="code ruby"><code class="ruby"><span class='const'><span class='object_link'><a href="EnhancedErrors.html" title="EnhancedErrors (class)">EnhancedErrors</a></span></span><span class='period'>.</span><span class='id identifier rubyid_eligible_for_capture'><span class='object_link'><a href="EnhancedErrors.html#eligible_for_capture-class_method" title="EnhancedErrors.eligible_for_capture (method)">eligible_for_capture</a></span></span> <span class='kw'>do</span> <span class='op'>|</span><span class='id identifier rubyid_exception'>exception</span><span class='op'>|</span>
|
291
|
+
<span class='id identifier rubyid_exception'>exception</span><span class='period'>.</span><span class='id identifier rubyid_class'>class</span><span class='period'>.</span><span class='id identifier rubyid_name'>name</span> <span class='op'>==</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>ExceptionIWantTOCatch</span><span class='tstring_end'>'</span></span>
|
292
|
+
<span class='kw'>end</span>
|
293
|
+
</code></pre>
|
294
|
+
|
295
|
+
<h4 id="label-Using+on_format">Using <code>on_format</code></h4>
|
296
|
+
|
297
|
+
<p><code>on_format</code> is the last stop for the message string that will be appended to <code>exception.message</code>.</p>
|
298
|
+
|
299
|
+
<p>Here it can be encrypted, rewritten, or otherwise modified.</p>
|
300
|
+
|
301
|
+
<pre class="code ruby"><code class="ruby"><span class='const'><span class='object_link'><a href="EnhancedErrors.html" title="EnhancedErrors (class)">EnhancedErrors</a></span></span><span class='period'>.</span><span class='id identifier rubyid_on_format'><span class='object_link'><a href="EnhancedErrors.html#on_format-class_method" title="EnhancedErrors.on_format (method)">on_format</a></span></span> <span class='kw'>do</span> <span class='op'>|</span><span class='id identifier rubyid_formatted_string'>formatted_string</span><span class='op'>|</span>
|
302
|
+
<span class='tstring'><span class='tstring_beg'>"</span><span class='tstring_content'>---whatever--- </span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_formatted_string'>formatted_string</span><span class='embexpr_end'>}</span><span class='tstring_content'> ---whatever---</span><span class='tstring_end'>"</span></span>
|
303
|
+
<span class='kw'>end</span>
|
304
|
+
</code></pre>
|
305
|
+
|
306
|
+
<h4 id="label-Applying+a+Variable+Skip+List">Applying a Variable Skip List</h4>
|
307
|
+
|
308
|
+
<p>EnhancedErrors comes with predefined skip lists to exclude sensitive or irrelevant variables. By default, the skip list is used to remove a lot of framework noise from Rails and RSpec. You can add additional variables to the skip list as needed:</p>
|
309
|
+
|
310
|
+
<pre class="code ruby"><code class="ruby">
|
311
|
+
<span class='const'><span class='object_link'><a href="EnhancedErrors.html" title="EnhancedErrors (class)">EnhancedErrors</a></span></span><span class='period'>.</span><span class='id identifier rubyid_enhance!'><span class='object_link'><a href="EnhancedErrors.html#enhance!-class_method" title="EnhancedErrors.enhance! (method)">enhance!</a></span></span> <span class='kw'>do</span>
|
312
|
+
<span class='id identifier rubyid_add_to_skip_list'>add_to_skip_list</span> <span class='symbol'>:@variable_to_skip</span>
|
313
|
+
<span class='kw'>end</span>
|
314
|
+
</code></pre>
|
315
|
+
|
316
|
+
<p>The skip list is pre-populated with common variables to exclude and can be extended based on your application’s requirements.</p>
|
317
|
+
|
318
|
+
<h3 id="label-Capture+Levels">Capture Levels</h3>
|
319
|
+
|
320
|
+
<p>EnhancedErrors supports different capture levels to control the verbosity of the captured data:</p>
|
321
|
+
<ul><li>
|
322
|
+
<p><strong>Info Level</strong>: Respects the skip list, excluding predefined sensitive or irrelevant variables. Global variables are ignored.</p>
|
323
|
+
</li><li>
|
324
|
+
<p><strong>Debug Level</strong>: Ignores the skip lists, capturing all variables including those typically excluded and global variables. Global variables,</p>
|
325
|
+
</li></ul>
|
326
|
+
|
327
|
+
<p><strong>Default Behavior</strong>: By default, <code>info</code> level is used, which excludes variables in the skip list to protect sensitive information. In <code>debug</code> mode, the skip lists are ignored to provide more comprehensive data, which is useful during development but should be used cautiously to avoid exposing sensitive data. The info mode is recommended.</p>
|
328
|
+
|
329
|
+
<h3 id="label-Capture+Types">Capture Types</h3>
|
330
|
+
|
331
|
+
<p>EnhancedErrors differentiates between two types of capture events:</p>
|
332
|
+
<ul><li>
|
333
|
+
<p><strong><code>raise</code></strong>: Captures the context when an exception is initially raised.</p>
|
334
|
+
</li><li>
|
335
|
+
<p><strong><code>rescue</code></strong>: Captures the context when an exception is last rescued.</p>
|
336
|
+
</li></ul>
|
337
|
+
|
338
|
+
<p><strong>Default Behavior</strong>: By default, EnhancedErrors returns the first <code>raise</code> and the last <code>rescue</code> event for each exception. This provides a clear picture of where and how the exception was handled.</p>
|
339
|
+
|
340
|
+
<h3 id="label-Example-3A+Redacting+Sensitive+Information">Example: Redacting Sensitive Information</h3>
|
341
|
+
|
342
|
+
<pre class="code ruby"><code class="ruby"><span class='const'><span class='object_link'><a href="EnhancedErrors.html" title="EnhancedErrors (class)">EnhancedErrors</a></span></span><span class='period'>.</span><span class='id identifier rubyid_on_capture'><span class='object_link'><a href="EnhancedErrors.html#on_capture-class_method" title="EnhancedErrors.on_capture (method)">on_capture</a></span></span> <span class='kw'>do</span> <span class='op'>|</span><span class='id identifier rubyid_binding_info'>binding_info</span><span class='op'>|</span>
|
343
|
+
<span class='id identifier rubyid_sensitive_keys'>sensitive_keys</span> <span class='op'>=</span> <span class='lbracket'>[</span><span class='symbol'>:password</span><span class='comma'>,</span> <span class='symbol'>:ssn</span><span class='comma'>,</span> <span class='symbol'>:health_info</span><span class='rbracket'>]</span>
|
344
|
+
<span class='id identifier rubyid_sensitive_keys'>sensitive_keys</span><span class='period'>.</span><span class='id identifier rubyid_each'>each</span> <span class='kw'>do</span> <span class='op'>|</span><span class='id identifier rubyid_key'>key</span><span class='op'>|</span>
|
345
|
+
<span class='kw'>if</span> <span class='id identifier rubyid_binding_info'>binding_info</span><span class='lbracket'>[</span><span class='symbol'>:variables</span><span class='rbracket'>]</span><span class='lbracket'>[</span><span class='symbol'>:locals</span><span class='rbracket'>]</span><span class='lbracket'>[</span><span class='id identifier rubyid_key'>key</span><span class='rbracket'>]</span>
|
346
|
+
<span class='id identifier rubyid_binding_info'>binding_info</span><span class='lbracket'>[</span><span class='symbol'>:variables</span><span class='rbracket'>]</span><span class='lbracket'>[</span><span class='symbol'>:locals</span><span class='rbracket'>]</span><span class='lbracket'>[</span><span class='id identifier rubyid_key'>key</span><span class='rbracket'>]</span> <span class='op'>=</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>[REDACTED]</span><span class='tstring_end'>'</span></span>
|
347
|
+
<span class='kw'>end</span>
|
348
|
+
<span class='kw'>end</span>
|
349
|
+
<span class='id identifier rubyid_binding_info'>binding_info</span>
|
350
|
+
<span class='kw'>end</span>
|
351
|
+
</code></pre>
|
352
|
+
|
353
|
+
<h3 id="label-Example-3A+Encrypting+Data+in+Custom+Format">Example: Encrypting Data in Custom Format</h3>
|
354
|
+
|
355
|
+
<pre class="code ruby"><code class="ruby"><span class='comment'># config/initializers/encryption.rb
|
356
|
+
</span>
|
357
|
+
<span class='id identifier rubyid_require'>require</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>active_support</span><span class='tstring_end'>'</span></span>
|
358
|
+
|
359
|
+
<span class='comment'># Retrieve the encryption key from Rails credentials or environment variables
|
360
|
+
</span><span class='const'>ENCRYPTION_KEY</span> <span class='op'>=</span> <span class='const'>Rails</span><span class='period'>.</span><span class='id identifier rubyid_application'>application</span><span class='period'>.</span><span class='id identifier rubyid_credentials'>credentials</span><span class='period'>.</span><span class='id identifier rubyid_encryption_key'>encryption_key</span> <span class='op'>||</span> <span class='const'>ENV</span><span class='lbracket'>[</span><span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>ENCRYPTION_KEY</span><span class='tstring_end'>'</span></span><span class='rbracket'>]</span>
|
361
|
+
|
362
|
+
<span class='comment'># It's recommended to use a 256-bit key (32 bytes)
|
363
|
+
</span><span class='comment'># If your key is in hex or another format, ensure it's properly decoded
|
364
|
+
</span><span class='id identifier rubyid_key'>key</span> <span class='op'>=</span> <span class='const'>ActiveSupport</span><span class='op'>::</span><span class='const'>KeyGenerator</span><span class='period'>.</span><span class='id identifier rubyid_new'>new</span><span class='lparen'>(</span><span class='const'>ENCRYPTION_KEY</span><span class='rparen'>)</span><span class='period'>.</span><span class='id identifier rubyid_generate_key'>generate_key</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>enhanced_errors</span><span class='tstring_end'>'</span></span><span class='comma'>,</span> <span class='int'>32</span><span class='rparen'>)</span>
|
365
|
+
<span class='const'>ENCRYPTOR</span> <span class='op'>=</span> <span class='const'>ActiveSupport</span><span class='op'>::</span><span class='const'>MessageEncryptor</span><span class='period'>.</span><span class='id identifier rubyid_new'>new</span><span class='lparen'>(</span><span class='id identifier rubyid_key'>key</span><span class='rparen'>)</span>
|
366
|
+
</code></pre>
|
367
|
+
|
368
|
+
<pre class="code ruby"><code class="ruby">
|
369
|
+
<span class='id identifier rubyid_require_relative'>require_relative</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>path_to/enhanced_errors</span><span class='tstring_end'>'</span></span> <span class='comment'># Adjust the path accordingly
|
370
|
+
</span><span class='id identifier rubyid_require'>require</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>active_support/message_encryptor</span><span class='tstring_end'>'</span></span>
|
371
|
+
|
372
|
+
<span class='comment'># Ensure the encryptor is initialized
|
373
|
+
</span><span class='id identifier rubyid_encryptor'>encryptor</span> <span class='op'>=</span> <span class='const'>ENCRYPTOR</span>
|
374
|
+
|
375
|
+
<span class='const'><span class='object_link'><a href="EnhancedErrors.html" title="EnhancedErrors (class)">EnhancedErrors</a></span></span><span class='period'>.</span><span class='id identifier rubyid_on_format'><span class='object_link'><a href="EnhancedErrors.html#on_format-class_method" title="EnhancedErrors.on_format (method)">on_format</a></span></span> <span class='op'>=</span> <span class='id identifier rubyid_lambda'>lambda</span> <span class='kw'>do</span> <span class='op'>|</span><span class='id identifier rubyid_formatted_string'>formatted_string</span><span class='op'>|</span>
|
376
|
+
<span class='id identifier rubyid_encrypted_data'>encrypted_data</span> <span class='op'>=</span> <span class='id identifier rubyid_encryptor'>encryptor</span><span class='period'>.</span><span class='id identifier rubyid_encrypt_and_sign'>encrypt_and_sign</span><span class='lparen'>(</span><span class='id identifier rubyid_formatted_string'>formatted_string</span><span class='rparen'>)</span>
|
377
|
+
<span class='id identifier rubyid_encrypted_base64'>encrypted_base64</span> <span class='op'>=</span> <span class='const'>Base64</span><span class='period'>.</span><span class='id identifier rubyid_strict_encode64'>strict_encode64</span><span class='lparen'>(</span><span class='id identifier rubyid_encrypted_data'>encrypted_data</span><span class='rparen'>)</span>
|
378
|
+
<span class='tstring'><span class='tstring_beg'>"</span><span class='tstring_content'>ENCRYPTED[</span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_encrypted_base64'>encrypted_base64</span><span class='embexpr_end'>}</span><span class='tstring_content'>]</span><span class='tstring_end'>"</span></span>
|
379
|
+
<span class='kw'>end</span>
|
380
|
+
</code></pre>
|
381
|
+
|
382
|
+
<h2 id="label-How+It+Works">How It Works</h2>
|
383
|
+
|
384
|
+
<p>EnhancedErrors uses Ruby’s <code>TracePoint</code> to listen for <code>:raise</code> and <code>:rescue</code> events. When an exception is raised or rescued, it captures:</p>
|
385
|
+
<ul><li>
|
386
|
+
<p><strong>Local Variables</strong>: Variables local to the scope where the exception occurred.</p>
|
387
|
+
</li><li>
|
388
|
+
<p><strong>Instance Variables</strong>: Instance variables of the object.</p>
|
389
|
+
</li><li>
|
390
|
+
<p><strong>Method and Arguments</strong>: The method name and its arguments.</p>
|
391
|
+
</li><li>
|
392
|
+
<p><strong>Let Variables</strong>: RSpec let variables, if applicable. Only memoized (evaluated) let variables are captured.</p>
|
393
|
+
</li><li>
|
394
|
+
<p><strong>Global Variables</strong>: Global variables, in debug mode.</p>
|
395
|
+
</li></ul>
|
396
|
+
|
397
|
+
<p>The captured data includes a <code>capture_type</code> field indicating whether the data was captured during a <code>raise</code> or <code>rescue</code> event. By default, EnhancedErrors returns the first <code>raise</code> and the last <code>rescue</code> event for each exception, providing a clear trace of the exception lifecycle.</p>
|
398
|
+
|
399
|
+
<p>The captured data is then appended to the exception’s message, providing rich context for debugging.</p>
|
400
|
+
|
401
|
+
<h2 id="label-Awesome+Print">Awesome Print</h2>
|
402
|
+
|
403
|
+
<p>EnhancedErrors automatically uses the <a href="https://github.com/awesome-print/awesome_print">awesome_print</a> gem to format the captured data, <strong><em>if</em></strong> it is installed and available. If not, error enhancement will work, but the output may be less pretty (er, awesome). AwesomePrint is not required directly by EnhancedErrors, so you will need to add it to your Gemfile if you want to use it.</p>
|
404
|
+
|
405
|
+
<pre class="code ruby"><code class="ruby"><span class='id identifier rubyid_gem'>gem</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>awesome_print</span><span class='tstring_end'>'</span></span>
|
406
|
+
</code></pre>
|
407
|
+
|
408
|
+
<h2 id="label-Performance+Considerations">Performance Considerations</h2>
|
409
|
+
<ul><li>
|
410
|
+
<p><strong>Minimal Overhead</strong>: Since TracePoint is only activated during exception raising and rescuing, the performance impact is negligible during normal operation.</p>
|
411
|
+
</li><li>
|
412
|
+
<p><strong>Production Safe</strong>: The gem is designed to be safe for production use, giving you valuable insights without compromising performance.</p>
|
413
|
+
</li></ul>
|
414
|
+
|
415
|
+
<h2 id="label-Contributing">Contributing</h2>
|
416
|
+
|
417
|
+
<p>Bug reports and pull requests are welcome on GitHub at <a href="https://github.com/your_username/enhanced_errors">github.com/your_username/enhanced_errors</a>.</p>
|
418
|
+
|
419
|
+
<h2 id="label-License">License</h2>
|
420
|
+
|
421
|
+
<p>The gem is available as open-source under the terms of the <a href="https://opensource.org/licenses/MIT">MIT License</a>.</p>
|
422
|
+
</div></div>
|
423
|
+
|
424
|
+
<div id="footer">
|
425
|
+
Generated on Tue Oct 22 23:16:25 2024 by
|
426
|
+
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
427
|
+
0.9.37 (ruby-3.1.3).
|
428
|
+
</div>
|
429
|
+
|
430
|
+
</div>
|
431
|
+
</body>
|
432
|
+
</html>
|