#include <u.h>
#include <libc.h>
#include <bio.h>
#include <thread.h>
#include "collectd.h"
typedef struct Avg Avg;
struct Avg {
ulong size;
double *next;
double values[];
};
static Avg *
mkavg(ulong size)
{
Avg *avg;
avg = emalloc(sizeof *avg + sizeof(double)*size);
avg->size = size;
avg->next = &avg->values[0];
return avg;
}
static void
avgadd(Avg *avg, double value)
{
double *e;
e = avg->values + avg->size;
if(avg->next == e)
avg->next = &avg->values[0];
*avg->next++ = value;
}
static double
avgcalc(Avg *avg)
{
double *p, *e;
double sum;
sum = 0;
p = avg->values;
e = p + avg->size;
while(p < e)
sum += *p++;
return sum / avg->size;
}
static void
submit(Channel *c, double s, double m, double l)
{
Packet *pp;
pp = palloc();
pp->host = estrdup(hostname);
pp->interval = interval;
pp->time = time(nil);
pp->plugin = estrdup("load");
pp->type = estrdup("load");
addgauge(pp, s);
addgauge(pp, m);
addgauge(pp, l);
if(nbsendp(c, pp) < 1)
pfree(pp);
}
static Avg *load[3]; /* short, medium, long */
void
loadproc(void *arg)
{
Channel *c;
Biobuf *bp;
Sysstat sysstat;
double value;
int i;
/*
* Collectd expects Unix-like load averages; we collect
* rolling averages for 1, 5, and 15 minute intervals.
*/
load[0] = mkavg(60 / interval);
load[1] = mkavg(5*60 / interval);
load[2] = mkavg(15*60 / interval);
c = arg;
for(;;){
snooze();
/*
* Load average is only reported in the first
* sysstat entry. To avoid leaking resources, we
* flush and close the buffer immediately rather
* than read remaining lines.
*/
bp = readsysstat(nil, "/dev/sysstat", &sysstat);
Bterm(bp);
value = (double)sysstat.load / 1000;
for(i = 0; i < nelem(load); ++i)
avgadd(load[i], value);
submit(c, avgcalc(load[0]), avgcalc(load[1]), avgcalc(load[2]));
}
}
|