Use a single call as a setter and getter for log groups.
"hostname()\n hostname\n"
"package_version()\n return package version\n"
"user(name[, group])\n change process user (and group)\n"
- "log_level(level)\n logging level (crit, err, warning, notice, info or debug)\n"
- "log_target(target)\n logging target (syslog, stderr, stdout)\n"
+ "log_level(level)\n logging level (crit, err, warning, notice, info or debug)\n"
+ "log_target(target)\n logging target (syslog, stderr, stdout)\n"
+ "log_groups(groups)\n turn on debug log for selected groups\n"
"option(opt[, new_val])\n get/set server option\n"
"mode(strict|normal|permissive)\n set resolver strictness level\n"
"reorder_RR([true|false])\n set/get reordering of RRs within RRsets\n"
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))
+static int l_log_groups(lua_State *L)
{
- if (lua_gettop(L) != 1 || (!lua_isstring(L, 1) && !lua_istable(L, 1)))
- lua_error_p(L, "takes string or table of strings");
-
- if (lua_isstring(L, 1)) {
- enum kr_log_group grp = kr_log_name2grp(lua_tostring(L, 1));
- if (grp == 0)
- lua_error_p(L, "unknown group \"%s\"", lua_tostring(L, -1));
- action(grp);
- }
+ const int params = lua_gettop(L);
+ if (params > 1)
+ goto bad_call;
+ if (params == 1) { // set
+ if (!lua_istable(L, 1))
+ goto bad_call;
+ kr_log_group_reset();
- if (lua_istable(L, 1)) {
int idx = 1;
lua_pushnil(L);
while (lua_next(L, 1) != 0) {
- if (!lua_isstring(L, -1))
- lua_error_p(L, "wrong value at index %d, must be string", idx);
- enum kr_log_group grp = kr_log_name2grp(lua_tostring(L, -1));
+ const char *grp_str = lua_tostring(L, -1);
+ if (!grp_str)
+ goto bad_call;
+ enum kr_log_group grp = kr_log_name2grp(grp_str);
if (grp == 0)
- lua_error_p(L, "unknown group \"%s\"", lua_tostring(L, -1));
+ lua_error_p(L, "unknown log group '%s'", lua_tostring(L, -1));
- action(grp);
+ kr_log_group_add(grp);
++idx;
lua_pop(L, 1);
}
}
-
- return 0;
-}
-
-static int l_add_log_groups(lua_State *L)
-{
- return handle_log_groups(L, kr_log_add_group);
-}
-
-static int l_del_log_groups(lua_State *L)
-{
- return handle_log_groups(L, kr_log_del_group);
-}
-
-static int l_get_log_groups(lua_State *L)
-{
+ // get
lua_newtable(L);
+ int i = 1;
for (int grp = LOG_GRP_SYSTEM; grp <= LOG_GRP_DEVEL; grp++) {
const char *name = kr_log_grp2name(grp);
if (kr_fails_assert(name))
continue;
if (kr_log_group_is_set(grp)) {
- lua_pushboolean(L, true);
- lua_setfield(L, -2, name);
+ lua_pushinteger(L, i);
+ lua_pushstring(L, name);
+ lua_settable(L, -3);
+ i++;
}
}
-
return 1;
+bad_call:
+ lua_error_p(L, "takes a table of string groups as parameter or nothing");
}
char *engine_get_hostname(struct engine *engine) {
lua_setglobal(engine->L, "log_level");
lua_pushcfunction(engine->L, l_log_target);
lua_setglobal(engine->L, "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);
- lua_setglobal(engine->L, "del_log_groups");
- lua_pushcfunction(engine->L, l_get_log_groups);
- lua_setglobal(engine->L, "get_log_groups");
+ lua_pushcfunction(engine->L, l_log_groups);
+ lua_setglobal(engine->L, "log_groups");
lua_pushcfunction(engine->L, l_setuser);
lua_setglobal(engine->L, "user");
lua_pushcfunction(engine->L, l_hint_root_file);
local function test_log_groups()
- same(get_log_groups()['system'], nil, '"system" log group not logged by default')
- add_log_groups('system')
- same(get_log_groups()['system'], true, 'add "system" log group as string')
- add_log_groups('devel')
- same(get_log_groups()['devel'], true, 'add another ("devel") log group as string')
- add_log_groups({ 'cache' })
- same(get_log_groups()['cache'], true, 'add "cache" log group as table')
- add_log_groups({ 'io', 'tests' })
- same(get_log_groups()['io'], true, 'add "io" log group as table with multiple entires')
- same(get_log_groups()['tests'], true, 'add "tests" log group as table with multiple entries')
- del_log_groups('system')
- same(get_log_groups()['system'], nil, 'remove "system" log group as string')
- del_log_groups({ 'cache' })
- same(get_log_groups()['cache'], nil, 'remove "cache" log group as table')
- del_log_groups({ 'io', 'tests' })
- same(get_log_groups()['io'], nil, 'remove "io" log group as table with multiple entries')
- same(get_log_groups()['tests'], nil, 'remove "tests" log group as table with multiple entries')
- boom(add_log_groups, { 'nonexistent' }, "nonexistent group cant't be added")
- boom(del_log_groups, { 'nonexistent2' }, "nonexistent2 group can't be removed")
+ same(log_groups(), {}, 'no groups are logged by default')
+ same(log_groups({'system'}), {'system'}, 'configure "system" group')
+ same(log_groups({'devel'}), {'devel'}, 'another call overrides previously set groups')
+ same(log_groups({'devel', 'system'}), {'system', 'devel'}, 'configure multiple groups')
+ same(log_groups({}), {}, 'clear groups with empty table')
+ boom(log_groups, { 'string' }, "group argument can't be string")
+ boom(log_groups, { {'nonexistent'} }, "nonexistent group can't be added")
+ boom(log_groups, { 1, 2 }, "group doesn't take multiple arguments")
end
return {
In addition to levels, logging is also divided into the
:ref:`groups <config_log_groups>`. All groups
-are logged by default, but you can enable ``debug`` level for some groups using
-:func:`add_log_groups` function. Other groups are logged to the log level
+are logged by default, but you can enable ``debug`` level for selected groups using
+:func:`log_groups` function. Other groups are logged to the log level
set by :func:`log_level`.
.. py:function:: log_level([level])
: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.
+ 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()
+.. py:function:: log_groups([table])
- :return: table :ref:`Groups <config_log_groups>` switched to ``debug`` level.
+ :param: table of string(s) representing ref:`log groups <config_log_groups>`
+ :return: table of string with currently set log groups
- Get :ref:`groups <config_log_groups>` switched to ``debug`` level.
+ Use to turn-on debug logging for the selected groups regardless of the global
+ log level. Calling with no argument lists the currently active log groups. To
+ remove all log groups, call the function with an empty table.
-.. py:function:: add_log_groups([string | table])
-
- :param: :ref:`Groups <config_log_groups>` to switch to ``debug`` level.
-
- Set debug level for selected :ref:`groups <config_log_groups>`.
-
-.. py:function:: del_log_groups([string | table])
-
- :param: :ref:`Groups <config_log_groups>` switched to global logging level.
-
- Switch selected :ref:`groups <config_log_groups>` to logging level set
- by :func:`log_level`.
+ .. code-block:: lua
+ log_groups({'io', 'tls'} -- turn on debug logging for io and tls groups
+ log_groups() -- list active log groups
+ log_groups({}) -- remove all log groups
It is also possible to enable ``debug`` logging level for *a single request*, see chapter :ref:`mod-http-trace`.
return;
}
-void kr_log_add_group(enum kr_log_group group)
+void kr_log_group_add(enum kr_log_group group)
{
kr_log_groups |= (1ULL << group);
if (group == LOG_GRP_GNUTLS)
kr_gnutls_log_level_set();
}
-void kr_log_del_group(enum kr_log_group group)
+void kr_log_group_reset()
{
- kr_log_groups &= (~(1ULL << group));
- if (group == LOG_GRP_GNUTLS)
+ bool had_gnutls = kr_log_group_is_set(LOG_GRP_GNUTLS);
+ kr_log_groups = 0;
+ if (had_gnutls)
kr_gnutls_log_level_set();
}
KR_EXPORT
bool kr_log_group_is_set(enum kr_log_group group);
KR_EXPORT
-void kr_log_add_group(enum kr_log_group group);
+void kr_log_group_add(enum kr_log_group group);
KR_EXPORT
-void kr_log_del_group(enum kr_log_group group);
+void kr_log_group_reset();
KR_EXPORT
const char *kr_log_grp2name(enum kr_log_group group);
KR_EXPORT