@@ -34,6 +34,7 @@ local version = "0.4.1"
34
34
local os_date = os.date
35
35
local os_time = os.time
36
36
local debug_getinfo = debug.getinfo
37
+ local debug_getlocal = debug.getlocal
37
38
local math_random = math.random
38
39
local json_encode = json .encode
39
40
local string_format = string.format
@@ -140,7 +141,50 @@ local function _get_server_name()
140
141
return ngx and ngx .var .server_name or " undefined"
141
142
end
142
143
143
- local function backtrace (level )
144
+ local function get_function_details (f )
145
+ local info = debug_getinfo (f , " fSl" )
146
+ return string_format (" %s defined at line %d in %s" , tostring (info .func ), info .linedefined , info .short_src )
147
+ end
148
+
149
+ -- these two are mutually recursive, hence declaration before instantiation
150
+ local json_prep_table , json_prep_value
151
+ json_prep_value = function (v , max_depth )
152
+ if max_depth == nil then
153
+ max_depth = 0
154
+ end
155
+
156
+ local tv = type (v )
157
+ if tv == " function" then
158
+ return get_function_details (v )
159
+ elseif tv == " lightuserdata" or tv == " userdata" or tv == " thread" then
160
+ return tostring (v )
161
+ elseif tv == " table" then
162
+ if max_depth <= 0 then
163
+ return tostring (v )
164
+ else
165
+ return json_prep_table (v , max_depth - 1 )
166
+ end
167
+ else
168
+ return v
169
+ end
170
+ end
171
+
172
+ json_prep_table = function (t , max_depth )
173
+ if max_depth == nil then
174
+ max_depth = 0
175
+ end
176
+
177
+ local out = {}
178
+ for k , v in pairs (t ) do
179
+ local tk = type (k )
180
+ if tk == " number" or tk == " string" then
181
+ out [k ] = json_prep_value (v , max_depth )
182
+ end
183
+ end
184
+ return out
185
+ end
186
+
187
+ local function backtrace (level , capture_frame_locals , max_depth )
144
188
local frames = {}
145
189
146
190
level = level + 1
@@ -151,12 +195,32 @@ local function backtrace(level)
151
195
break
152
196
end
153
197
154
- table_insert ( frames , 1 , {
198
+ local frame = {
155
199
filename = info .short_src ,
156
200
[" function" ] = info .name ,
157
201
lineno = info .currentline ,
158
- })
202
+ }
203
+
204
+ if capture_frame_locals then
205
+ local frame_locals = {}
206
+ local frame_local_idx = 1
207
+ while true do
208
+ local k , v = debug_getlocal (level , frame_local_idx )
209
+ if k == nil then
210
+ break
211
+ end
212
+
213
+ -- unsure whether this tostring is actually necessary
214
+ k = tostring (k )
215
+ if k :sub (0 , 1 ) ~= " (" then -- internal/temp vars start with (, ignore them
216
+ frame_locals [k ] = json_prep_value (v , max_depth )
217
+ end
218
+ frame_local_idx = frame_local_idx + 1
219
+ end
220
+ frame .vars = frame_locals
221
+ end
159
222
223
+ table_insert (frames , 1 , frame )
160
224
level = level + 1
161
225
end
162
226
return { frames = frames }
@@ -253,6 +317,8 @@ function _M.new(self, dsn, conf)
253
317
obj .level = " error"
254
318
obj .verify_ssl = true
255
319
obj .cacert = " ./data/cacert.pem"
320
+ obj .capture_frame_locals = true
321
+ obj .max_depth = 0
256
322
257
323
if conf then
258
324
if conf .tags then
@@ -270,6 +336,14 @@ function _M.new(self, dsn, conf)
270
336
if conf .cacert then
271
337
obj .cacert = conf .cacert
272
338
end
339
+
340
+ if conf .capture_frame_locals == false then
341
+ obj .capture_frame_locals = false
342
+ end
343
+
344
+ if conf .max_depth then
345
+ obj .max_depth = conf .max_depth
346
+ end
273
347
end
274
348
275
349
return setmetatable (obj , mt )
@@ -319,7 +393,7 @@ function _M.captureException(self, exception, conf)
319
393
trace_level = conf .trace_level
320
394
321
395
clear_tab (_json )
322
- exception [1 ].stacktrace = backtrace (trace_level )
396
+ exception [1 ].stacktrace = backtrace (trace_level , self . capture_frame_locals , self . max_depth )
323
397
_json .exception = exception
324
398
_json .message = exception [1 ].value
325
399
@@ -448,7 +522,7 @@ function _M.catcher(self, err)
448
522
449
523
clear_tab (_exception [1 ])
450
524
_exception [1 ].value = err
451
- _exception [1 ].stacktrace = backtrace (catcher_trace_level )
525
+ _exception [1 ].stacktrace = backtrace (catcher_trace_level , self . capture_frame_locals , self . max_depth )
452
526
453
527
clear_tab (_json )
454
528
_json .exception = _exception
0 commit comments