Skip to content

Commit e998603

Browse files
committed
lightningd: fix up log filtering for generic daemons (e.g. connectd).
Without this, only per-peer daemons were filtered correctly. For generic daemons, we need to filter with the actual nodeid they use (if any). Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> Changelog-Fixed: config: `log-level` filters now apply correctly to messages from `connectd`.
1 parent 7001940 commit e998603

File tree

2 files changed

+84
-24
lines changed

2 files changed

+84
-24
lines changed

lightningd/log.c

+82-22
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,9 @@ struct logger {
7474

7575
/* Print log message at >= this level */
7676
enum log_level print_level;
77+
/* For non-trivial setups, we might need to test filters again
78+
* when actually producing output. */
79+
bool need_refiltering;
7780
};
7881

7982
static struct log_prefix *log_prefix_new(const tal_t *ctx,
@@ -154,10 +157,45 @@ static bool filter_level(const struct list_head *print_filters,
154157
return false;
155158
}
156159

160+
/* What's the lowest filtering which could possibly apply? */
161+
static void lowest_filter(const struct list_head *print_filters,
162+
const char *prefix,
163+
const struct node_id *node_id,
164+
enum log_level *level)
165+
{
166+
struct print_filter *i;
167+
const char *node_id_str;
168+
169+
if (node_id)
170+
node_id_str = node_id_to_hexstr(tmpctx, node_id);
171+
else
172+
node_id_str = NULL;
173+
174+
list_for_each(print_filters, i, list) {
175+
bool match;
176+
177+
if (strstr(prefix, i->prefix))
178+
match = true;
179+
else if (node_id_str) {
180+
match = (strstr(node_id_str, i->prefix) != NULL);
181+
} else {
182+
/* Could this possibly match a node_id? */
183+
match = strstarts(i->prefix, "02") || strstarts(i->prefix, "03");
184+
}
185+
186+
if (match && i->level < *level) {
187+
*level = i->level;
188+
}
189+
}
190+
}
191+
157192
static void log_to_files(const char *log_prefix,
158193
const char *entry_prefix,
159194
enum log_level level,
195+
/* The node_id to log under. */
160196
const struct node_id *node_id,
197+
/* Filters to apply, if non-NULL */
198+
const struct list_head *print_filters,
161199
const struct timeabs *time,
162200
const char *str,
163201
const u8 *io,
@@ -203,6 +241,17 @@ static void log_to_files(const char *log_prefix,
203241
entry_prefix, str);
204242
}
205243

244+
/* In complex configurations, we tell loggers to overshare: then we
245+
* need to filter here to see if we really want it. */
246+
if (print_filters) {
247+
enum log_level filter;
248+
if (filter_level(print_filters,
249+
entry_prefix, nodestr, &filter)) {
250+
if (level < filter)
251+
return;
252+
}
253+
}
254+
206255
/* Default if nothing set is stdout */
207256
if (!log_files) {
208257
fwrite(entry, strlen(entry), 1, stdout);
@@ -336,32 +385,34 @@ struct log_book *new_log_book(struct lightningd *ld, size_t max_mem)
336385
return log_book;
337386
}
338387

339-
/* What's the minimum level to print for this log book? */
388+
/* What's the minimum level to print this prefix and node_id for this
389+
* log book? Saves us marshalling long print lines in most cases. */
340390
static enum log_level print_level(struct log_book *log_book,
341391
const struct log_prefix *lp,
342-
const struct node_id *node_id)
392+
const struct node_id *node_id,
393+
bool *need_refiltering)
343394
{
344-
enum log_level level;
345-
const char *node_id_str = node_id ? node_id_to_hexstr(tmpctx, node_id) : "";
395+
enum log_level level = *log_book->default_print_level;
396+
bool have_filters = false;
346397

347-
assert(log_book->default_print_level != NULL);
348-
if (!filter_level(&log_book->print_filters, lp->prefix,
349-
node_id_str, &level)) {
350-
level = *log_book->default_print_level;
351-
}
398+
lowest_filter(&log_book->print_filters, lp->prefix, node_id, &level);
399+
if (!list_empty(&log_book->print_filters))
400+
have_filters = true;
352401

353402
/* We need to look into per-file filters as well: might give a
354403
* lower filter! */
355404
for (size_t i = 0; i < tal_count(log_book->log_files); i++) {
356-
enum log_level sublevel;
357-
if (filter_level(&log_book->log_files[i]->print_filters,
358-
lp->prefix, node_id_str, &sublevel)) {
359-
if (sublevel < level) {
360-
level = sublevel;
361-
}
362-
}
405+
lowest_filter(&log_book->log_files[i]->print_filters,
406+
lp->prefix, node_id, &level);
407+
if (!list_empty(&log_book->log_files[i]->print_filters))
408+
have_filters = true;
363409
}
364410

411+
/* Almost any complex array of filters can mean we want to re-check
412+
* when logging. */
413+
if (need_refiltering)
414+
*need_refiltering = have_filters;
415+
365416
return level;
366417
}
367418

@@ -389,10 +440,15 @@ new_logger(const tal_t *ctx, struct log_book *log_book,
389440
default_node_id);
390441

391442
/* Still initializing? Print UNUSUAL / BROKEN messages only */
392-
if (!log->log_book->default_print_level)
443+
if (!log->log_book->default_print_level) {
393444
log->print_level = LOG_UNUSUAL;
394-
else
395-
log->print_level = print_level(log->log_book, log->prefix, default_node_id);
445+
log->need_refiltering = false;
446+
} else {
447+
log->print_level = print_level(log->log_book,
448+
log->prefix,
449+
default_node_id,
450+
&log->need_refiltering);
451+
}
396452
list_add(&log->log_book->loggers, &log->list);
397453
tal_add_destructor(log, destroy_logger);
398454
return log;
@@ -405,7 +461,7 @@ const char *log_prefix(const struct logger *log)
405461

406462
bool log_has_io_logging(const struct logger *log)
407463
{
408-
return print_level(log->log_book, log->prefix, log->default_node_id) < LOG_DBG;
464+
return print_level(log->log_book, log->prefix, log->default_node_id, NULL) < LOG_DBG;
409465
}
410466

411467
/* This may move entry! */
@@ -467,6 +523,7 @@ static void maybe_print(struct logger *log, const struct log_entry *l)
467523
if (l->level >= log->print_level)
468524
log_to_files(log->log_book->prefix, log->prefix->prefix, l->level,
469525
l->nc ? &l->nc->node_id : NULL,
526+
log->need_refiltering ? &log->log_book->print_filters : NULL,
470527
&l->time, l->log,
471528
l->io, tal_bytelen(l->io),
472529
log->log_book->print_timestamps,
@@ -518,6 +575,7 @@ void log_io(struct logger *log, enum log_level dir,
518575
if (l->level >= log->print_level)
519576
log_to_files(log->log_book->prefix, log->prefix->prefix, l->level,
520577
l->nc ? &l->nc->node_id : NULL,
578+
log->need_refiltering ? &log->log_book->print_filters : NULL,
521579
&l->time, str,
522580
data, len,
523581
log->log_book->print_timestamps,
@@ -857,16 +915,18 @@ void logging_options_parsed(struct log_book *log_book)
857915
list_for_each(&log_book->loggers, log, list) {
858916
log->print_level = print_level(log_book,
859917
log->prefix,
860-
log->default_node_id);
918+
log->default_node_id,
919+
&log->need_refiltering);
861920
}
862921

863922
/* Catch up, since before we were only printing BROKEN msgs */
864923
for (size_t i = 0; i < log_book->num_entries; i++) {
865924
const struct log_entry *l = &log_book->log[i];
866925

867-
if (l->level >= print_level(log_book, l->prefix, l->nc ? &l->nc->node_id : NULL))
926+
if (l->level >= print_level(log_book, l->prefix, l->nc ? &l->nc->node_id : NULL, NULL))
868927
log_to_files(log_book->prefix, l->prefix->prefix, l->level,
869928
l->nc ? &l->nc->node_id : NULL,
929+
&log_book->print_filters,
870930
&l->time, l->log,
871931
l->io, tal_bytelen(l->io),
872932
log_book->print_timestamps,

tests/test_misc.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -3005,8 +3005,8 @@ def test_log_filter(node_factory):
30053005

30063006
# No debug messages in l1's log
30073007
assert not l1.daemon.is_in_log(r'-chan#[0-9]*:')
3008-
# FIXME: the connectd messages should also be matched!
3009-
# assert not l1.daemon.is_in_log(l2.info['id'])
3008+
# No mention of l2 at all (except spenderp mentions it)
3009+
assert not l1.daemon.is_in_log(l2.info['id'] + '-')
30103010

30113011
# Every message in log2 must be about l1...
30123012
with open(log2, "r") as f:

0 commit comments

Comments
 (0)