]> source.dussan.org Git - rspamd.git/commitdiff
Add new logger API.
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Sun, 5 Apr 2015 00:09:41 +0000 (01:09 +0100)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Sun, 5 Apr 2015 00:09:41 +0000 (01:09 +0100)
src/lua/lua_logger.c

index 0047190bfc8f1f99c7e9fbc17de9d65780a192a0..559a2a0f800a9602eeb46fdbe44dc9b6813667c2 100644 (file)
 
 #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 ***/