From: Kentaro Hayashi Date: Sat, 13 Jan 2024 08:27:32 +0000 (+0900) Subject: lua: add missing notification callback X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0f7e490cc0db52c4fe6d3b7b295dd8dbe86fb026;p=thirdparty%2Fcollectd.git lua: add missing notification callback * register_notification In this version, it support callback function something like: function notification(notif) print(inspect(notif)) return 0 end collectd.register_notification(notification) It accepts PUTNOTIF event via plugin_dispatch_notification then you can handle it. Signed-off-by: Kentaro Hayashi --- diff --git a/src/lua.c b/src/lua.c index 53bf781f1..0b0406c8a 100644 --- a/src/lua.c +++ b/src/lua.c @@ -46,6 +46,7 @@ #define PLUGIN_WRITE 2 #define PLUGIN_SHUTDOWN 3 #define PLUGIN_CONFIG 4 +#define PLUGIN_NOTIFICATION 5 typedef struct lua_script_s { lua_State *lua_state; @@ -204,6 +205,62 @@ static int clua_write(const data_set_t *ds, const value_list_t *vl, /* {{{ */ return status; } /* }}} int clua_write */ +static int clua_notification(const notification_t *notify, + user_data_t *ud) /* {{{ */ +{ + clua_callback_data_t *cb = ud->data; + + pthread_mutex_lock(&lua_lock); + + lua_State *L = cb->lua_state; + + int status = clua_load_callback(L, cb->callback_id); + if (status != 0) { + ERROR("Lua plugin: Unable to load callback \"%s\" (id %i).", + cb->lua_function_name, cb->callback_id); + pthread_mutex_unlock(&lua_lock); + return -1; + } + /* +1 = 1 */ + + /* convert notification_t to table on stack */ + status = luaC_pushnotification(L, notify); + if (status != 0) { + lua_pop(L, 1); /* -1 = 0 */ + pthread_mutex_unlock(&lua_lock); + ERROR("Lua plugin: luaC_notification failed."); + return -1; + } + /* +1 = 2 */ + + status = lua_pcall(L, 1, 1, 0); /* -2+1 = 1 */ + if (status != 0) { + const char *errmsg = lua_tostring(L, -1); + if (errmsg == NULL) + ERROR("Lua plugin: Calling the notification callback failed. " + "In addition, retrieving the error message failed."); + else + ERROR("Lua plugin: Calling the notification callback failed:\n%s", + errmsg); + lua_pop(L, 1); /* -1 = 0 */ + pthread_mutex_unlock(&lua_lock); + return -1; + } + + if (!lua_isnumber(L, -1)) { + ERROR("Lua plugin: Notification function \"%s\" (id %i) did not return a " + "numeric value.", + cb->lua_function_name, cb->callback_id); + status = -1; + } else { + status = (int)lua_tointeger(L, -1); + } + + lua_pop(L, 1); /* -1 = 0 */ + pthread_mutex_unlock(&lua_lock); + return status; +} /* }}} int clua_notification */ + /* * Exported functions */ @@ -400,6 +457,17 @@ static int lua_cb_register_generic(lua_State *L, int type) /* {{{ */ if (status != 0) return luaL_error(L, "lua_cb_register_plugin_callbacks(config) failed"); return 0; + } else if (PLUGIN_NOTIFICATION == type) { + int status = + plugin_register_notification(/* name = */ function_name, + /* callback = */ clua_notification, + &(user_data_t){ + .data = cb, + .free_func = lua_cb_free, + }); + if (status != 0) + return luaL_error(L, "plugin_register_notification failed"); + return 0; } else { return luaL_error(L, "%s", "lua_cb_register_generic unsupported type"); } @@ -425,6 +493,10 @@ static int lua_cb_register_config(lua_State *L) { return lua_cb_register_generic(L, PLUGIN_CONFIG); } +static int lua_cb_register_notification(lua_State *L) { + return lua_cb_register_generic(L, PLUGIN_NOTIFICATION); +} + static const luaL_Reg collectdlib[] = { {"log_debug", lua_cb_log_debug}, {"log_error", lua_cb_log_error}, @@ -437,6 +509,7 @@ static const luaL_Reg collectdlib[] = { {"register_init", lua_cb_register_init}, {"register_shutdown", lua_cb_register_shutdown}, {"register_config", lua_cb_register_config}, + {"register_notification", lua_cb_register_notification}, {NULL, NULL}}; static int open_collectd(lua_State *L) /* {{{ */ diff --git a/src/utils_lua.c b/src/utils_lua.c index 8e131cd10..451b7f1b7 100644 --- a/src/utils_lua.c +++ b/src/utils_lua.c @@ -382,3 +382,92 @@ int luaC_pushoconfigitem(lua_State *L, const oconfig_item_t *ci) /* {{{ */ } return 0; } /* }}} int luaC_pushoconfigitem */ + +static int luaC_pushnotificationmeta(lua_State *L, + const notification_meta_t *meta) /* {{{ */ +{ + /* + notification_meta_t will be mapped to the following Lua table: + { + key1 => value1, + ..., + keyN => valueN + + } + */ + lua_newtable(L); + for (; meta != NULL; meta = meta->next) { + switch (meta->type) { + case NM_TYPE_STRING: + lua_pushstring(L, meta->nm_value.nm_string); + break; + case NM_TYPE_SIGNED_INT: + lua_pushnumber(L, meta->nm_value.nm_signed_int); + break; + case NM_TYPE_UNSIGNED_INT: + lua_pushnumber(L, meta->nm_value.nm_unsigned_int); + break; + case NM_TYPE_DOUBLE: + lua_pushnumber(L, meta->nm_value.nm_double); + break; + case NM_TYPE_BOOLEAN: + lua_pushboolean(L, meta->nm_value.nm_boolean); + break; + } + lua_setfield(L, -2, meta->name); + } + return 0; +} + +int luaC_pushnotification(lua_State *L, + const notification_t *notification) /* {{{ */ +{ + /* + notification_t will be mapped to the following Lua table: + + { + severity => ..., + time => ..., + message => ..., + host => ..., + plugin => ..., + plugin_instance => ..., + type => ..., + type_instance => ..., + meta => luaC_pushnotificationmeta(); + } + */ + + lua_newtable(L); + switch (notification->severity) { + case NOTIF_FAILURE: + lua_pushstring(L, "failure"); + lua_setfield(L, -2, "severity"); + break; + case NOTIF_WARNING: + lua_pushstring(L, "warning"); + lua_setfield(L, -2, "severity"); + break; + case NOTIF_OKAY: + lua_pushstring(L, "okay"); + lua_setfield(L, -2, "severity"); + break; + } + luaC_pushcdtime(L, notification->time); + lua_setfield(L, -2, "time"); + lua_pushstring(L, notification->message); + lua_setfield(L, -2, "message"); + lua_pushstring(L, notification->host); + lua_setfield(L, -2, "host"); + lua_pushstring(L, notification->plugin); + lua_setfield(L, -2, "plugin"); + lua_pushstring(L, notification->plugin_instance); + lua_setfield(L, -2, "plugin_instance"); + lua_pushstring(L, notification->type); + lua_setfield(L, -2, "type"); + lua_pushstring(L, notification->type_instance); + lua_setfield(L, -2, "type_instance"); + luaC_pushnotificationmeta(L, notification->meta); + lua_setfield(L, -2, "meta"); + return 0; +} /* }}} int luaC_pushnotification */