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 STAT_FILE "/proc/stat"
28 /* Using /proc filesystem to retrieve the boot time, Linux only. */
29 /* #endif KERNEL_LINUX */
32 /* Using kstats chain to retrieve the boot time on Solaris / OpenSolaris systems */
33 /* #endif HAVE_LIBKSTAT */
35 #elif HAVE_SYS_SYSCTL_H
36 # include <sys/sysctl.h>
37 /* Using sysctl interface to retrieve the boot time on *BSD / Darwin / OS X systems */
38 /* #endif HAVE_SYS_SYSCTL_H */
41 # include <sys/protosw.h>
42 # include <libperfstat.h>
43 /* Using perfstat_cpu_total to retrive the boot time in AIX */
44 /* #endif HAVE_PERFSTAT */
47 # error "No applicable input method."
53 /* boottime always used, no OS distinction */
54 static time_t boottime;
57 extern kstat_ctl_t *kc;
58 #endif /* #endif HAVE_LIBKSTAT */
60 static void uptime_submit (gauge_t uptime)
63 value_list_t vl = VALUE_LIST_INIT;
65 values[0].gauge = uptime;
70 sstrncpy (vl.host, hostname_g, sizeof (vl.host));
71 sstrncpy (vl.plugin, "uptime", sizeof (vl.plugin));
72 sstrncpy (vl.type, "uptime", sizeof (vl.type));
74 plugin_dispatch_values (&vl);
77 static int uptime_init (void) /* {{{ */
80 * On most unix systems the uptime is calculated by looking at the boot
81 * time (stored in unix time, since epoch) and the current one. We are
82 * going to do the same, reading the boot time value while executing
83 * the uptime_init function (there is no need to read, every time the
84 * plugin_read is called, a value that won't change). However, since
85 * uptime_init is run only once, if the function fails in retrieving
86 * the boot time, the plugin is unregistered and there is no chance to
87 * try again later. Nevertheless, this is very unlikely to happen.
91 unsigned long starttime;
98 fh = fopen (STAT_FILE, "r");
103 ERROR ("uptime plugin: Cannot open "STAT_FILE": %s",
104 sstrerror (errno, errbuf, sizeof (errbuf)));
108 while (fgets (buffer, 1024, fh) != NULL)
110 /* look for the btime string and read the value */
111 ret = sscanf (buffer, "btime %lu", &starttime);
112 /* avoid further loops if btime has been found and read
113 * correctly (hopefully) */
120 /* loop done, check if no value has been found/read */
123 ERROR ("uptime plugin: No value read from "STAT_FILE"");
127 boottime = (time_t) starttime;
131 ERROR ("uptime plugin: btime read from "STAT_FILE", "
132 "but `boottime' is zero!");
135 /* #endif KERNEL_LINUX */
144 /* kstats chain already opened by update_kstat (using *kc), verify everything went fine. */
147 ERROR ("uptime plugin: kstat chain control structure not available.");
151 ksp = kstat_lookup (kc, "unix", 0, "system_misc");
154 ERROR ("uptime plugin: Cannot find unix:0:system_misc kstat.");
158 if (kstat_read (kc, ksp, NULL) < 0)
160 ERROR ("uptime plugin: kstat_read failed.");
164 knp = (kstat_named_t *) kstat_data_lookup (ksp, "boot_time");
167 ERROR ("uptime plugin: kstat_data_lookup (boot_time) failed.");
171 boottime = (time_t) knp->value.ui32;
175 ERROR ("uptime plugin: kstat_data_lookup returned success, "
176 "but `boottime' is zero!");
179 /* #endif HAVE_LIBKSTAT */
181 # elif HAVE_SYS_SYSCTL_H
182 struct timeval boottv;
189 mib[1] = KERN_BOOTTIME;
191 boottv_len = sizeof (boottv);
192 memset (&boottv, 0, boottv_len);
194 status = sysctl (mib, STATIC_ARRAY_SIZE (mib), &boottv, &boottv_len,
195 /* new_value = */ NULL, /* new_length = */ 0);
199 ERROR ("uptime plugin: No value read from sysctl interface: %s",
200 sstrerror (errno, errbuf, sizeof (errbuf)));
204 boottime = boottv.tv_sec;
208 ERROR ("uptime plugin: sysctl(3) returned success, "
209 "but `boottime' is zero!");
212 /* #endif HAVE_SYS_SYSCTL_H */
216 perfstat_cpu_total_t cputotal;
219 status = perfstat_cpu_total(NULL, &cputotal,
220 sizeof(perfstat_cpu_total_t), 1);
224 ERROR ("uptime plugin: perfstat_cpu_total: %s",
225 sstrerror (errno, errbuf, sizeof (errbuf)));
229 hertz = sysconf(_SC_CLK_TCK);
233 boottime = time(NULL) - cputotal.lbolt / hertz;
234 #endif /* HAVE_PERFSTAT */
237 } /* }}} int uptime_init */
239 static int uptime_read (void)
244 /* calculate the amount of time elapsed since boot, AKA uptime */
245 elapsed = time (NULL) - boottime;
247 uptime = (gauge_t) elapsed;
249 uptime_submit (uptime);
254 void module_register (void)
256 plugin_register_init ("uptime", uptime_init);
257 plugin_register_read ("uptime", uptime_read);
258 } /* void module_register */