summaryrefslogtreecommitdiffstats
path: root/src/lua/lua_logger.c
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2015-04-05 01:09:41 +0100
committerVsevolod Stakhov <vsevolod@highsecure.ru>2015-04-05 01:09:41 +0100
commit8b01c72fc883bf50d8827763b4ad3d793f8a176d (patch)
tree18564d177b3e73582d8295de231675f0ce5310d8 /src/lua/lua_logger.c
parent5d376e9b1ac313d1ec1bfd296b965c50f434a5f6 (diff)
downloadrspamd-8b01c72fc883bf50d8827763b4ad3d793f8a176d.tar.gz
rspamd-8b01c72fc883bf50d8827763b4ad3d793f8a176d.zip
Add new logger API.
Diffstat (limited to 'src/lua/lua_logger.c')
-rw-r--r--src/lua/lua_logger.c263
1 files 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 ***/