#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
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)))
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);
-- 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
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;
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``,
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 <config_log_groups>` switched to ``debug`` level.
#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;
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);
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)
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 */
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)
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