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 # error "No applicable input method."
47 /* boottime always used, no OS distinction */
48 static time_t boottime;
51 extern kstat_ctl_t *kc;
52 #endif /* #endif HAVE_LIBKSTAT */
55 static void uptime_submit (gauge_t uptime)
58 value_list_t vl = VALUE_LIST_INIT;
60 values[0].gauge = uptime;
65 sstrncpy (vl.host, hostname_g, sizeof (vl.host));
66 sstrncpy (vl.plugin, "uptime", sizeof (vl.plugin));
67 sstrncpy (vl.type, "uptime", sizeof (vl.type));
69 plugin_dispatch_values (&vl);
72 static int uptime_init (void)
76 On most unix systems the uptime is calculated by looking at the boot time
77 (stored in unix time, since epoch) and the current one. We are going to
78 do the same, reading the boot time value while executing the uptime_init
79 function (there is no need to read, every time the plugin_read is called,
80 a value that won't change). However, since uptime_init is run only once,
81 if the function fails in retrieving the boot time, the plugin is
82 unregistered and there is no chance to try again later. Nevertheless,
83 this is very unlikely to happen.
87 unsigned long starttime;
94 fh = fopen (STAT_FILE, "r");
99 ERROR ("uptime plugin: Cannot open "STAT_FILE": %s",
100 sstrerror (errno, errbuf, sizeof (errbuf)));
104 while (fgets (buffer, 1024, fh) != NULL)
106 /* look for the btime string and read the value */
107 if (( ret = sscanf(buffer, "btime %lu", &starttime) ) == 1 )
108 /* avoid further loops if btime has been found and read correctly (hopefully) */
115 /* loop done, check if no value has been found/read */
118 ERROR ("uptime plugin: No value read from "STAT_FILE"");
122 boottime = (time_t) starttime;
126 ERROR ("uptime plugin: btime read from "STAT_FILE", "
127 "but `boottime' is zero!");
130 /* #endif KERNEL_LINUX */
139 /* kstats chain already opened by update_kstat (using *kc), verify everything went fine. */
142 ERROR ("uptime plugin: kstat chain control structure not available.");
146 ksp = kstat_lookup (kc, "unix", 0, "system_misc");
149 ERROR ("uptime plugin: Cannot find unix:0:system_misc kstat.");
153 if (kstat_read (kc, ksp, NULL) < 0)
155 ERROR ("uptime plugin: kstat_read failed.");
159 knp = (kstat_named_t *) kstat_data_lookup (ksp, "boot_time");
162 ERROR ("uptime plugin: kstat_data_lookup (boot_time) failed.");
166 boottime = (time_t) knp->value.ui32;
170 ERROR ("uptime plugin: kstat_data_lookup returned success, "
171 "but `boottime' is zero!");
174 /* #endif HAVE_LIBKSTAT */
176 # elif HAVE_SYS_SYSCTL_H
177 struct timeval boottv;
184 mib[1] = KERN_BOOTTIME;
186 boottv_len = sizeof (boottv);
187 memset (&boottv, 0, boottv_len);
189 status = sysctl (mib, STATIC_ARRAY_SIZE (mib), &boottv, &boottv_len,
190 /* new_value = */ NULL, /* new_length = */ 0);
194 ERROR ("uptime plugin: No value read from sysctl interface: %s",
195 sstrerror (errno, errbuf, sizeof (errbuf)));
199 boottime = boottv.tv_sec;
203 ERROR ("uptime plugin: sysctl(3) returned success, "
204 "but `boottime' is zero!");
207 #endif /* HAVE_SYS_SYSCTL_H */
214 static int uptime_read (void)
219 /* calculate the ammount of time elapsed since boot, AKA uptime */
220 elapsed = time (NULL) - boottime;
222 uptime = (gauge_t) elapsed;
224 uptime_submit (uptime);
229 void module_register (void)
231 plugin_register_init ("uptime", uptime_init);
232 plugin_register_read ("uptime", uptime_read);
233 } /* void module_register */