2 * collectd - src/uptime.c
3 * Copyright (C) 2009 Marco Chiappero
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; only version 2 of the License is applicable.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 * Marco Chiappero <marco at absence.it>
27 # define UPTIME_FILE "/proc/uptime"
29 No need for includes, using /proc filesystem, Linux only.
31 /* #endif KERNEL_LINUX */
34 /* something to include? maybe <sys/sysinfo.h> ? */
36 Using kstats chain to retrieve the boot time, this applies to:
37 - Solaris / OpenSolaris
39 /* #endif HAVE_LIBKSTAT */
41 #elif HAVE_SYS_SYSCTL_H
42 # include <sys/sysctl.h>
44 Using sysctl interface to retrieve the boot time, this applies to:
48 /* #endif HAVE_SYS_SYSCTL_H */
51 # error "No applicable input method."
56 #define INIT_FAILED "uptime plugin: unable to calculate uptime, the plugin will be disabled."
61 /* global variables not needed*/
63 #elif HAVE_SYS_SYSCTL_H || HAVE_LIBKSTAT
64 static time_t boottime;
66 extern kstat_ctl_t *kc;
72 static void uptime_submit (gauge_t uptime)
75 value_list_t vl = VALUE_LIST_INIT;
77 values[0].gauge = uptime;
81 vl.time = time (NULL);
83 sstrncpy (vl.host, hostname_g, sizeof (vl.host));
84 sstrncpy (vl.plugin, "uptime", sizeof (vl.plugin));
85 sstrncpy (vl.type, "uptime", sizeof (vl.type));
87 plugin_dispatch_values (&vl);
91 static int uptime_init (void)
95 On unix systems other than Linux there is no /proc filesystem which
96 calculates the uptime every time we call a read for the /proc/uptime
97 file, the only information available is the boot time (in unix time,
98 since epoch). Hence there is no need to read, every time the
99 plugin_read is called, a value that won't change: this is a right
100 task for the uptime_init function. However, since uptime_init is run
101 only once, if the function fails in retrieving the boot time, the
102 plugin is unregistered and there is no chance to try again later.
103 Nevertheless, this is very unlikely to happen.
115 /* kstats chain already opened by update_kstat (using *kc), let's verify everything went fine. */
118 ERROR ("uptime plugin: unable to open kstat control structure");
123 if (( ksp = kstat_lookup (kc, "unix", 0, "system_misc")) == NULL )
125 ERROR ("uptime plugin: cannot find %s kstat", "unix:0:system_misc");
130 if (( kstat_read (kc, ksp, NULL) < 0 ) ||
131 (( knp = (kstat_named_t *) kstat_data_lookup (ksp, "boot_time")) != NULL ))
133 ERROR ("uptime plugin: kstat data reading failed");
138 boottime = (time_t) knp->value.ui32;
140 /* #endif HAVE_LIBKSTAT */
142 # elif HAVE_SYS_SYSCTL_H
144 struct timeval boottv;
150 mib[1] = KERN_BOOTTIME;
152 boottv_len = sizeof (boottv);
154 if (( sysctl (mib, 2, &boottv, &boottv_len, NULL, 0) != 0 ) || boottv.tv_sec == 0 )
157 ERROR ("uptime plugin: no value read from sysctl interface: %s",
158 sstrerror (errno, errbuf, sizeof (errbuf)));
163 boottime = boottv.tv_sec;
165 /* #endif HAVE_SYS_SYSCTL_H */
174 static int uptime_read (void)
182 fh = fopen (UPTIME_FILE, "r");
187 ERROR ("uptime plugin: cannot open %s: %s", UPTIME_FILE,
188 sstrerror (errno, errbuf, sizeof (errbuf)));
192 if ( fscanf (fh, "%lf", &uptime) < 1 )
194 WARNING ("no value read from %s", UPTIME_FILE);
201 /* #endif KERNEL_LINUX */
204 #elif HAVE_SYS_SYSCTL_H || HAVE_LIBKSTAT
208 elapsed = time (NULL) - boottime;
210 uptime = (gauge_t) elapsed;
212 /* #endif HAVE_SYS_SYSCTL_H */
216 uptime_submit (uptime);
221 void module_register (void)
224 plugin_register_init ("uptime", uptime_init);
226 plugin_register_read ("uptime", uptime_read);
227 } /* void module_register */