From: Vladimír Čunát Date: Mon, 26 Jul 2021 18:58:50 +0000 (+0200) Subject: lib/log: redesign startup and target selection X-Git-Tag: v5.4.0~2^2~14 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=eee257853fe69824a511abf1aeb9c11da29e81b3;p=thirdparty%2Fknot-resolver.git lib/log: redesign startup and target selection - add lua set_log_target() + docs - default to 'stderr' (manual runs) - switch to 'syslog' in distro-preconfig.lua - a few minor tweaks --- diff --git a/daemon/engine.c b/daemon/engine.c index e5d02bac7..4d8cad7c5 100644 --- a/daemon/engine.c +++ b/daemon/engine.c @@ -27,6 +27,7 @@ #include "lib/defines.h" #include "lib/cache/cdb_lmdb.h" #include "lib/dnssec/ta.h" +#include "lib/log.h" /* Magic defaults for the engine. */ #ifndef LRU_RTT_SIZE @@ -175,6 +176,41 @@ static int l_get_log_level(lua_State *L) return 1; } +static int l_set_log_target(lua_State *L) +{ + const int params = lua_gettop(L); + if (params > 1) + goto bad_call; + // set + if (params == 1) { + const char *t_str = lua_tostring(L, 1); + if (!t_str) + goto bad_call; + kr_log_target_t t; + if (strcmp(t_str, "syslog") == 0) { + t = LOG_TARGET_SYSLOG; + } else if (strcmp(t_str, "stdout") == 0) { + t = LOG_TARGET_STDOUT; + } else if (strcmp(t_str, "stderr") == 0) { + t = LOG_TARGET_STDERR; + } else { + lua_error_p(L, "unknown log target '%s'", t_str); + } + kr_log_target_set(t); + } + // get + const char *t_str = NULL; + switch (kr_log_target) { + case LOG_TARGET_SYSLOG: t_str = "syslog"; break; + case LOG_TARGET_STDERR: t_str = "stderr"; break; + case LOG_TARGET_STDOUT: t_str = "stdout"; break; + } // -Wswitch-enum + lua_pushstring(L, t_str); + return 1; +bad_call: + lua_error_p(L, "takes one string parameter or nothing"); +} + static int handle_log_groups(lua_State *L, void (*action)(enum kr_log_group grp)) { if (lua_gettop(L) != 1 || (!lua_isstring(L, 1) && !lua_istable(L, 1))) @@ -516,6 +552,8 @@ static int init_state(struct engine *engine) lua_setglobal(engine->L, "set_log_level"); lua_pushcfunction(engine->L, l_get_log_level); lua_setglobal(engine->L, "get_log_level"); + lua_pushcfunction(engine->L, l_set_log_target); + lua_setglobal(engine->L, "set_log_target"); lua_pushcfunction(engine->L, l_add_log_groups); lua_setglobal(engine->L, "add_log_groups"); lua_pushcfunction(engine->L, l_del_log_groups); diff --git a/daemon/lua/distro-preconfig.lua.in b/daemon/lua/distro-preconfig.lua.in index 69dd4a286..588c96603 100644 --- a/daemon/lua/distro-preconfig.lua.in +++ b/daemon/lua/distro-preconfig.lua.in @@ -1,4 +1,6 @@ -- SPDX-License-Identifier: GPL-3.0-or-later +set_log_target('syslog') -- assume running as OS service + local ffi = require('ffi') local id = os.getenv('SYSTEMD_INSTANCE') if not id then diff --git a/daemon/main.c b/daemon/main.c index 736213801..dd14692d9 100644 --- a/daemon/main.c +++ b/daemon/main.c @@ -418,7 +418,6 @@ int main(int argc, char **argv) the_args = &the_args_value; args_init(the_args); - kr_log_init(LOG_DEFAULT_LEVEL, LOG_TARGET_STDOUT); int ret = parse_args(argc, argv, the_args); if (ret >= 0) goto cleanup_args; diff --git a/doc/config-logging-monitoring.rst b/doc/config-logging-monitoring.rst index ef37ed519..afddb8bee 100644 --- a/doc/config-logging-monitoring.rst +++ b/doc/config-logging-monitoring.rst @@ -4,9 +4,7 @@ Logging, monitoring, diagnostics ******************************** -Knot Resolver logs to standard outputs, which is then captured by supervisor -and sent to logging system for further processing. -To read logs use commands usual for your distribution. +To read service logs use commands usual for your distribution. E.g. on distributions using systemd-journald use command ``journalctl -u kresd@* -f``. Knot Resolver supports 6 logging levels - ``crit``, ``err``, ``warning``, @@ -48,6 +46,16 @@ set by :func:`set_log_level`. Show current logging level. +.. py:function:: set_log_target(target) + + :param: String ``'syslog'``, ``'stderr'``, ``'stdout'`` + :return: string Current logging target. + + Knot Resolver logs to standard error stream by default, + but typical systemd units change that to ``'syslog'``. + That setting logs directly through systemd's facilities + (if available) to preserve more meta-data. + .. py:function:: get_log_groups() :return: table :ref:`Groups ` switched to ``debug`` level. diff --git a/lib/log.c b/lib/log.c index 0a7f0cb38..1931d01d3 100644 --- a/lib/log.c +++ b/lib/log.c @@ -19,8 +19,8 @@ bool use_journal = false; #define use_journal false #endif -kr_log_level_t kr_log_level = LOG_CRIT; -kr_log_target_t kr_log_target = LOG_TARGET_STDOUT; +kr_log_level_t kr_log_level = LOG_DEFAULT_LEVEL; +kr_log_target_t kr_log_target = LOG_TARGET_DEFAULT; /** Set of log-groups that are on debug level. It's a bitmap over 1 << enum kr_log_group. */ static uint64_t kr_log_groups = 0; @@ -127,12 +127,11 @@ void kr_log_fmt(enum kr_log_group group, kr_log_level_t level, const char *file, if (kr_log_group_is_set(group)) setlogmask(LOG_UPTO(kr_log_level)); } else { - FILE *stream; switch(kr_log_target) { case LOG_TARGET_STDOUT: stream = stdout; break; + default: kr_assert(false); // fall through case LOG_TARGET_STDERR: stream = stderr; break; - default: stream = stdout; break; } va_start(args, fmt); @@ -245,16 +244,22 @@ void kr_log_del_group(enum kr_log_group group) kr_gnutls_log_level_set(); } -void kr_log_init(kr_log_level_t level, kr_log_target_t target) +void kr_log_target_set(kr_log_target_t target) { kr_log_target = target; - kr_log_groups = 0; + if (target != LOG_TARGET_SYSLOG) + return; + int ret = 0; #if ENABLE_LIBSYSTEMD - use_journal = sd_booted(); + ret = sd_booted(); + use_journal = ret > 0; #endif - openlog(NULL, LOG_PID, LOG_DAEMON); - kr_log_level_set(level); + if (!use_journal) + openlog(NULL, LOG_PID, LOG_DAEMON); + if (ret < 0) + kr_log_error(SYSTEM, "failed test for systemd presence: %s\n", + strerror(abs(ret))); } static inline bool req_has_trace_log(const struct kr_request *req) diff --git a/lib/log.h b/lib/log.h index 060185899..6353446a2 100644 --- a/lib/log.h +++ b/lib/log.h @@ -17,6 +17,8 @@ typedef enum { LOG_TARGET_SYSLOG = 0, LOG_TARGET_STDERR = 1, LOG_TARGET_STDOUT = 2, + /* The default also applies *before* configuration changes it. */ + LOG_TARGET_DEFAULT = LOG_TARGET_STDERR, } kr_log_target_t; /* Groups */ @@ -148,7 +150,7 @@ int kr_log_level_set(kr_log_level_t level); KR_EXPORT kr_log_level_t kr_log_level_get(void); KR_EXPORT -void kr_log_init(kr_log_level_t level, kr_log_target_t target); +void kr_log_target_set(kr_log_target_t target); #define TO_STR_A(x) #x #define TO_STR(x) TO_STR_A(x) diff --git a/tests/pytests/kresd.py b/tests/pytests/kresd.py index 62835f366..7eeceb68a 100644 --- a/tests/pytests/kresd.py +++ b/tests/pytests/kresd.py @@ -95,7 +95,7 @@ class Kresd(ContextDecorator): self.logfile = open(self.logfile_path, 'w') self.process = subprocess.Popen( ['kresd', '-c', self.config_path, '-n', self.workdir], - stdout=self.logfile, env=os.environ.copy()) + stderr=self.logfile, env=os.environ.copy()) try: self._wait_for_tcp_port() # wait for ports to be up and responding