mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-02-22 14:42:40 +01:00
daemon: add logging options.
Particularly logging to file. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
3e77c55a3b
commit
117cf6b02d
6 changed files with 162 additions and 13 deletions
2
Makefile
2
Makefile
|
@ -185,7 +185,7 @@ PROGRAMS := $(TEST_CLI_PROGRAMS) $(TEST_PROGRAMS)
|
|||
|
||||
CWARNFLAGS := -Werror -Wall -Wundef -Wmissing-prototypes -Wmissing-declarations -Wstrict-prototypes -Wold-style-definition
|
||||
CDEBUGFLAGS := -g -fstack-protector
|
||||
CFLAGS := $(CWARNFLAGS) $(CDEBUGFLAGS) -I $(CCANDIR) -I secp256k1/include/ $(FEATURES)
|
||||
CFLAGS := $(CWARNFLAGS) $(CDEBUGFLAGS) -I $(CCANDIR) -I secp256k1/include/ -I . $(FEATURES)
|
||||
|
||||
LDLIBS := -lcrypto -lprotobuf-c
|
||||
$(PROGRAMS): CFLAGS+=-I.
|
||||
|
|
|
@ -24,4 +24,4 @@ check-source: $(DAEMON_HEADERS:%=check-hdr-include-order/%)
|
|||
check-daemon-makefile:
|
||||
@if [ "`echo daemon/*.h`" != "$(DAEMON_HEADERS)" ]; then echo DAEMON_HEADERS incorrect; exit 1; fi
|
||||
|
||||
daemon/lightningd: $(DAEMON_OBJS) $(CCAN_OBJS)
|
||||
daemon/lightningd: $(DAEMON_OBJS) $(CORE_OBJS) $(BITCOIN_OBJS) $(CCAN_OBJS) libsecp256k1.a
|
||||
|
|
|
@ -1,8 +1,15 @@
|
|||
#include "lightningd.h"
|
||||
#include "log.h"
|
||||
#include <ccan/array_size/array_size.h>
|
||||
#include <ccan/err/err.h>
|
||||
#include <ccan/opt/opt.h>
|
||||
#include <ccan/tal/str/str.h>
|
||||
#include <ccan/tal/tal.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <version.h>
|
||||
|
||||
static struct lightningd_state *lightningd_state(void)
|
||||
{
|
||||
|
@ -15,11 +22,102 @@ static struct lightningd_state *lightningd_state(void)
|
|||
return state;
|
||||
}
|
||||
|
||||
static struct {
|
||||
const char *name;
|
||||
enum log_level level;
|
||||
} log_levels[] = {
|
||||
{ "IO", LOG_IO },
|
||||
{ "DEBUG", LOG_DBG },
|
||||
{ "INFO", LOG_INFORM },
|
||||
{ "UNUSUAL", LOG_UNUSUAL },
|
||||
{ "BROKEN", LOG_BROKEN }
|
||||
};
|
||||
|
||||
static char *arg_log_level(const char *arg, struct lightningd_state *state)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(log_levels); i++) {
|
||||
if (strcasecmp(arg, log_levels[i].name) == 0) {
|
||||
set_log_level(state->log_record, log_levels[i].level);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return tal_fmt(NULL, "unknown log level");
|
||||
}
|
||||
|
||||
static char *arg_log_prefix(const char *arg, struct lightningd_state *state)
|
||||
{
|
||||
set_log_prefix(state->base_log, arg);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void log_to_file(const char *prefix,
|
||||
enum log_level level,
|
||||
bool continued,
|
||||
const char *str,
|
||||
struct lightningd_state *state)
|
||||
{
|
||||
if (!continued) {
|
||||
fprintf(state->logf, "%s %s\n", prefix, str);
|
||||
} else {
|
||||
fprintf(state->logf, "%s \t%s\n", prefix, str);
|
||||
}
|
||||
}
|
||||
|
||||
static char *arg_log_to_file(const char *arg, struct lightningd_state *state)
|
||||
{
|
||||
state->logf = fopen(arg, "a");
|
||||
if (!state->logf)
|
||||
return tal_fmt(NULL, "Failed to open: %s", strerror(errno));
|
||||
set_log_outfn(state->log_record, log_to_file, state);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Tal wrappers for opt. */
|
||||
static void *opt_allocfn(size_t size)
|
||||
{
|
||||
return tal_alloc_(NULL, size, false, TAL_LABEL("opt_allocfn", ""));
|
||||
}
|
||||
|
||||
static void *tal_reallocfn(void *ptr, size_t size)
|
||||
{
|
||||
if (!ptr)
|
||||
return opt_allocfn(size);
|
||||
tal_resize_(&ptr, 1, size, false);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static void tal_freefn(void *ptr)
|
||||
{
|
||||
tal_free(ptr);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct lightningd_state *state = lightningd_state();
|
||||
|
||||
err_set_progname(argv[0]);
|
||||
opt_set_alloc(opt_allocfn, tal_reallocfn, tal_freefn);
|
||||
|
||||
opt_register_noarg("--help|-h", opt_usage_and_exit,
|
||||
"\n"
|
||||
"A bitcoin lightning daemon.",
|
||||
"Print this message.");
|
||||
opt_register_arg("--log-level", arg_log_level, NULL, state,
|
||||
"log level (debug, info, unusual, broken)");
|
||||
opt_register_arg("--log-prefix", arg_log_prefix, NULL, state,
|
||||
"log prefix");
|
||||
opt_register_arg("--log-file=<file>", arg_log_to_file, NULL, state,
|
||||
"log to file instead of stdout");
|
||||
opt_register_version();
|
||||
|
||||
opt_parse(&argc, argv, opt_log_stderr_exit);
|
||||
if (argc != 1)
|
||||
errx(1, "no arguments accepted");
|
||||
|
||||
log_info(state->base_log, "Hello world!");
|
||||
tal_free(state);
|
||||
opt_free_table();
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
#ifndef LIGHTNING_DAEMON_LIGHTNING_H
|
||||
#define LIGHTNING_DAEMON_LIGHTNING_H
|
||||
#include "config.h"
|
||||
#include <stdio.h>
|
||||
|
||||
/* Here's where the global variables hide! */
|
||||
struct lightningd_state {
|
||||
/* Where all our logging goes. */
|
||||
struct log_record *log_record;
|
||||
struct log *base_log;
|
||||
FILE *logf;
|
||||
};
|
||||
#endif /* LIGHTNING_DAEMON_LIGHTNING_H */
|
||||
|
|
57
daemon/log.c
57
daemon/log.c
|
@ -20,7 +20,12 @@ struct log_entry {
|
|||
struct log_record {
|
||||
size_t mem_used;
|
||||
size_t max_mem;
|
||||
enum log_level print;
|
||||
void (*print)(const char *prefix,
|
||||
enum log_level level,
|
||||
bool continued,
|
||||
const char *str, void *arg);
|
||||
void *print_arg;
|
||||
enum log_level print_level;
|
||||
struct timeabs init_time;
|
||||
|
||||
struct list_head log;
|
||||
|
@ -31,6 +36,18 @@ struct log {
|
|||
const char *prefix;
|
||||
};
|
||||
|
||||
static void log_default_print(const char *prefix,
|
||||
enum log_level level,
|
||||
bool continued,
|
||||
const char *str, void *arg)
|
||||
{
|
||||
if (!continued) {
|
||||
printf("%s %s\n", prefix, str);
|
||||
} else {
|
||||
printf("%s \t%s\n", prefix, str);
|
||||
}
|
||||
}
|
||||
|
||||
static size_t log_bufsize(const struct log_entry *e)
|
||||
{
|
||||
if (e->level == LOG_IO)
|
||||
|
@ -76,7 +93,8 @@ struct log_record *new_log_record(const tal_t *ctx,
|
|||
assert(max_mem > sizeof(struct log) * 2);
|
||||
lr->mem_used = 0;
|
||||
lr->max_mem = max_mem;
|
||||
lr->print = printlevel;
|
||||
lr->print = log_default_print;
|
||||
lr->print_level = printlevel;
|
||||
lr->init_time = time_now();
|
||||
list_head_init(&lr->log);
|
||||
|
||||
|
@ -101,7 +119,7 @@ new_log(const tal_t *ctx, struct log_record *record, const char *fmt, ...)
|
|||
|
||||
void set_log_level(struct log_record *lr, enum log_level level)
|
||||
{
|
||||
lr->print = level;
|
||||
lr->print_level = level;
|
||||
}
|
||||
|
||||
void set_log_prefix(struct log *log, const char *prefix)
|
||||
|
@ -110,6 +128,17 @@ void set_log_prefix(struct log *log, const char *prefix)
|
|||
log->prefix = tal_strdup(log->lr, prefix);
|
||||
}
|
||||
|
||||
void set_log_outfn_(struct log_record *lr,
|
||||
void (*print)(const char *prefix,
|
||||
enum log_level level,
|
||||
bool continued,
|
||||
const char *str, void *arg),
|
||||
void *arg)
|
||||
{
|
||||
lr->print = print;
|
||||
lr->print_arg = arg;
|
||||
}
|
||||
|
||||
const char *log_prefix(const struct log *log)
|
||||
{
|
||||
return log->prefix;
|
||||
|
@ -161,8 +190,9 @@ void logv(struct log *log, enum log_level level, const char *fmt, va_list ap)
|
|||
|
||||
l->log = tal_vfmt(l, fmt, ap);
|
||||
|
||||
if (level >= log->lr->print)
|
||||
printf("%s %s\n", log->prefix, l->log);
|
||||
if (level >= log->lr->print_level)
|
||||
log->lr->print(log->prefix, level, false, l->log,
|
||||
log->lr->print_arg);
|
||||
|
||||
add_entry(log, l);
|
||||
}
|
||||
|
@ -176,12 +206,16 @@ void log_io(struct log *log, bool in, const void *data, size_t len)
|
|||
l->log[0] = in;
|
||||
memcpy(l->log + 1, data, len);
|
||||
|
||||
if (LOG_IO >= log->lr->print) {
|
||||
char *hex = tal_arr(l, char, hex_str_size(len));
|
||||
hex_encode(data, len, hex, hex_str_size(len));
|
||||
printf("%s[%s] %s\n", log->prefix, in ? "IN" : "OUT", hex);
|
||||
if (LOG_IO >= log->lr->print_level) {
|
||||
const char *dir = in ? "[IN]" : "[OUT]";
|
||||
char *hex = tal_arr(l, char, strlen(dir) + hex_str_size(len));
|
||||
strcpy(hex, dir);
|
||||
hex_encode(data, len, hex + strlen(dir), hex_str_size(len));
|
||||
log->lr->print(log->prefix, LOG_IO, false, l->log,
|
||||
log->lr->print_arg);
|
||||
tal_free(hex);
|
||||
}
|
||||
|
||||
add_entry(log, l);
|
||||
errno = save_errno;
|
||||
}
|
||||
|
@ -198,8 +232,9 @@ static void do_log_add(struct log *log, const char *fmt, va_list ap)
|
|||
tal_append_vfmt(&l->log, fmt, ap);
|
||||
add_entry(log, l);
|
||||
|
||||
if (l->level >= log->lr->print)
|
||||
printf("%s \t%s\n", log->prefix, l->log + oldlen);
|
||||
if (l->level >= log->lr->print_level)
|
||||
log->lr->print(log->prefix, l->level, true, l->log + oldlen,
|
||||
log->lr->print_arg);
|
||||
}
|
||||
|
||||
void log_(struct log *log, enum log_level level, const char *fmt, ...)
|
||||
|
|
14
daemon/log.h
14
daemon/log.h
|
@ -54,6 +54,20 @@ void log_add_enum_(struct log *log, const char *enumname, unsigned int val);
|
|||
void set_log_level(struct log_record *lr, enum log_level level);
|
||||
void set_log_prefix(struct log *log, const char *prefix);
|
||||
const char *log_prefix(const struct log *log);
|
||||
#define set_log_outfn(lr, print, arg) \
|
||||
set_log_outfn_((lr), \
|
||||
typesafe_cb_preargs(void, void *, (print), (arg),\
|
||||
const char *, \
|
||||
enum log_level, \
|
||||
bool, \
|
||||
const char *), (arg))
|
||||
|
||||
void set_log_outfn_(struct log_record *lr,
|
||||
void (*print)(const char *prefix,
|
||||
enum log_level level,
|
||||
bool continued,
|
||||
const char *str, void *arg),
|
||||
void *arg);
|
||||
|
||||
size_t log_max_mem(const struct log_record *lr);
|
||||
size_t log_used(const struct log_record *lr);
|
||||
|
|
Loading…
Add table
Reference in a new issue