ruby-changes:62509
From: Koichi <ko1@a...>
Date: Sun, 2 Aug 2020 09:00:04 +0900 (JST)
Subject: [ruby-changes:62509] b4f58ea300 (master): support multiple filters by RUBY_DEBUG_LOG_FILTER
https://git.ruby-lang.org/ruby.git/commit/?id=b4f58ea300 From b4f58ea3008e3e86bdc931407c68c6e0497ef078 Mon Sep 17 00:00:00 2001 From: Koichi Sasada <ko1@a...> Date: Sun, 2 Aug 2020 04:24:47 +0900 Subject: support multiple filters by RUBY_DEBUG_LOG_FILTER Now you can specify multiple filters for RUBY_DEBUG_LOG output by RUBY_DEBUG_LOG_FILTER=a,b,c (in this case, logs that the function name contains a, b or c). diff --git a/debug.c b/debug.c index 7241d37..1dd7eeb 100644 --- a/debug.c +++ b/debug.c @@ -266,14 +266,14 @@ ruby_set_debug_option(const char *str) https://github.com/ruby/ruby/blob/trunk/debug.c#L266 #define MAX_DEBUG_LOG 0x1000 #define MAX_DEBUG_LOG_MESSAGE_LEN 0x0200 -#define MAX_DEBUG_LOG_FILTER 0x0001 +#define MAX_DEBUG_LOG_FILTER 0x0010 enum ruby_debug_log_mode ruby_debug_log_mode; static struct { char *mem; unsigned int cnt; - const char *filters[MAX_DEBUG_LOG_FILTER]; + char filters[MAX_DEBUG_LOG_FILTER][MAX_DEBUG_LOG_FILTER]; unsigned int filters_num; rb_nativethread_lock_t lock; FILE *output; @@ -292,6 +292,7 @@ setup_debug_log(void) https://github.com/ruby/ruby/blob/trunk/debug.c#L292 const char *log_config = getenv("RUBY_DEBUG_LOG"); if (log_config) { fprintf(stderr, "RUBY_DEBUG_LOG=%s\n", log_config); + unsetenv("RUBY_DEBUG_LOG"); if (strcmp(log_config, "mem") == 0) { debug_log.mem = (char *)malloc(MAX_DEBUG_LOG * MAX_DEBUG_LOG_MESSAGE_LEN); if (debug_log.mem == NULL) { @@ -317,12 +318,49 @@ setup_debug_log(void) https://github.com/ruby/ruby/blob/trunk/debug.c#L318 // check RUBY_DEBUG_LOG_FILTER const char *filter_config = getenv("RUBY_DEBUG_LOG_FILTER"); - if (filter_config) { - fprintf(stderr, "RUBY_DEBUG_LOG_FILTER=%s\n", filter_config); + if (filter_config && strlen(filter_config) > 0) { + unsigned int i; + for (i=0; i<MAX_DEBUG_LOG_FILTER; i++) { + const char *p; + if ((p = strchr(filter_config, ',')) == NULL) { + if (strlen(filter_config) >= MAX_DEBUG_LOG_FILTER) { + fprintf(stderr, "too long: %s (max:%d)\n", filter_config, MAX_DEBUG_LOG_FILTER); + exit(1); + } + strncpy(debug_log.filters[i], filter_config, MAX_DEBUG_LOG_FILTER - 1); + i++; + break; + } + else { + size_t n = p - filter_config; + if (n >= MAX_DEBUG_LOG_FILTER) { + fprintf(stderr, "too long: %s (max:%d)\n", filter_config, MAX_DEBUG_LOG_FILTER); + exit(1); + } + strncpy(debug_log.filters[i], filter_config, n); + filter_config = p+1; + } + } + debug_log.filters_num = i; + for (i=0; i<debug_log.filters_num; i++) { + fprintf(stderr, "RUBY_DEBUG_LOG_FILTER[%d]=%s\n", i, debug_log.filters[i]); + } + } +} - // TODO: multiple filters - debug_log.filters[0] = filter_config; - debug_log.filters_num = 1; +bool +ruby_debug_log_filter(const char *func_name) +{ + if (debug_log.filters_num > 0) { + for (unsigned int i = 0; i<debug_log.filters_num; i++) { + if (strstr(func_name, debug_log.filters[i]) != NULL) { + return true; + } + } + return false; + } + else { + return true; } } @@ -346,15 +384,6 @@ ruby_debug_log(const char *file, int line, const char *func_name, const char *fm https://github.com/ruby/ruby/blob/trunk/debug.c#L384 // message title if (func_name && len < MAX_DEBUG_LOG_MESSAGE_LEN) { - // filter on func_name - if (debug_log.filters_num > 0) { - int hit = 0; - for (unsigned int i = 0; i<debug_log.filters_num; i++) { - if (strstr(func_name, debug_log.filters[i]) != NULL) hit++; - } - if (hit != 0) return; - } - r = snprintf(buff + len, MAX_DEBUG_LOG_MESSAGE_LEN, "%s\t", func_name); if (r < 0) rb_bug("ruby_debug_log returns %d\n", r); len += r; diff --git a/vm_debug.h b/vm_debug.h index 9b4fb3d..a3631c0 100644 --- a/vm_debug.h +++ b/vm_debug.h @@ -89,14 +89,24 @@ extern enum ruby_debug_log_mode { https://github.com/ruby/ruby/blob/trunk/vm_debug.h#L89 void ruby_debug_log(const char *file, int line, const char *func_name, const char *fmt, ...); void ruby_debug_log_print(unsigned int n); +bool ruby_debug_log_filter(const char *func_name); // convenient macro to log even if the USE_RUBY_DEBUG_LOG macro is not specified. // You can use this macro for temporary usage (you should not commit it). #define _RUBY_DEBUG_LOG(fmt, ...) ruby_debug_log(__FILE__, __LINE__, __func__, fmt, __VA_ARGS__) #if USE_RUBY_DEBUG_LOG -#define RUBY_DEBUG_LOG(fmt, ...) do { if (ruby_debug_log_mode) ruby_debug_log(__FILE__, __LINE__, __func__, fmt, __VA_ARGS__); } while (0) -#define RUBY_DEBUG_LOG2(file, line, fmt, ...) do { if (ruby_debug_log_mode) ruby_debug_log(file, line, __func__, fmt, __VA_ARGS__); } while (0) + +#define RUBY_DEBUG_LOG(fmt, ...) do { \ + if (ruby_debug_log_mode && ruby_debug_log_filter(__func__)) \ + ruby_debug_log(__FILE__, __LINE__, __func__, fmt, __VA_ARGS__); \ +} while (0) + +#define RUBY_DEBUG_LOG2(file, line, fmt, ...) do { \ + if (ruby_debug_log_mode && ruby_debug_log_filter(__func__)) \ + ruby_debug_log(file, line, __func__, fmt, __VA_ARGS__); \ +} while (0) + #else // do nothing #define RUBY_DEBUG_LOG(fmt, ...) -- cgit v0.10.2 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/