summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: e4b8a18)
raw | patch | inline | side by side (parent: e4b8a18)
author | Marco Chiappero <marco@absence.it> | |
Thu, 19 Mar 2009 12:30:32 +0000 (13:30 +0100) | ||
committer | Florian Forster <octo@huhu.verplant.org> | |
Thu, 19 Mar 2009 12:30:32 +0000 (13:30 +0100) |
Florian Forster ha scritto:
>Hi Marco,
Hi Florian,
> Checking the KSTAT_TYPE_NAMED twice (three times if you count the
> assertion) is of course not necessary. I suspect a copy'n'paste error ;)
Me too. Please remove the second one at least, kstat_read do not change
ks_type.
>A quick `grep' revealed that `get_kstat' is only used in two places, the
>memory and the swap plugin - both trying to figure out the pagesize. If
>you need something else than `KSTAT_TYPE_NAMED', I'd suggest to move the
>checks to a new function `get_kstat_pagesize' and use that function in
>the two plugins.
I went for the kstat.h only solution.
Ok, I'm attaching the code, please check the preprocessor directives for
the includes section, I don't much about defines created by the build
system and its names.
I'm using it right now on a linux machine, but I haven't tested yet on
Solaris and BSDs. Today I tried to compile it on OpenSolaris, but after
fighting with the packaging system and many other things I gave up and
decided I won't try anymore. So, since I'd like to say the plugin is
done after testing it, Solaris testers are wanted :P
As soon as I can I will edit the wiki page, but first I want to have a
closer look to the iptable plugin and see how many modifications are
needed for IPv6 and then have an opinion about the single vs. double
plugin approach.
See you soon :)
Regars,
Marco
>Hi Marco,
Hi Florian,
> Checking the KSTAT_TYPE_NAMED twice (three times if you count the
> assertion) is of course not necessary. I suspect a copy'n'paste error ;)
Me too. Please remove the second one at least, kstat_read do not change
ks_type.
>A quick `grep' revealed that `get_kstat' is only used in two places, the
>memory and the swap plugin - both trying to figure out the pagesize. If
>you need something else than `KSTAT_TYPE_NAMED', I'd suggest to move the
>checks to a new function `get_kstat_pagesize' and use that function in
>the two plugins.
I went for the kstat.h only solution.
Ok, I'm attaching the code, please check the preprocessor directives for
the includes section, I don't much about defines created by the build
system and its names.
I'm using it right now on a linux machine, but I haven't tested yet on
Solaris and BSDs. Today I tried to compile it on OpenSolaris, but after
fighting with the packaging system and many other things I gave up and
decided I won't try anymore. So, since I'd like to say the plugin is
done after testing it, Solaris testers are wanted :P
As soon as I can I will edit the wiki page, but first I want to have a
closer look to the iptable plugin and see how many modifications are
needed for IPv6 and then have an opinion about the single vs. double
plugin approach.
See you soon :)
Regars,
Marco
src/types.db | patch | blob | history | |
src/uptime.c | [new file with mode: 0644] | patch | blob |
diff --git a/src/types.db b/src/types.db
index f0525fe4064a79f8c7d191e3e7441b82b0cbaa62..05f5f7911ece643ba5a84298125174debd6f55c2 100644 (file)
--- a/src/types.db
+++ b/src/types.db
time_dispersion seconds:GAUGE:-1000000:1000000
timeleft timeleft:GAUGE:0:3600
time_offset seconds:GAUGE:-1000000:1000000
+uptime value:GAUGE:0:4294967295
users users:GAUGE:0:65535
virt_cpu_total ns:COUNTER:0:256000000000
virt_vcpu ns:COUNTER:0:1000000000
diff --git a/src/uptime.c b/src/uptime.c
--- /dev/null
+++ b/src/uptime.c
@@ -0,0 +1,227 @@
+/**
+ * collectd - src/uptime.c
+ * Copyright (C) 2009 Marco Chiappero
+ *
+ * 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
+ *
+ * Authors:
+ * Marco Chiappero <marco at absence.it>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+
+#if KERNEL_LINUX
+# define UPTIME_FILE "/proc/uptime"
+/*
+ No need for includes, using /proc filesystem, Linux only.
+*/
+/* #endif KERNEL_LINUX */
+
+#elif HAVE_LIBKSTAT
+/* something to include? maybe <sys/sysinfo.h> ? */
+/*
+ Using kstats chain to retrieve the boot time, this applies to:
+ - Solaris / OpenSolaris
+*/
+/* #endif HAVE_LIBKSTAT */
+
+#elif HAVE_SYS_SYSCTL_H
+# include <sys/sysctl.h>
+/*
+ Using sysctl interface to retrieve the boot time, this applies to:
+ - *BSD
+ - Darwin / OS X
+*/
+/* #endif HAVE_SYS_SYSCTL_H */
+
+#else
+# error "No applicable input method."
+#endif
+
+
+#if !KERNEL_LINUX
+#define INIT_FAILED "uptime plugin: unable to calculate uptime, the plugin will be disabled."
+#endif
+
+
+#if KERNEL_LINUX
+/* global variables not needed*/
+
+#elif HAVE_SYS_SYSCTL_H || HAVE_LIBKSTAT
+static time_t boottime;
+# if HAVE_LIBKSTAT
+extern kstat_ctl_t *kc;
+# endif
+
+#endif
+
+
+static void uptime_submit (gauge_t uptime)
+{
+ value_t values[1];
+ value_list_t vl = VALUE_LIST_INIT;
+
+ values[0].gauge = uptime;
+
+ vl.values = values;
+ vl.values_len = 1;
+ vl.time = time (NULL);
+
+ sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+ sstrncpy (vl.plugin, "uptime", sizeof (vl.plugin));
+ sstrncpy (vl.type, "uptime", sizeof (vl.type));
+
+ plugin_dispatch_values (&vl);
+}
+
+#if !KERNEL_LINUX
+static int uptime_init (void)
+{
+/* NOTE
+
+ On unix systems other than Linux there is no /proc filesystem which
+ calculates the uptime every time we call a read for the /proc/uptime
+ file, the only information available is the boot time (in unix time,
+ since epoch). Hence there is no need to read, every time the
+ plugin_read is called, a value that won't change: this is a right
+ task for the uptime_init function. However, since uptime_init is run
+ only once, if the function fails in retrieving the boot time, the
+ plugin is unregistered and there is no chance to try again later.
+ Nevertheless, this is very unlikely to happen.
+
+*/
+
+# if HAVE_LIBKSTAT
+
+ kstat_t *ksp;
+ kstat_named_t *knp;
+
+ ksp = NULL;
+ knp = NULL;
+
+ /* kstats chain already opened by update_kstat (using *kc), let's verify everything went fine. */
+ if ( kc == NULL )
+ {
+ ERROR ("uptime plugin: unable to open kstat control structure");
+ ERROR (INIT_FAILED);
+ return (-1);
+ }
+
+ if (( ksp = kstat_lookup (kc, "unix", 0, "system_misc")) == NULL )
+ {
+ ERROR ("uptime plugin: cannot find %s kstat", "unix:0:system_misc");
+ ERROR (INIT_FAILED);
+ return (-1);
+ }
+
+ if (( kstat_read (kc, ksp, NULL) < 0 ) ||
+ (( knp = (kstat_named_t *) kstat_data_lookup (ksp, "boot_time")) != NULL ))
+ {
+ ERROR ("uptime plugin: kstat data reading failed");
+ ERROR (INIT_FAILED);
+ return (-1);
+ }
+
+ boottime = (time_t) knp->value.ui32;
+
+/* #endif HAVE_LIBKSTAT */
+
+# elif HAVE_SYS_SYSCTL_H
+
+ struct timeval boottv;
+ size_t boottv_len;
+
+ int mib[2];
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_BOOTTIME;
+
+ boottv_len = sizeof (boottv);
+
+ if (( sysctl (mib, 2, &boottv, &boottv_len, NULL, 0) != 0 ) || boottv.tv_sec == 0 )
+ {
+ char errbuf[1024];
+ ERROR ("uptime plugin: no value read from sysctl interface: %s",
+ sstrerror (errno, errbuf, sizeof (errbuf)));
+ ERROR (INIT_FAILED);
+ return (-1);
+ }
+
+ boottime = boottv.tv_sec;
+
+/* #endif HAVE_SYS_SYSCTL_H */
+
+# endif
+
+ return (0);
+
+}
+#endif
+
+static int uptime_read (void)
+{
+ gauge_t uptime;
+
+#if KERNEL_LINUX
+
+ FILE *fh;
+
+ fh = fopen (UPTIME_FILE, "r");
+
+ if (fh == NULL)
+ {
+ char errbuf[1024];
+ ERROR ("uptime plugin: cannot open %s: %s", UPTIME_FILE,
+ sstrerror (errno, errbuf, sizeof (errbuf)));
+ return (-1);
+ }
+
+ if ( fscanf (fh, "%lf", &uptime) < 1 )
+ {
+ WARNING ("no value read from %s", UPTIME_FILE);
+ fclose (fh);
+ return (-1);
+ }
+
+ fclose (fh);
+
+/* #endif KERNEL_LINUX */
+
+
+#elif HAVE_SYS_SYSCTL_H || HAVE_LIBKSTAT
+
+ time_t elapsed;
+
+ elapsed = time (NULL) - boottime;
+
+ uptime = (gauge_t) elapsed;
+
+/* #endif HAVE_SYS_SYSCTL_H */
+
+#endif
+
+ uptime_submit (uptime);
+
+ return (0);
+}
+
+void module_register (void)
+{
+#if !KERNEL_LINUX
+ plugin_register_init ("uptime", uptime_init);
+#endif
+ plugin_register_read ("uptime", uptime_read);
+} /* void module_register */