[collectd] nfs client stats
Jason Pepas
cell at ices.utexas.edu
Wed Nov 2 15:53:47 CET 2005
I realized I never actually fleshed out the rest of the long-assed
"%u:%llu:%llu..." lines. Corrected.
I also decided to be less verbose in the skip/fetch lines chunks of
code. The comments are sufficient to avoid confusion.
-jason pepas
-------------- next part --------------
#include "nfs.h"
#if COLLECT_NFS
#define MODULE_NAME "nfs"
#include "plugin.h"
#include "common.h"
static char *nfs_net_file = "nfs_net.rrd";
static char *nfs_rpc_file = "nfs_rpc.rrd";
static char *nfs_v2_file = "nfs_v2.rrd";
static char *nfs_v3_file = "nfs_v3.rrd";
/*
see /proc/net/rpc/nfs
see http://www.missioncriticallinux.com/orph/NFS-Statistics
net x x x x
rpc_stat.netcnt Not used; always zero.
rpc_stat.netudpcnt Not used; always zero.
rpc_stat.nettcpcnt Not used; always zero.
rpc_stat.nettcpconn Not used; always zero.
rpc x x x
rpc_stat.rpccnt The number of RPC calls.
rpc_stat.rpcretrans The number of retransmitted RPC calls.
rpc_stat.rpcauthrefresh The number of credential refreshes.
proc2 x x x...
proc3 x x x...
Procedure NFS Version NFS Version 3
Number Procedures Procedures
0 null null
1 getattr getattr
2 setattr setattr
3 root lookup
4 lookup access
5 readlink readlink
6 read read
7 wrcache write
8 write create
9 create mkdir
10 remove symlink
11 rename mknod
12 link remove
13 symlink rmdir
14 mkdir rename
15 rmdir link
16 readdir readdir
17 fsstat readdirplus
18 fsstat
19 fsinfo
20 pathconf
21 commit
*/
typedef struct nfs_net_stats
{
unsigned long long netcnt;
unsigned long long netudpcnt;
unsigned long long nettcpcnt;
unsigned long long nettcpcon;
} nfs_net_stats_t;
typedef struct nfs_rpc_stats
{
unsigned long long rpccnt;
unsigned long long rpcretrans;
unsigned long long rpcauthrefresh;
} nfs_rpc_stats_t;
typedef struct nfs_v2_stats
{
unsigned long long v2null;
unsigned long long v2getattr;
unsigned long long v2setattr;
unsigned long long v2root;
unsigned long long v2lookup;
unsigned long long v2readlink;
unsigned long long v2read;
unsigned long long v2wrcache;
unsigned long long v2write;
unsigned long long v2create;
unsigned long long v2remove;
unsigned long long v2rename;
unsigned long long v2link;
unsigned long long v2symlink;
unsigned long long v2mkdir;
unsigned long long v2rmdir;
unsigned long long v2readdir;
unsigned long long v2fsstat;
} nfs_v2_stats_t;
typedef struct nfs_v3_stats
{
unsigned long long v3null;
unsigned long long v3getattr;
unsigned long long v3setattr;
unsigned long long v3lookup;
unsigned long long v3access;
unsigned long long v3readlink;
unsigned long long v3read;
unsigned long long v3write;
unsigned long long v3create;
unsigned long long v3mkdir;
unsigned long long v3symlink;
unsigned long long v3mknod;
unsigned long long v3remove;
unsigned long long v3rmdir;
unsigned long long v3rename;
unsigned long long v3link;
unsigned long long v3readdir;
unsigned long long v3readdirplus;
unsigned long long v3fsstat;
unsigned long long v3fsinfo;
unsigned long long v3pathconf;
unsigned long long v3commit;
} nfs_v3_stats_t;
static char *nfs_net_ds_def[] =
{
"DS:netcnt:COUNTER:25:0:U",
"DS:netudpcnt:COUNTER:25:0:U",
"DS:nettcpcnt:COUNTER:25:0:U",
"DS:nettcpcon:COUNTER:25:0:U", // should be gauge?
NULL
};
static int nfs_net_ds_num = 4;
static char *nfs_rpc_ds_def[] =
{
"DS:rpccnt:COUNTER:25:0:U",
"DS:rpcretrans:COUNTER:25:0:U",
"DS:rpcauthrefresh:COUNTER:25:0:U",
NULL
};
static int nfs_rpc_ds_num = 3;
static char *nfs_v2_ds_def[] =
{
"DS:v2getattr:COUNTER:25:0:U",
"DS:v2setattr:COUNTER:25:0:U",
"DS:v2root:COUNTER:25:0:U",
"DS:v2lookup:COUNTER:25:0:U",
"DS:v2readlink:COUNTER:25:0:U",
"DS:v2read:COUNTER:25:0:U",
"DS:v2wrcache:COUNTER:25:0:U",
"DS:v2write:COUNTER:25:0:U",
"DS:v2create:COUNTER:25:0:U",
"DS:v2remove:COUNTER:25:0:U",
"DS:v2rename:COUNTER:25:0:U",
"DS:v2link:COUNTER:25:0:U",
"DS:v2symlink:COUNTER:25:0:U",
"DS:v2mkdir:COUNTER:25:0:U",
"DS:v2rmdir:COUNTER:25:0:U",
"DS:v2readdir:COUNTER:25:0:U",
"DS:v2fsstat:COUNTER:25:0:U",
NULL
};
static int nfs_v2_ds_num = 17;
static char *nfs_v3_ds_def[] =
{
"DS:v3getattr:COUNTER:25:0:U",
"DS:v3setattr:COUNTER:25:0:U",
"DS:v3lookup:COUNTER:25:0:U",
"DS:v3access:COUNTER:25:0:U",
"DS:v3readlink:COUNTER:25:0:U",
"DS:v3read:COUNTER:25:0:U",
"DS:v3write:COUNTER:25:0:U",
"DS:v3create:COUNTER:25:0:U",
"DS:v3mkdir:COUNTER:25:0:U",
"DS:v3symlink:COUNTER:25:0:U",
"DS:v3mknod:COUNTER:25:0:U",
"DS:v3remove:COUNTER:25:0:U",
"DS:v3rmdir:COUNTER:25:0:U",
"DS:v3rename:COUNTER:25:0:U",
"DS:v3link:COUNTER:25:0:U",
"DS:v2readdir:COUNTER:25:0:U",
"DS:v3readdirplus:COUNTER:25:0:U",
"DS:v3fsstat:COUNTER:25:0:U",
"DS:v3fsinfo:COUNTER:25:0:U",
"DS:v3pathconf:COUNTER:25:0:U",
"DS:v3commit:COUNTER:25:0:U",
NULL
};
static int nfs_v3_ds_num = 21;
extern time_t curtime;
void nfs_net_write (char *host, char *inst, char *val)
{
rrd_update_file (host, nfs_net_file, val, nfs_net_ds_def, nfs_net_ds_num);
}
void nfs_rpc_write (char *host, char *inst, char *val)
{
rrd_update_file (host, nfs_rpc_file, val, nfs_rpc_ds_def, nfs_rpc_ds_num);
}
void nfs_v2_write (char *host, char *inst, char *val)
{
rrd_update_file (host, nfs_v2_file, val, nfs_v2_ds_def, nfs_v2_ds_num);
}
void nfs_v3_write (char *host, char *inst, char *val)
{
rrd_update_file (host, nfs_v3_file, val, nfs_v3_ds_def, nfs_v3_ds_num);
}
#define BUFSIZE 1024
void nfs_net_submit(nfs_net_stats_t *net_stats)
{
char buf[BUFSIZE];
int retval = 0;
retval = snprintf(buf, BUFSIZE, "%u:%llu:%llu:%llu:%llu",
(unsigned int) curtime, net_stats->netcnt, net_stats->netudpcnt, net_stats->nettcpcnt, net_stats->nettcpcon);
if (retval < 0 || retval >= BUFSIZE)
{
syslog (LOG_ERR, "load: fgets: %s", strerror (errno));
return;
}
plugin_submit ("nfs_rpc", "-", buf);
}
#undef BUFSIZE
#define BUFSIZE 1024
void nfs_rpc_submit(nfs_rpc_stats_t *rpc_stats)
{
char buf[BUFSIZE];
int retval = 0;
retval = snprintf(buf, BUFSIZE, "%u:%llu:%llu:%llu",
(unsigned int) curtime, rpc_stats->rpccnt, rpc_stats->rpcretrans, rpc_stats->rpcauthrefresh);
if (retval < 0 || retval >= BUFSIZE)
{
syslog (LOG_ERR, "load: fgets: %s", strerror (errno));
return;
}
plugin_submit("nfs_rpc", "-", buf);
}
#undef BUFSIZE
#define BUFSIZE 1024
void nfs_v2_submit(nfs_v2_stats_t *v2_stats)
{
char buf[BUFSIZE];
int retval = 0;
retval = snprintf(buf, BUFSIZE, "%u:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu",
(unsigned int) curtime, v2_stats->v2null, v2_stats->v2getattr, v2_stats->v2setattr, v2_stats->v2root, v2_stats->v2lookup,
v2_stats->v2readlink, v2_stats->v2read, v2_stats->v2wrcache, v2_stats->v2write, v2_stats->v2create, v2_stats->v2remove, v2_stats->v2rename,
v2_stats->v2link, v2_stats->v2symlink, v2_stats->v2mkdir, v2_stats->v2rmdir, v2_stats->v2readdir, v2_stats->v2fsstat);
if (retval < 0 || retval >= BUFSIZE)
{
syslog (LOG_ERR, "load: fgets: %s", strerror (errno));
return;
}
plugin_submit ("nfs_v2", "-", buf);
}
#undef BUFSIZE
#define BUFSIZE 1024
void nfs_v3_submit(nfs_v3_stats_t *v3_stats)
{
char buf[BUFSIZE];
int retval = 0;
retval = snprintf(buf, BUFSIZE, "%u:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu",
(unsigned int) curtime, v3_stats->v3null, v3_stats->v3getattr, v3_stats->v3setattr, v3_stats->v3lookup, v3_stats->v3access,
v3_stats->v3readlink, v3_stats->v3read, v3_stats->v3write, v3_stats->v3create, v3_stats->v3mkdir, v3_stats->v3symlink, v3_stats->v3mknod, v3_stats->v3remove,
v3_stats->v3rmdir, v3_stats->v3rename, v3_stats->v3link, v3_stats->v3readdir, v3_stats->v3readdirplus, v3_stats->v3fsstat, v3_stats->v3fsinfo, v3_stats->v3pathconf, v3_stats->v3commit);
if (retval < 0 || retval >= BUFSIZE)
{
syslog (LOG_ERR, "load: fgets: %s", strerror (errno));
return;
}
plugin_submit("nfs_v3", "-", buf);
}
#undef BUFSIZE
#define BUFSIZE 512
void nfs_net_read (void)
{
FILE *fp;
char buffer[BUFSIZE];
nfs_net_stats_t net_stats;
fp = fopen("/proc/net/rpc/nfs", "r");
if (fp == NULL)
{
syslog (LOG_ERR, "load: fopen: %s", strerror(errno));
return;
}
// fetch line 1
if (fgets(buffer, BUFSIZE, fp) == NULL)
{
syslog (LOG_ERR, "load: fgets: %s", strerror (errno));
return;
}
// parse line 1: "net x x x x"
{
char *fields[5];
int numfields = 0;
numfields = strsplit(buffer, fields, 5);
if (numfields < 5)
{
syslog (LOG_ERR, "load: strsplit: error parsing line");
return;
}
// fields[0] is "net"
net_stats.netcnt = atoll(fields[1]);
net_stats.netudpcnt = atoll(fields[2]);
net_stats.nettcpcnt = atoll(fields[3]);
net_stats.nettcpcon = atoll(fields[4]);
}
if (fclose(fp) != 0)
syslog (LOG_WARNING, "load: fclose: %s", strerror (errno));
nfs_net_submit(&net_stats);
}
#undef BUFSIZE
#define BUFSIZE 512
void nfs_rpc_read (void)
{
FILE *fp;
char buffer[BUFSIZE];
nfs_rpc_stats_t rpc_stats;
fp = fopen("/proc/net/rpc/nfs", "r");
if (fp == NULL)
{
syslog (LOG_ERR, "load: fopen: %s", strerror(errno));
return;
}
// skip line 1, fetch line 2
if (fgets(buffer, BUFSIZE, fp) == NULL ||
fgets(buffer, BUFSIZE, fp) == NULL)
{
syslog (LOG_ERR, "load: fgets: %s", strerror (errno));
return;
}
// parse line 2: "rpc x x x"
{
char *fields[4];
int numfields = 0;
numfields = strsplit(buffer, fields, 4);
if (numfields < 4)
{
syslog (LOG_ERR, "load: strsplit: error parsing line");
return;
}
// fields[0] is "rpc"
rpc_stats.rpccnt = atoll(fields[1]);
rpc_stats.rpcretrans = atoll(fields[2]);
rpc_stats.rpcauthrefresh = atoll(fields[3]);
}
if (fclose(fp) != 0)
syslog (LOG_WARNING, "load: fclose: %s", strerror (errno));
nfs_rpc_submit(&rpc_stats);
}
#undef BUFSIZE
#define BUFSIZE 512
void nfs_v2_read (void)
{
FILE *fp;
char buffer[BUFSIZE];
nfs_v2_stats_t v2_stats;
fp = fopen("/proc/net/rpc/nfs", "r");
if (fp == NULL)
{
syslog (LOG_ERR, "load: fopen: %s", strerror(errno));
return;
}
// skip line 1 & 2, fetch line 3
if (fgets(buffer, BUFSIZE, fp) == NULL ||
fgets(buffer, BUFSIZE, fp) == NULL ||
fgets(buffer, BUFSIZE, fp) == NULL)
{
syslog (LOG_ERR, "load: fgets: %s", strerror (errno));
return;
}
// parse line 3: "proc2 x x x..."
{
char *fields[19];
int numfields = 0;
numfields = strsplit(buffer, fields, 19);
if (numfields < 19)
{
syslog (LOG_ERR, "load: strsplit: error parsing line");
return;
}
// fields[0] is "proc2"
// fields[1] is the number of interface procedures defined for protocol version 2
v2_stats.v2getattr = atoll(fields[2]);
v2_stats.v2setattr = atoll(fields[3]);
v2_stats.v2root = atoll(fields[4]);
v2_stats.v2lookup = atoll(fields[5]);
v2_stats.v2readlink = atoll(fields[6]);
v2_stats.v2read = atoll(fields[7]);
v2_stats.v2wrcache = atoll(fields[8]);
v2_stats.v2write = atoll(fields[9]);
v2_stats.v2create = atoll(fields[10]);
v2_stats.v2remove = atoll(fields[11]);
v2_stats.v2rename = atoll(fields[12]);
v2_stats.v2link = atoll(fields[13]);
v2_stats.v2symlink = atoll(fields[14]);
v2_stats.v2mkdir = atoll(fields[15]);
v2_stats.v2rmdir = atoll(fields[16]);
v2_stats.v2readdir = atoll(fields[17]);
v2_stats.v2fsstat = atoll(fields[18]);
}
if (fclose(fp) != 0)
syslog (LOG_WARNING, "load: fclose: %s", strerror (errno));
nfs_v2_submit(&v2_stats);
}
#undef BUFSIZE
#define BUFSIZE 512
void nfs_v3_read (void)
{
FILE *fp;
char buffer[BUFSIZE];
nfs_v3_stats_t v3_stats;
fp = fopen("/proc/net/rpc/nfs", "r");
if (fp == NULL)
{
syslog (LOG_ERR, "load: fopen: %s", strerror(errno));
return;
}
// skip line 1 - 3, fetch line 4
if (fgets(buffer, BUFSIZE, fp) == NULL ||
fgets(buffer, BUFSIZE, fp) == NULL ||
fgets(buffer, BUFSIZE, fp) == NULL ||
fgets(buffer, BUFSIZE, fp) == NULL)
{
syslog (LOG_ERR, "load: fgets: %s", strerror (errno));
return;
}
// parse line 4: "proc3 x x x..."
{
char *fields[23];
int numfields = 0;
numfields = strsplit(buffer, fields, 23);
if (numfields < 23)
{
syslog (LOG_ERR, "load: strsplit: error parsing line");
return;
}
// fields[0] is "proc3"
// fields[1] is the number of interface procedures defined for protocol version 3
v3_stats.v3getattr = atoll(fields[2]);
v3_stats.v3setattr = atoll(fields[3]);
v3_stats.v3lookup = atoll(fields[4]);
v3_stats.v3access = atoll(fields[5]);
v3_stats.v3readlink = atoll(fields[6]);
v3_stats.v3read = atoll(fields[7]);
v3_stats.v3write = atoll(fields[8]);
v3_stats.v3create = atoll(fields[9]);
v3_stats.v3mkdir = atoll(fields[10]);
v3_stats.v3symlink = atoll(fields[11]);
v3_stats.v3mknod = atoll(fields[12]);
v3_stats.v3remove = atoll(fields[13]);
v3_stats.v3rmdir = atoll(fields[14]);
v3_stats.v3rename = atoll(fields[15]);
v3_stats.v3link = atoll(fields[16]);
v3_stats.v3readdir = atoll(fields[17]);
v3_stats.v3readdirplus = atoll(fields[18]);
v3_stats.v3fsstat = atoll(fields[19]);
v3_stats.v3fsinfo = atoll(fields[20]);
v3_stats.v3pathconf = atoll(fields[21]);
v3_stats.v3commit = atoll(fields[22]);
}
if (fclose(fp) != 0)
syslog (LOG_WARNING, "load: fclose: %s", strerror (errno));
nfs_v3_submit(&v3_stats);
}
#undef BUFSIZE
void module_register (void)
{
plugin_register("nfs_net", NULL, nfs_net_read, nfs_net_write);
plugin_register("nfs_rpc", NULL, nfs_rpc_read, nfs_rpc_write);
plugin_register("nfs_v2", NULL, nfs_v2_read, nfs_v2_write);
plugin_register("nfs_v3", NULL, nfs_v3_read, nfs_v3_write);
}
#endif /* COLLECT_LOAD */
More information about the Collectd
mailing list