diff --git a/doc/developer/scripting.rst b/doc/developer/scripting.rst index 7a43314490..f51130b1e3 100644 --- a/doc/developer/scripting.rst +++ b/doc/developer/scripting.rst @@ -523,6 +523,7 @@ object which contains methods corresponding to each of the ``zlog`` levels: log.error("error") log.notice("notice") log.debug("debug") + log.trace("trace") The log messages will show up in the daemon's log output. @@ -579,14 +580,14 @@ accomplished with scripting. RM_FAILURE, RM_NOMATCH, RM_MATCH, RM_MATCH_AND_CHANGE) log.info("Evaluating route " .. prefix.network .. " from peer " .. peer.remote_id.string) - + function on_match (prefix, attributes) log.info("Match") return { attributes = RM_MATCH } end - + function on_nomatch (prefix, attributes) log.info("No match") return { diff --git a/lib/frrlua.c b/lib/frrlua.c index 6ad0b5796a..ef081e4bd0 100644 --- a/lib/frrlua.c +++ b/lib/frrlua.c @@ -382,6 +382,12 @@ static const char *frrlua_log_thunk(lua_State *L) return lua_tostring(L, 1); } +static int frrlua_log_trace(lua_State *L) +{ + zlog_debug("%s", frrlua_stackdump(L)); + return 0; +} + static int frrlua_log_debug(lua_State *L) { zlog_debug("%s", frrlua_log_thunk(L)); @@ -413,11 +419,12 @@ static int frrlua_log_error(lua_State *L) } static const luaL_Reg log_funcs[] = { - {"debug", frrlua_log_debug}, - {"info", frrlua_log_info}, - {"notice", frrlua_log_notice}, - {"warn", frrlua_log_warn}, - {"error", frrlua_log_error}, + { "trace", frrlua_log_trace }, + { "debug", frrlua_log_debug }, + { "info", frrlua_log_info }, + { "notice", frrlua_log_notice }, + { "warn", frrlua_log_warn }, + { "error", frrlua_log_error }, {}, }; @@ -432,6 +439,67 @@ void frrlua_export_logging(lua_State *L) * Debugging. */ +void lua_table_dump(lua_State *L, int index, struct buffer *buf, int level) +{ + char tmpbuf[64] = {}; + + lua_pushnil(L); + + while (lua_next(L, index) != 0) { + int key_type; + int value_type; + + for (int i = 0; i < level; i++) + buffer_putstr(buf, " "); + + key_type = lua_type(L, -2); + if (key_type == LUA_TSTRING) { + const char *key = lua_tostring(L, -2); + + buffer_putstr(buf, key); + buffer_putstr(buf, ": "); + } else if (key_type == LUA_TNUMBER) { + snprintf(tmpbuf, sizeof(tmpbuf), "%g", + lua_tonumber(L, -2)); + buffer_putstr(buf, tmpbuf); + buffer_putstr(buf, ": "); + } + + value_type = lua_type(L, -1); + switch (value_type) { + case LUA_TSTRING: + snprintf(tmpbuf, sizeof(tmpbuf), "\"%s\"\n", + lua_tostring(L, -1)); + buffer_putstr(buf, tmpbuf); + break; + case LUA_TBOOLEAN: + snprintf(tmpbuf, sizeof(tmpbuf), "%s\n", + lua_toboolean(L, -1) ? "true" : "false"); + buffer_putstr(buf, tmpbuf); + break; + case LUA_TNUMBER: + snprintf(tmpbuf, sizeof(tmpbuf), "%g\n", + lua_tonumber(L, -1)); + buffer_putstr(buf, tmpbuf); + break; + case LUA_TTABLE: + buffer_putstr(buf, "{\n"); + lua_table_dump(L, lua_gettop(L), buf, level + 1); + for (int i = 0; i < level; i++) + buffer_putstr(buf, " "); + buffer_putstr(buf, "}\n"); + break; + default: + snprintf(tmpbuf, sizeof(tmpbuf), "%s\n", + lua_typename(L, value_type)); + buffer_putstr(buf, tmpbuf); + break; + } + + lua_pop(L, 1); + } +} + char *frrlua_stackdump(lua_State *L) { int top = lua_gettop(L); @@ -458,6 +526,11 @@ char *frrlua_stackdump(lua_State *L) lua_tonumber(L, i)); buffer_putstr(buf, tmpbuf); break; + case LUA_TTABLE: /* tables */ + buffer_putstr(buf, "{\n"); + lua_table_dump(L, i, buf, 1); + buffer_putstr(buf, "}\n"); + break; default: /* other values */ snprintf(tmpbuf, sizeof(tmpbuf), "%s\n", lua_typename(L, t)); diff --git a/lib/frrlua.h b/lib/frrlua.h index dc0f4d9986..e407a4492f 100644 --- a/lib/frrlua.h +++ b/lib/frrlua.h @@ -181,6 +181,9 @@ int frrlua_table_get_integer(lua_State *L, const char *key); */ void frrlua_export_logging(lua_State *L); +/* A helper fuction that dumps the Lua stack */ +void lua_table_dump(lua_State *L, int index, struct buffer *buf, int level); + /* * Dump Lua stack to a string. *