#include <u.h>
#include <libc.h>
#include <bio.h>
#include <thread.h>
#include "collectd.h"
#define MAXCPU 32
Biobuf *
readsysstat(Biobuf *bp, char *file, Sysstat *sysstat)
{
char *p, *f[10];
int nf;
if(bp == nil){
bp = Bopen(file, OREAD);
if(bp == nil)
sysfatal("couldn't open %s: %r", file);
}
p = Brdline(bp, '\n');
if(p == nil){
Bterm(bp);
return nil;
}
p[Blinelen(bp)-1] = '\0';
nf = tokenize(p, f, nelem(f));
if(nf < nelem(f))
sysfatal("unexpected sysstat output");
sysstat->id = strtoul(f[0], nil, 0);
sysstat->cs = strtoul(f[1], nil, 0);
sysstat->intr = strtoul(f[2], nil, 0);
sysstat->syscall = strtoul(f[3], nil, 0);
sysstat->pfault = strtoul(f[4], nil, 0);
sysstat->tlbfault = strtoul(f[5], nil, 0);
sysstat->tlbpurge = strtoul(f[6], nil, 0);
sysstat->load = strtoul(f[7], nil, 0);
sysstat->idlepct = strtoul(f[8], nil, 0);
sysstat->intrpct = strtoul(f[9], nil, 0);
return bp;
}
static void
submit(Channel *c, ulong id, char *type, uvlong value)
{
Packet *pp;
pp = palloc();
pp->host = estrdup(hostname);
pp->interval = interval;
pp->time = time(nil);
pp->plugin = estrdup("cpu");
pp->pinst = smprint("%uld", id);
#ifdef USE_JIFFIES
pp->type = estrdup("cpu");
#else
pp->type = estrdup("percent");
#endif
pp->tinst = estrdup(type);
addcounter(pp, value);
if(nbsendp(c, pp) < 1)
pfree(pp);
}
static uvlong counter[MAXCPU][3]; /* idle, interrupt, user */
void
cpuproc(void *arg)
{
Channel *c;
Biobuf *bp;
Sysstat sysstat;
ulong userpct;
c = arg;
bp = nil;
for(;;){
snooze();
while(bp = readsysstat(bp, "/dev/sysstat", &sysstat)){
/*
* Unfortunately, syscall usage is not exposed
* via sysstat, so we are unable to distinguish
* between system and user. Rather than report
* nothing, we submit the remainder as user.
*/
userpct = 100 - sysstat.idlepct - sysstat.intrpct;
#ifdef USE_JIFFIES
/*
* Older versions of collectd expect that cpu
* usage is reported in terms of "jiffies".
* We simulate this nonsense by incrementing
* each counter with usage multiplied by the
* interval to match expectations.
*/
counter[sysstat.id][0] += sysstat.idlepct*interval;
submit(c, sysstat.id, "idle", counter[sysstat.id][0]);
counter[sysstat.id][1] += sysstat.intrpct*interval;
submit(c, sysstat.id, "interrupt", counter[sysstat.id][1]);
counter[sysstat.id][2] += userpct*interval;
submit(c, sysstat.id, "user", counter[sysstat.id][2]);
#else
submit(c, sysstat.id, "idle", sysstat.idlepct);
submit(c, sysstat.id, "interrupt", sysstat.intrpct);
submit(c, sysstat.id, "user", userpct);
#endif
}
}
}
|