]> git.ipfire.org Git - thirdparty/collectd.git/commitdiff
lua: add missing notification callback
authorKentaro Hayashi <hayashi@clear-code.com>
Sat, 13 Jan 2024 08:27:32 +0000 (17:27 +0900)
committerKentaro Hayashi <hayashi@clear-code.com>
Sat, 13 Jan 2024 11:32:23 +0000 (20:32 +0900)
* 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 <hayashi@clear-code.com>
src/lua.c
src/utils_lua.c

index 53bf781f1c2f0d7f70eec41fd55697f62c6b3e60..0b0406c8a86d63e4eb0985ce48fcedc24632dde0 100644 (file)
--- 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) /* {{{ */
index 8e131cd1017f87ab0bbcc238bcadd6b94c7f3721..451b7f1b7d78095b49d0f8281f8c9899afa17f0b 100644 (file)
@@ -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 */