Skip to content

Commit 5a4f997

Browse files
committed
func: and file: prefix for RUBY_DEBUG_LOG_FILTER
`RUBY_DEBUG_LOG_FILTER` specified only function names but this patch also check file names for each log events. If you specify `file:` or `func:` prefix, it's only filter file names or func names (otherwize check both). foo # show log when file or func names are mached with foo func:foo # show log when func name matches foo file:foo # show log when file name matches foo -file:foo,func:bar # show log when file name does not contains foo # and func name matches bar
1 parent 8d57336 commit 5a4f997

File tree

1 file changed

+121
-45
lines changed

1 file changed

+121
-45
lines changed

debug.c

Lines changed: 121 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -273,10 +273,26 @@ ruby_set_debug_option(const char *str)
273273

274274
enum ruby_debug_log_mode ruby_debug_log_mode;
275275

276+
struct debug_log_filter {
277+
enum debug_log_filter_type {
278+
dlf_all,
279+
dlf_file, // "file:..."
280+
dlf_func, // "func:..."
281+
} type;
282+
bool negative;
283+
char str[MAX_DEBUG_LOG_FILTER_LEN];
284+
};
285+
286+
static const char *dlf_type_names[] = {
287+
"all",
288+
"file",
289+
"func",
290+
};
291+
276292
static struct {
277293
char *mem;
278294
unsigned int cnt;
279-
char filters[MAX_DEBUG_LOG_FILTER_NUM][MAX_DEBUG_LOG_FILTER_LEN];
295+
struct debug_log_filter filters[MAX_DEBUG_LOG_FILTER_NUM];
280296
unsigned int filters_num;
281297
rb_nativethread_lock_t lock;
282298
FILE *output;
@@ -288,6 +304,23 @@ RUBY_DEBUG_LOG_MEM_ENTRY(unsigned int index)
288304
return &debug_log.mem[MAX_DEBUG_LOG_MESSAGE_LEN * index];
289305
}
290306

307+
static enum debug_log_filter_type
308+
filter_type(const char *str, int *skiplen)
309+
{
310+
if (strncmp(str, "file:", 5) == 0) {
311+
*skiplen = 5;
312+
return dlf_file;
313+
}
314+
else if(strncmp(str, "func:", 5) == 0) {
315+
*skiplen = 5;
316+
return dlf_func;
317+
}
318+
else {
319+
*skiplen = 0;
320+
return dlf_all;
321+
}
322+
}
323+
291324
static void
292325
setup_debug_log(void)
293326
{
@@ -323,78 +356,121 @@ setup_debug_log(void)
323356
const char *filter_config = getenv("RUBY_DEBUG_LOG_FILTER");
324357
if (filter_config && strlen(filter_config) > 0) {
325358
unsigned int i;
326-
for (i=0; i<MAX_DEBUG_LOG_FILTER_NUM; i++) {
359+
for (i=0; i<MAX_DEBUG_LOG_FILTER_NUM && filter_config; i++) {
360+
size_t len;
361+
const char *str = filter_config;
327362
const char *p;
328-
if ((p = strchr(filter_config, ',')) == NULL) {
329-
if (strlen(filter_config) >= MAX_DEBUG_LOG_FILTER_LEN) {
330-
fprintf(stderr, "too long: %s (max:%d)\n", filter_config, MAX_DEBUG_LOG_FILTER_LEN);
331-
exit(1);
332-
}
333-
strncpy(debug_log.filters[i], filter_config, MAX_DEBUG_LOG_FILTER_LEN - 1);
334-
i++;
335-
break;
363+
364+
if ((p = strchr(str, ',')) == NULL) {
365+
len = strlen(str);
366+
filter_config = NULL;
336367
}
337368
else {
338-
size_t n = p - filter_config;
339-
if (n >= MAX_DEBUG_LOG_FILTER_LEN) {
340-
fprintf(stderr, "too long: %s (max:%d)\n", filter_config, MAX_DEBUG_LOG_FILTER_LEN);
341-
exit(1);
342-
}
343-
strncpy(debug_log.filters[i], filter_config, n);
344-
filter_config = p+1;
369+
len = p - str - 1; // 1 is ','
370+
filter_config = p + 1;
371+
}
372+
373+
// positive/negative
374+
if (*str == '-') {
375+
debug_log.filters[i].negative = true;
376+
str++;
377+
} else if (*str == '+') {
378+
// negative is false on default.
379+
str++;
380+
}
381+
382+
// type
383+
int skiplen;
384+
debug_log.filters[i].type = filter_type(str, &skiplen);
385+
len -= skiplen;
386+
387+
if (len >= MAX_DEBUG_LOG_FILTER_LEN) {
388+
fprintf(stderr, "too long: %s (max:%d)\n", str, MAX_DEBUG_LOG_FILTER_LEN - 1);
389+
exit(1);
345390
}
391+
392+
// body
393+
strncpy(debug_log.filters[i].str, str + skiplen, len);
394+
debug_log.filters[i].str[len] = 0;
346395
}
347396
debug_log.filters_num = i;
397+
348398
for (i=0; i<debug_log.filters_num; i++) {
349-
fprintf(stderr, "RUBY_DEBUG_LOG_FILTER[%d]=%s\n", i, debug_log.filters[i]);
399+
fprintf(stderr, "RUBY_DEBUG_LOG_FILTER[%d]=%s (%s%s)\n", i,
400+
debug_log.filters[i].str,
401+
debug_log.filters[i].negative ? "-" : "",
402+
dlf_type_names[debug_log.filters[i].type]);
403+
}
404+
}
405+
}
406+
407+
static bool
408+
check_filter(const char *str, const struct debug_log_filter *filter, bool *state)
409+
{
410+
if (filter->negative) {
411+
if (strstr(str, filter->str) == NULL) {
412+
*state = true;
413+
return false;
414+
}
415+
else {
416+
*state = false;
417+
return true;
418+
}
419+
}
420+
else {
421+
if (strstr(str, filter->str) != NULL) {
422+
*state = true;
423+
return true;
424+
}
425+
else {
426+
*state = false;
427+
return false;
350428
}
351429
}
352430
}
353431

354432
//
355433
// RUBY_DEBUG_LOG_FILTER=-foo,-bar,baz,boo
356434
// returns true if
357-
// func_name doesn't contain foo
435+
// (func_name or file_name) doesn't contain foo
358436
// and
359-
// func_name doesn't contain bar
437+
// (func_name or file_name) doesn't contain bar
360438
// and
361-
// func_name contains baz or boo
439+
// (func_name or file_name) contains baz or boo
362440
//
363441
// RUBY_DEBUG_LOG_FILTER=foo,bar,-baz,-boo
364442
// retunrs true if
365-
// func_name contains foo or bar
443+
// (func_name or file_name) contains foo or bar
366444
// or
367-
// func_name doesn't contain baz and
368-
// func_name doesn't contain boo and
445+
// (func_name or file_name) doesn't contain baz and
446+
// (func_name or file_name) doesn't contain boo and
447+
//
448+
// You can specify "file:" (ex file:foo) or "func:" (ex func:foo)
449+
// prefixes to specify the filter for.
369450
//
370451
bool
371-
ruby_debug_log_filter(const char *func_name)
452+
ruby_debug_log_filter(const char *func_name, const char *file_name)
372453
{
373454
if (debug_log.filters_num > 0) {
374-
bool status = false;
455+
bool state = false;
375456

376457
for (unsigned int i = 0; i<debug_log.filters_num; i++) {
377-
const char *filter = debug_log.filters[i];
378-
379-
if (*filter == '-') {
380-
if (strstr(func_name, &filter[1]) == NULL) {
381-
status = true;
382-
}
383-
else {
384-
return false;
385-
}
386-
}
387-
else {
388-
if (strstr(func_name, filter) != NULL) {
389-
return true;
390-
}
391-
else {
392-
status = false;
393-
}
458+
const struct debug_log_filter *filter = &debug_log.filters[i];
459+
460+
switch (filter->type) {
461+
case dlf_all:
462+
if (check_filter(func_name, filter, &state)) return state;
463+
if (check_filter(file_name, filter, &state)) return state;
464+
break;
465+
case dlf_func:
466+
if (check_filter(func_name, filter, &state)) return state;
467+
break;
468+
case dlf_file:
469+
if (check_filter(file_name, filter, &state)) return state;
470+
break;
394471
}
395472
}
396-
397-
return status;
473+
return state;
398474
}
399475
else {
400476
return true;

0 commit comments

Comments
 (0)