[collectd] [PATCH] desktop_notification: Added a plugin to send desktop notifications.

Sebastian Harl sh at tokkee.org
Mon May 19 23:08:17 CEST 2008


This plugin sends desktop notifications to a notification daemon, as
defined in the Desktop Notification Specification (see
http://www.galago-project.org/specs/notification/).

The timeout after which to expire the displayed notification may be
configured in collectd.conf.

Signed-off-by: Sebastian Harl <sh at tokkee.org>
---
 README                     |    9 +++
 configure.in               |    7 ++
 src/Makefile.am            |    9 +++
 src/collectd.conf.in       |    7 ++
 src/collectd.conf.pod      |   26 +++++++
 src/desktop_notification.c |  160 ++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 218 insertions(+), 0 deletions(-)
 create mode 100644 src/desktop_notification.c

diff --git a/README b/README
index 904e7c7..aad6a70 100644
--- a/README
+++ b/README
@@ -230,6 +230,12 @@ Features
 
   * Notifications can be handled by the following plugins:
 
+    - desktop_notification
+      Send a desktop notification to a notification daemon, as defined in
+      the Desktop Notification Specification. To actually display the
+      notifications, notification-daemon is required.
+      See http://www.galago-project.org/specs/notification/.
+
     - exec
       Execute a program or script to handle the notification.
       See collectd-exec(5).
@@ -333,6 +339,9 @@ Prerequisites
   * libnetsnmp (optional)
     For the `snmp' plugin.
 
+  * libnotify (optional)
+    For the `desktop_notification' plugin.
+
   * liboping (optional, if not found a version shipped with this distribution
     can be used)
     Used by the `ping' plugin to send and receive ICMP packets.
diff --git a/configure.in b/configure.in
index 3876b4f..57fb82c 100644
--- a/configure.in
+++ b/configure.in
@@ -1738,6 +1738,10 @@ then
 fi
 AM_CONDITIONAL(BUILD_WITH_LIBNETSNMP, test "x$with_libnetsnmp" = "xyes")
 
+PKG_CHECK_MODULES([LIBNOTIFY], [libnotify],
+		[with_libnotify="yes"],
+		[with_libnotify="no ($LIBNOTIFY_PKG_ERRORS)"])
+
 with_upsclient_config="libupsclient-config"
 with_upsclient_cflags=""
 with_upsclient_libs=""
@@ -2469,6 +2473,7 @@ AC_PLUGIN([battery],     [$plugin_battery],    [Battery statistics])
 AC_PLUGIN([cpu],         [$plugin_cpu],        [CPU usage statistics])
 AC_PLUGIN([cpufreq],     [$plugin_cpufreq],    [CPU frequency statistics])
 AC_PLUGIN([csv],         [yes],                [CSV output plugin])
+AC_PLUGIN([desktop_notification], [$with_libnotify], [Desktop notifications])
 AC_PLUGIN([df],          [$plugin_df],         [Filesystem usage statistics])
 AC_PLUGIN([disk],        [$plugin_disk],       [Disk usage statistics])
 AC_PLUGIN([dns],         [$with_libpcap],      [DNS traffic analysis])
@@ -2598,6 +2603,7 @@ Configuration:
     libmysql  . . . . . $with_libmysql
     libnetlink  . . . . $with_libnetlink
     libnetsnmp  . . . . $with_libnetsnmp
+    libnotify . . . . . $with_libnotify
     liboconfig  . . . . $with_liboconfig
     libopenipmi . . . . $with_libopenipmipthread
     liboping  . . . . . $with_liboping
@@ -2628,6 +2634,7 @@ Configuration:
     cpu . . . . . . . . $enable_cpu
     cpufreq . . . . . . $enable_cpufreq
     csv . . . . . . . . $enable_csv
+    desktop_notification $enable_desktop_notification
     df  . . . . . . . . $enable_df
     disk  . . . . . . . $enable_disk
     dns . . . . . . . . $enable_dns
diff --git a/src/Makefile.am b/src/Makefile.am
index 2102249..194c1a7 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -181,6 +181,15 @@ collectd_LDADD += "-dlopen" csv.la
 collectd_DEPENDENCIES += csv.la
 endif
 
+if BUILD_PLUGIN_DESKTOP_NOTIFICATION
+pkglib_LTLIBRARIES += desktop_notification.la
+desktop_notification_la_SOURCES = desktop_notification.c
+desktop_notification_la_CFLAGS = $(LIBNOTIFY_CFLAGS)
+desktop_notification_la_LDFLAGS = -module -avoid-version $(LIBNOTIFY_LIBS)
+collectd_LDADD += "-dlopen" desktop_notification.la
+collectd_DEPENDENCIES += desktop_notification.la
+endif
+
 if BUILD_PLUGIN_DF
 pkglib_LTLIBRARIES += df.la
 df_la_SOURCES = df.c
diff --git a/src/collectd.conf.in b/src/collectd.conf.in
index e900ce8..eaa3de1 100644
--- a/src/collectd.conf.in
+++ b/src/collectd.conf.in
@@ -21,6 +21,7 @@ FQDNLookup   true
 @BUILD_PLUGIN_CPU_TRUE at LoadPlugin cpu
 @BUILD_PLUGIN_CPUFREQ_TRUE at LoadPlugin cpufreq
 @BUILD_PLUGIN_CSV_TRUE at LoadPlugin csv
+ at BUILD_PLUGIN_DESKTOP_NOTIFICATION_TRUE@LoadPlugin desktop_notification
 @BUILD_PLUGIN_DF_TRUE at LoadPlugin df
 @BUILD_PLUGIN_DISK_TRUE at LoadPlugin disk
 @BUILD_PLUGIN_DNS_TRUE at LoadPlugin dns
@@ -93,6 +94,12 @@ FQDNLookup   true
 #	StoreRates false
 #</Plugin>
 
+#<Plugin desktop_notification>
+#	OkayTimeout 1000
+#	WarningTimeout 5000
+#	FailureTimeout 0
+#</Plugin>
+
 #<Plugin df>
 #	Device "/dev/hda1"
 #	Device "192.168.0.2:/mnt/nfs"
diff --git a/src/collectd.conf.pod b/src/collectd.conf.pod
index afa0571..2c4ff46 100644
--- a/src/collectd.conf.pod
+++ b/src/collectd.conf.pod
@@ -265,6 +265,32 @@ number.
 
 =back
 
+=head2 Plugin C<desktop_notification>
+
+This plugin sends a desktop notification to a notification daemon, as defined
+in the Desktop Notification Specification. To actually display the
+notifications, B<notification-daemon> is required and B<collectd> has to be
+able to access the X server.
+
+The Desktop Notification Specification can be found at
+L<http://www.galago-project.org/specs/notification/>.
+
+=over 4
+
+=item B<OkayTimeout> I<timeout>
+
+=item B<WarningTimeout> I<timeout>
+
+=item B<FailureTimeout> I<timeout>
+
+Set the I<timeout>, in milliseconds, after which to expire the notification
+for C<OKAY>, C<WARNING> and C<FAILURE> severities respectively. If zero has
+been specified, the displayed notification will not be closed at all - the
+user has to do so herself. These options default to 5000. If a negative number
+has been specified, the default is used as well.
+
+=back
+
 =head2 Plugin C<df>
 
 =over 4
diff --git a/src/desktop_notification.c b/src/desktop_notification.c
new file mode 100644
index 0000000..3b6af07
--- /dev/null
+++ b/src/desktop_notification.c
@@ -0,0 +1,160 @@
+/**
+ * collectd - src/desktop_notification.c
+ * Copyright (C) 2008  Sebastian Harl
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Author:
+ *   Sebastian Harl <sh at tokkee.org>
+ **/
+
+/*
+ * This plugin sends desktop notifications to a notification daemon.
+ */
+
+#include "collectd.h"
+#include "plugin.h"
+#include "configfile.h"
+
+#include <glib.h>
+#include <libnotify/notify.h>
+
+#define log_info(...) INFO ("desktop_notification: " __VA_ARGS__)
+#define log_warn(...) WARNING ("desktop_notification: " __VA_ARGS__)
+#define log_err(...) ERROR ("desktop_notification: " __VA_ARGS__)
+
+#define DEFAULT_TIMEOUT 5000
+
+static int okay_timeout = DEFAULT_TIMEOUT;
+static int warn_timeout = DEFAULT_TIMEOUT;
+static int fail_timeout = DEFAULT_TIMEOUT;
+
+static int set_timeout (oconfig_item_t *ci, int *timeout)
+{
+	if ((0 != ci->children_num) || (1 != ci->values_num)
+			|| (OCONFIG_TYPE_NUMBER != ci->values[0].type)) {
+		log_err ("%s expects a single number argument.", ci->key);
+		return 1;
+	}
+
+	*timeout = (int)ci->values[0].value.number;
+	if (0 > *timeout)
+		*timeout = DEFAULT_TIMEOUT;
+	return 0;
+} /* set_timeout */
+
+static int c_notify_config (oconfig_item_t *ci)
+{
+	int i = 0;
+
+	for (i = 0; i < ci->children_num; ++i) {
+		oconfig_item_t *c = ci->children + i;
+
+		if (0 == strcasecmp (c->key, "OkayTimeout"))
+			set_timeout (c, &okay_timeout);
+		else if (0 == strcasecmp (c->key, "WarningTimeout"))
+			set_timeout (c, &warn_timeout);
+		else if (0 == strcasecmp (c->key, "FailureTimeout"))
+			set_timeout (c, &fail_timeout);
+	}
+	return 0;
+} /* c_notify_config */
+
+static int c_notify (const notification_t *n)
+{
+	NotifyNotification *notification = NULL;
+	NotifyUrgency       urgency      = NOTIFY_URGENCY_LOW;
+	int                 timeout      = okay_timeout;
+
+	char summary[1024];
+
+	if (NOTIF_WARNING == n->severity) {
+		urgency = NOTIFY_URGENCY_NORMAL;
+		timeout = warn_timeout;
+	}
+	else if (NOTIF_FAILURE == n->severity) {
+		urgency = NOTIFY_URGENCY_CRITICAL;
+		timeout = fail_timeout;
+	}
+
+	ssnprintf (summary, sizeof (summary), "collectd %s notification",
+			(NOTIF_FAILURE == n->severity) ? "FAILURE"
+				: (NOTIF_WARNING == n->severity) ? "WARNING"
+				: (NOTIF_OKAY == n->severity) ? "OKAY" : "UNKNOWN");
+
+	notification = notify_notification_new (summary, n->message, NULL, NULL);
+	if (NULL == notification) {
+		log_err ("Failed to create a new notification.");
+		return -1;
+	}
+
+	notify_notification_set_urgency (notification, urgency);
+	notify_notification_set_timeout (notification, timeout);
+
+	if (! notify_notification_show (notification, NULL))
+		log_err ("Failed to display notification.");
+
+	g_object_unref (G_OBJECT (notification));
+	return 0;
+} /* c_notify */
+
+static int c_notify_shutdown (void)
+{
+	plugin_unregister_init ("desktop_notification");
+	plugin_unregister_notification ("desktop_notification");
+	plugin_unregister_shutdown ("desktop_notification");
+
+	if (notify_is_initted ())
+		notify_uninit ();
+	return 0;
+} /* c_notify_shutdown */
+
+static int c_notify_init (void)
+{
+	char *name         = NULL;
+	char *vendor       = NULL;
+	char *version      = NULL;
+	char *spec_version = NULL;
+
+	if (! notify_init (PACKAGE_STRING)) {
+		log_err ("Failed to initialize libnotify.");
+		return -1;
+	}
+
+	if (! notify_get_server_info (&name, &vendor, &version, &spec_version))
+		log_warn ("Failed to get the notification server info. "
+				"Check if you have a notification daemon running.");
+	else {
+		log_info ("Found notification daemon: %s (%s) %s (spec version %s)",
+				name, vendor, version, spec_version);
+		free (name);
+		free (vendor);
+		free (version);
+		free (spec_version);
+	}
+
+	plugin_register_notification ("desktop_notification", c_notify);
+	plugin_register_shutdown ("desktop_notification", c_notify_shutdown);
+	return 0;
+} /* c_notify_init */
+
+void module_register (void)
+{
+	plugin_register_complex_config ("desktop_notification", c_notify_config);
+	plugin_register_init ("desktop_notification", c_notify_init);
+	return;
+} /* module_register */
+
+/* vim: set sw=4 ts=4 tw=78 noexpandtab : */
+
-- 
1.5.5.1.125.gc697a

-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
Url : http://mailman.verplant.org/pipermail/collectd/attachments/20080519/4cab1ed3/attachment.pgp 


More information about the collectd mailing list