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>
28 #define UPTIME_FILE "/proc/uptime"
29 /* Using /proc filesystem to retrieve the boot time, Linux only. */
30 /* #endif KERNEL_LINUX */
33 /* Using kstats chain to retrieve the boot time on Solaris / OpenSolaris systems
35 /* #endif HAVE_LIBKSTAT */
37 #elif HAVE_SYS_SYSCTL_H
38 #include <sys/sysctl.h>
39 /* Using sysctl interface to retrieve the boot time on *BSD / Darwin / OS X
41 /* #endif HAVE_SYS_SYSCTL_H */
44 #include <libperfstat.h>
45 #include <sys/protosw.h>
46 /* Using perfstat_cpu_total to retrive the boot time in AIX */
47 /* #endif HAVE_PERFSTAT */
50 #error "No applicable input method."
56 /* boottime always used, no OS distinction */
57 static time_t boottime;
60 extern kstat_ctl_t *kc;
61 #endif /* #endif HAVE_LIBKSTAT */
63 static void uptime_submit(gauge_t value) {
64 value_list_t vl = VALUE_LIST_INIT;
66 vl.values = &(value_t){.gauge = value};
69 sstrncpy(vl.plugin, "uptime", sizeof(vl.plugin));
70 sstrncpy(vl.type, "uptime", sizeof(vl.type));
72 plugin_dispatch_values(&vl);
75 static int uptime_init(void) /* {{{ */
78 * On most unix systems the uptime is calculated by looking at the boot
79 * time (stored in unix time, since epoch) and the current one. We are
80 * going to do the same, reading the boot time value while executing
81 * the uptime_init function (there is no need to read, every time the
82 * plugin_read is called, a value that won't change). However, since
83 * uptime_init is run only once, if the function fails in retrieving
84 * the boot time, the plugin is unregistered and there is no chance to
85 * try again later. Nevertheless, this is very unlikely to happen.
89 double uptime_seconds;
95 fh = fopen(UPTIME_FILE, "r");
99 ERROR("uptime plugin: Cannot open " UPTIME_FILE ": %s",
100 sstrerror(errno, errbuf, sizeof(errbuf)));
104 ret = fscanf(fh, "%lf", &uptime_seconds);
108 /* loop done, check if no value has been found/read */
110 ERROR("uptime plugin: No value read from " UPTIME_FILE "");
114 if (uptime_seconds == 0.0) {
115 ERROR("uptime plugin: uptime read from " UPTIME_FILE ", "
120 boottime = time(NULL) - (long)uptime_seconds;
121 /* #endif KERNEL_LINUX */
130 /* kstats chain already opened by update_kstat (using *kc), verify everything
133 ERROR("uptime plugin: kstat chain control structure not available.");
137 ksp = kstat_lookup(kc, "unix", 0, "system_misc");
139 ERROR("uptime plugin: Cannot find unix:0:system_misc kstat.");
143 if (kstat_read(kc, ksp, NULL) < 0) {
144 ERROR("uptime plugin: kstat_read failed.");
148 knp = (kstat_named_t *)kstat_data_lookup(ksp, "boot_time");
150 ERROR("uptime plugin: kstat_data_lookup (boot_time) failed.");
154 boottime = (time_t)knp->value.ui32;
157 ERROR("uptime plugin: kstat_data_lookup returned success, "
158 "but `boottime' is zero!");
161 /* #endif HAVE_LIBKSTAT */
163 #elif HAVE_SYS_SYSCTL_H
164 struct timeval boottv = {0};
168 int mib[] = {CTL_KERN, KERN_BOOTTIME};
170 boottv_len = sizeof(boottv);
172 status = sysctl(mib, STATIC_ARRAY_SIZE(mib), &boottv, &boottv_len,
173 /* new_value = */ NULL, /* new_length = */ 0);
176 ERROR("uptime plugin: No value read from sysctl interface: %s",
177 sstrerror(errno, errbuf, sizeof(errbuf)));
181 boottime = boottv.tv_sec;
184 ERROR("uptime plugin: sysctl(3) returned success, "
185 "but `boottime' is zero!");
188 /* #endif HAVE_SYS_SYSCTL_H */
192 perfstat_cpu_total_t cputotal;
195 status = perfstat_cpu_total(NULL, &cputotal, sizeof(perfstat_cpu_total_t), 1);
198 ERROR("uptime plugin: perfstat_cpu_total: %s",
199 sstrerror(errno, errbuf, sizeof(errbuf)));
203 hertz = sysconf(_SC_CLK_TCK);
207 boottime = time(NULL) - cputotal.lbolt / hertz;
208 #endif /* HAVE_PERFSTAT */
211 } /* }}} int uptime_init */
213 static int uptime_read(void) {
217 /* calculate the amount of time elapsed since boot, AKA uptime */
218 elapsed = time(NULL) - boottime;
220 uptime = (gauge_t)elapsed;
222 uptime_submit(uptime);
227 void module_register(void) {
228 plugin_register_init("uptime", uptime_init);
229 plugin_register_read("uptime", uptime_read);
230 } /* void module_register */