From 8b01c72fc883bf50d8827763b4ad3d793f8a176d Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Sun, 5 Apr 2015 01:09:41 +0100 Subject: [PATCH] Add new logger API. --- src/lua/lua_logger.c | 263 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 254 insertions(+), 9 deletions(-) diff --git a/src/lua/lua_logger.c b/src/lua/lua_logger.c index 0047190bf..559a2a0f8 100644 --- a/src/lua/lua_logger.c +++ b/src/lua/lua_logger.c @@ -25,24 +25,35 @@ #include "lua_common.h" +static gsize lua_logger_out_type (lua_State *L, gint pos, gchar *outbuf, gsize len); /* Logger methods */ LUA_FUNCTION_DEF (logger, err); LUA_FUNCTION_DEF (logger, warn); LUA_FUNCTION_DEF (logger, info); LUA_FUNCTION_DEF (logger, debug); +LUA_FUNCTION_DEF (logger, errx); +LUA_FUNCTION_DEF (logger, warnx); +LUA_FUNCTION_DEF (logger, infox); +LUA_FUNCTION_DEF (logger, debugx); +LUA_FUNCTION_DEF (logger, slog); static const struct luaL_reg loggerlib_f[] = { LUA_INTERFACE_DEF (logger, err), LUA_INTERFACE_DEF (logger, warn), LUA_INTERFACE_DEF (logger, info), LUA_INTERFACE_DEF (logger, debug), + LUA_INTERFACE_DEF (logger, errx), + LUA_INTERFACE_DEF (logger, warnx), + LUA_INTERFACE_DEF (logger, infox), + LUA_INTERFACE_DEF (logger, debugx), + LUA_INTERFACE_DEF (logger, slog), {"__tostring", rspamd_lua_class_tostring}, {NULL, NULL} }; static void -lua_common_log (GLogLevelFlags level, lua_State *L, const gchar *msg) +lua_common_log_line (GLogLevelFlags level, lua_State *L, const gchar *msg) { lua_Debug d; gchar func_buf[128], *p; @@ -96,8 +107,8 @@ lua_logger_err (lua_State * L) { const gchar *msg; msg = luaL_checkstring (L, 1); - lua_common_log (G_LOG_LEVEL_CRITICAL, L, msg); - return 1; + lua_common_log_line (G_LOG_LEVEL_CRITICAL, L, msg); + return 0; } static gint @@ -105,8 +116,8 @@ lua_logger_warn (lua_State * L) { const gchar *msg; msg = luaL_checkstring (L, 1); - lua_common_log (G_LOG_LEVEL_WARNING, L, msg); - return 1; + lua_common_log_line (G_LOG_LEVEL_WARNING, L, msg); + return 0; } static gint @@ -114,8 +125,8 @@ lua_logger_info (lua_State * L) { const gchar *msg; msg = luaL_checkstring (L, 1); - lua_common_log (G_LOG_LEVEL_INFO, L, msg); - return 1; + lua_common_log_line (G_LOG_LEVEL_INFO, L, msg); + return 0; } static gint @@ -123,10 +134,244 @@ lua_logger_debug (lua_State * L) { const gchar *msg; msg = luaL_checkstring (L, 1); - lua_common_log (G_LOG_LEVEL_DEBUG, L, msg); - return 1; + lua_common_log_line (G_LOG_LEVEL_DEBUG, L, msg); + return 0; +} + +static gsize +lua_logger_out_str (lua_State *L, gint pos, gchar *outbuf, gsize len) +{ + const gchar *str = lua_tostring (L, pos); + gsize r = 0; + + if (str) { + r = rspamd_strlcpy (outbuf, str, len); + } + + return r; +} + +static gsize +lua_logger_out_num (lua_State *L, gint pos, gchar *outbuf, gsize len) +{ + gdouble num = lua_tonumber (L, pos); + glong inum; + gsize r = 0; + + if ((gdouble)(glong)num == num) { + inum = num; + r = rspamd_snprintf (outbuf, len, "%ld", inum); + } + else { + r = rspamd_snprintf (outbuf, len, "%f", num); + } + + return r; +} + +static gsize +lua_logger_out_boolean (lua_State *L, gint pos, gchar *outbuf, gsize len) +{ + gboolean val = lua_toboolean (L, pos); + gsize r = 0; + + r = rspamd_strlcpy (outbuf, val ? "true" : "false", len); + + return r; +} + +#define MOVE_BUF(d, remain, r) if ((remain) - (r) == 0) break; (d) += (r); (remain) -= (r) + +static gsize +lua_logger_out_table (lua_State *L, gint pos, gchar *outbuf, gsize len) +{ + gchar *d = outbuf; + gsize remain = len, r; + gboolean first = TRUE; + + if (!lua_istable (L, pos)) { + return 0; + } + + lua_pushvalue (L, pos); + r = rspamd_snprintf (outbuf, remain, "{"); + + for (lua_pushnil (L); lua_next (L, -2) && remain > 0; lua_pop (L, 1)) { + /* 'key' is at index -2 and 'value' is at index -1 */ + if (!first) { + r = rspamd_snprintf (d, remain, ", "); + } + + MOVE_BUF(d, remain, r); + + if (lua_type (L, -2) == LUA_TNUMBER) { + r = rspamd_snprintf (d, remain, "[%d] = ", + lua_tonumber (L, -2)); + } + else if (lua_type (L, -2) == LUA_TSTRING) { + r = rspamd_snprintf (d, remain, "[%s] = ", + lua_tostring (L, -2)); + } + else { + g_assert (0); + } + + MOVE_BUF(d, remain, r); + r = lua_logger_out_type (L, -1, d, remain); + MOVE_BUF(d, remain, r); + } + + lua_pop (L, 1); + + r = rspamd_snprintf (outbuf, remain, "}"); + d += r; + + return (d - outbuf); } +#undef MOVE_BUF +static gsize +lua_logger_out_type (lua_State *L, gint pos, gchar *outbuf, gsize len) +{ + gint type; + gsize r = 0; + + type = lua_type (L, pos); + + switch (type) { + case LUA_TNUMBER: + r = lua_logger_out_num (L, pos, outbuf, len); + break; + case LUA_TBOOLEAN: + r = lua_logger_out_boolean (L, pos, outbuf, len); + break; + case LUA_TTABLE: + r = lua_logger_out_table (L, pos, outbuf, len); + break; + default: + /* Try to push everything as string using tostring magic */ + r = lua_logger_out_str (L, pos, outbuf, len); + break; + } + + return r; +} + +static gint +lua_logger_logx (lua_State *L, GLogLevelFlags level, gboolean is_string) +{ + static gchar logbuf[BUFSIZ]; + gchar *d; + const gchar *s, *c; + gsize remain, r; + guint arg_num = 0; + enum { + copy_char = 0, + got_percent, + parse_arg_num + } state = copy_char; + + d = logbuf; + remain = sizeof (logbuf); + s = lua_tostring (L, 1); + c = s; + + if (s == NULL) { + return 0; + } + + while (remain > 0 && *s != '\0') { + switch (state) { + case copy_char: + if (*s == '%') { + state = got_percent; + s ++; + } + else { + *d++ = *s++; + remain --; + } + break; + case got_percent: + if (g_ascii_isdigit (*s)) { + state = parse_arg_num; + c = s; + } + else { + *d++ = *s++; + state = copy_char; + } + break; + case parse_arg_num: + if (g_ascii_isdigit (*s)) { + s ++; + } + else { + arg_num = strtoul (c, NULL, 10); + + if (arg_num < 1 || arg_num > (guint)lua_gettop (L) + 1) { + msg_err ("wrong argument number: %ud", arg_num); + + if (is_string) { + lua_pushnil (L); + return 1; + } + else { + return 0; + } + } + + r = lua_logger_out_type (L, arg_num + 1, d, remain); + g_assert (r <= remain); + remain -= r; + d += r; + state = copy_char; + } + break; + } + } + + if (is_string) { + lua_pushlstring (L, logbuf, sizeof (logbuf) - remain); + return 1; + } + else { + *d = '\0'; + lua_common_log_line (level, L, logbuf); + } + + return 0; +} + +static gint +lua_logger_errx (lua_State * L) +{ + return lua_logger_logx (L, G_LOG_LEVEL_CRITICAL, FALSE); +} + +static gint +lua_logger_warnx (lua_State * L) +{ + return lua_logger_logx (L, G_LOG_LEVEL_WARNING, FALSE); +} + +static gint +lua_logger_infox (lua_State * L) +{ + return lua_logger_logx (L, G_LOG_LEVEL_INFO, FALSE); +} + +static gint +lua_logger_debugx (lua_State * L) +{ + return lua_logger_logx (L, G_LOG_LEVEL_DEBUG, FALSE); +} + +static gint +lua_logger_slog (lua_State * L) +{ + return lua_logger_logx (L, 0, TRUE); +} /*** Init functions ***/ -- 2.39.5