📄 libmetrics.c
字号:
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <time.h>#include <unistd.h>#include <ctype.h>#include <sys/sysinfo.h>/*add by zyl 20060904*/#include <net/if.h>#include <sys/socket.h>#include <errno.h>#include <fcntl.h>#include <sys/ioctl.h>#include <stdarg.h>#include <syslog.h>#include <libsens.h>#ifndef MAXLINE#define MAXLINE 4096#endifint daemon_proc; /* set nonzero by daemon_init() */int ganglia_quiet_errors = 0;static void err_doit (int, int, const char *, va_list);/* From old ganglia 2.5.x... */#include <sys/file.h>#include "libmetrics.h"//#include "fsusage.h"/* End old ganglia 2.5.x headers */#include "interface.h"#define OSNAME "Linux"#define OSNAME_LEN strlen(OSNAME)/* Never changes */#ifndef BUFFSIZE#define BUFFSIZE 8192#endifchar proc_cpuinfo[BUFFSIZE];char proc_sys_kernel_osrelease[BUFFSIZE];typedef struct { uint32_t last_read; uint32_t thresh; char *name; char buffer[BUFFSIZE];} timely_file;timely_file proc_stat = { 0, 15, "/proc/stat" };timely_file proc_loadavg = { 0, 15, "/proc/loadavg" };timely_file proc_meminfo = { 0, 30, "/proc/meminfo" };timely_file proc_net_dev = { 0, 30, "/proc/net/dev" };static void err_doit (int, int, const char *, va_list);voiderr_quiet( void ){ ganglia_quiet_errors = 1;}voiderr_verbose( void ){ ganglia_quiet_errors = 0;}/** * @fn void err_ret (const char *fmt, ...) * Print a message and return. Nonfatal error related to a system call. * @param fmt Format string the same as printf function * @param ... Arguments for the format string */voiderr_ret (const char *fmt, ...){ va_list ap; va_start (ap, fmt); err_doit (1, LOG_INFO, fmt, ap); va_end (ap); return;}/** * @fn void err_sys (const char *fmt, ...) * Print a message and terminate. * Fatal error related to a system call. * @param fmt Format string the same as printf function * @param ... Arguments for the format string */voiderr_sys (const char *fmt, ...){ va_list ap; va_start (ap, fmt); err_doit (1, LOG_ERR, fmt, ap); va_end (ap); exit (1);}/** * @fn void err_dump (const char *fmt, ...) * Print a message, dump core, and terminate. * Fatal error related to a system call. * @param fmt Format string the same as printf function * @param ... Arguments for the format string */voiderr_dump (const char *fmt, ...){ va_list ap; va_start (ap, fmt); err_doit (1, LOG_ERR, fmt, ap); va_end (ap); abort (); /* dump core and terminate */ exit (1); /* shouldn't get here */}/** * @fn void err_msg (const char *fmt, ...) * Print a message and return. Nonfatal error unrelated to a system call. * @param fmt Format string the same as printf function * @param ... Arguments for the format string */voiderr_msg (const char *fmt, ...){ va_list ap; va_start (ap, fmt); err_doit (0, LOG_INFO, fmt, ap); va_end (ap); return;}/** * @fn void err_quit (const char *fmt, ...) * Print a message and terminate. Fatal error unrelated to a system call. * @param fmt Format string the same as printf function * @param ... Arguments for the format string */voiderr_quit (const char *fmt, ...){ va_list ap; va_start (ap, fmt); err_doit (0, LOG_ERR, fmt, ap); va_end (ap); exit (1);}/* Print a message and return to caller. * Caller specifies "errnoflag" and "level". */static voiderr_doit (int errnoflag, int level, const char *fmt, va_list ap){ int errno_save, n; char buf[MAXLINE]; if(ganglia_quiet_errors) return; errno_save = errno; /* value caller might want printed */#ifdef HAVE_VSNPRINTF vsnprintf (buf, sizeof (buf), fmt, ap); /* this is safe */#else vsprintf (buf, fmt, ap); /* this is not safe */#endif n = strlen (buf); if (errnoflag) snprintf (buf + n, sizeof (buf) - n, ": %s", strerror (errno_save)); strcat (buf, "\n"); if (daemon_proc) { syslog (level, buf); } else { fflush (stdout); /* in case stdout and stderr are the same */ fputs (buf, stderr); fflush (stderr); } return;}int debug_level = 0;/** * @fn void debug_msg(const char *format, ...) * Prints the message to STDERR if DEBUG is #defined * @param format The format of the msg (see printf manpage) * @param ... Optional arguments */voiddebug_msg(const char *format, ...){ if (debug_level > 1 && format) { va_list ap; va_start(ap, format); vfprintf(stderr, format, ap); fprintf(stderr,"\n"); va_end(ap); } return;}char *skip_whitespace ( const char *p){ while (isspace(*p)) p++; return (char *)p;}char *skip_token ( const char *p){ while (isspace(*p)) p++; while (*p && !isspace(*p)) p++; return (char *)p;}/*** @fn int slurpfile ( char * filename, char *buffer, int buflen )* Reads an entire file into a buffer* @param filename The name of the file to read into memory* @param buffer A pointer to the data buffer* @param buflen The data buffer length* @return int* @retval 0 on success* @retval -1 on failure*/int slurpfile ( char * filename, char *buffer, int buflen ){ int fd, read_len; fd = open(filename, O_RDONLY); if ( fd < 0 ) { err_ret("slurpfile() open() error"); return SYNAPSE_FAILURE; } read: read_len = read( fd, buffer, buflen ); if ( read_len <= 0 ) { if ( errno == EINTR ) goto read; err_ret("slurpfile() read() error"); close(fd); return SYNAPSE_FAILURE; } close(fd); buffer[read_len] = '\0'; return read_len;}char *update_file(timely_file *tf){ int now,rval; now = time(0); if(now - tf->last_read > tf->thresh) { rval = slurpfile(tf->name, tf->buffer, BUFFSIZE); if(rval == SYNAPSE_FAILURE) { err_msg("update_file() got an error from slurpfile() reading %s", tf->name); return (char *)SYNAPSE_FAILURE; } else tf->last_read = now; } return tf->buffer;}/*** A helper function to determine the number of cpustates in /proc/stat (MKN)*/#define NUM_CPUSTATES_24X 4#define NUM_CPUSTATES_26X 7static unsigned int num_cpustates;unsigned intnum_cpustates_func ( void ){ char *p; unsigned int i=0; proc_stat.last_read=0; p = update_file(&proc_stat); proc_stat.last_read=0;/*** Skip initial "cpu" token*/ p = skip_token(p); p = skip_whitespace(p);/*** Loop over file until next "cpu" token is found.** i=4 : Linux 2.4.x** i=7 : Linux 2.6.x*/ while (strncmp(p,"cpu",3)) { p = skip_token(p); p = skip_whitespace(p); i++; } return i;}/* * This function is called only once by the gmond. Use to * initialize data structures, etc or just return SYNAPSE_SUCCESS; */g_val_tmetric_init(void){ g_val_t rval; char * dummy; num_cpustates = num_cpustates_func(); rval.int32 = slurpfile("/proc/cpuinfo", proc_cpuinfo, BUFFSIZE); if ( rval.int32 == SYNAPSE_FAILURE ) { err_msg("metric_init() got an error from slurpfile() /proc/cpuinfo"); return rval; } rval.int32 = slurpfile( "/proc/sys/kernel/osrelease", proc_sys_kernel_osrelease, BUFFSIZE); if ( rval.int32 == SYNAPSE_FAILURE ) { err_msg("metric_init() got an error from slurpfile()"); return rval; } /* Get rid of pesky \n in osrelease */ proc_sys_kernel_osrelease[rval.int32-1] = '\0'; dummy = update_file(&proc_net_dev); if ( dummy == (char *)SYNAPSE_FAILURE ) { err_msg("metric_init() got an error from update_file()"); rval.int32 = SYNAPSE_FAILURE; return rval; } rval.int32 = SYNAPSE_SUCCESS; return rval;}g_val_tpkts_in_func ( void ){ char *p; register int i; static g_val_t val; int size; static int stamp; static double last_bytes_in, last_bytes_out, last_pkts_in, last_pkts_out; double bytes_in=0, bytes_out=0, pkts_in=0, pkts_out=0, t = 0; double diff; p = update_file(&proc_net_dev); if (proc_net_dev.last_read != stamp) { size = ( index (p, 0x00) ) - p; /* skip past the two-line header ... */ p = index (p, '\n')+1; p = index (p, '\n')+1; while (*p != 0x00 ) { p = index(p, ':')+1; /* skip past the interface tag portion of this line */ if ( (*(p-2) != 'o') && (*(p-3) != 'l') ) { t = strtod( p, &p ); bytes_in += t; t = strtod( p, &p ); pkts_in += t; for (i = 0; i < 6; i++) strtol(p, &p, 10); t = strtod( p, &p ); bytes_out += t; pkts_out += strtod( p, &p ); } p = index (p, '\n') + 1; // skips a line } diff = pkts_in - last_pkts_in; val.f = 0.; if ( diff >= 1. ) { t = proc_net_dev.last_read - stamp; val.f = diff / t; } last_bytes_in = bytes_in; last_pkts_in = pkts_in; last_pkts_out = pkts_out; last_bytes_out = bytes_out; stamp = proc_net_dev.last_read; } debug_msg(" ********** PKTS_IN RETURN: %f", val.f); return val;}g_val_tpkts_out_func ( void ){ char *p; register int i; static g_val_t val; int size; static int stamp; static double last_bytes_in, last_bytes_out, last_pkts_in, last_pkts_out; double bytes_in=0, bytes_out=0, pkts_in=0, pkts_out=0, t = 0; double diff; p = update_file(&proc_net_dev); if (proc_net_dev.last_read != stamp) { size = ( index (p, 0x00) ) - p; /* skip past the two-line header ... */ p = index (p, '\n')+1; p = index (p, '\n')+1; while (*p != 0x00 ) { p = index(p, ':')+1; /* skip past the interface tag portion of this line */ if ( (*(p-2) != 'o') && (*(p-3) != 'l') ) { t = strtod( p, &p ); bytes_in += t; t = strtod( p, &p ); pkts_in += t; for (i = 0; i < 6; i++) strtol(p, &p, 10); t = strtod( p, &p ); bytes_out += t; pkts_out += strtod( p, &p ); } p = index (p, '\n') + 1; // skips a line } diff = pkts_out - last_pkts_out; val.f = 0.; if ( diff >= 1. ) { t = proc_net_dev.last_read - stamp; val.f = diff / t; } last_bytes_in = bytes_in; last_pkts_in = pkts_in; last_pkts_out = pkts_out; last_bytes_out = bytes_out; stamp = proc_net_dev.last_read; } debug_msg(" ********** PKTS_OUT RETURN: %f", val.f); return val;}g_val_tbytes_out_func ( void ){ char *p; register int i; static g_val_t val; int size; static int stamp; static double last_bytes_in, last_bytes_out, last_pkts_in, last_pkts_out; double bytes_in=0, bytes_out=0, pkts_in=0, pkts_out=0, t = 0; double diff; p = update_file(&proc_net_dev); if (proc_net_dev.last_read != stamp) { size = ( index (p, 0x00) ) - p; /* skip past the two-line header ... */ p = index (p, '\n')+1; p = index (p, '\n')+1; while (*p != 0x00 ) { p = index(p, ':')+1; /* skip past the interface tag portion of this line */ if ( (*(p-2) != 'o') && (*(p-3) != 'l') ) { t = strtod( p, &p ); bytes_in += t; t = strtod( p, &p ); pkts_in += t; for (i = 0; i < 6; i++) strtol(p, &p, 10); /* Fixed 2003 by Dr Michael Wirtz <m.wirtz@tinnit.de> and Phil Radden <P.Radden@rl.ac.uk> */ t = strtod( p, &p ); bytes_out += t; pkts_out += strtod( p, &p ); } p = index (p, '\n') + 1; // skips a line } diff = bytes_out - last_bytes_out; val.f = 0.; if ( diff >= 1. ) { t = proc_net_dev.last_read - stamp; val.f = diff / t; } last_bytes_in = bytes_in; last_pkts_in = pkts_in; last_pkts_out = pkts_out; last_bytes_out = bytes_out; stamp = proc_net_dev.last_read; } debug_msg(" ********** BYTES_OUT RETURN: %f", val.f); return val;}g_val_tbytes_in_func ( void ){ char *p; register int i; static g_val_t val; int size; static int stamp; static double last_bytes_in, last_bytes_out, last_pkts_in, last_pkts_out; double bytes_in=0, bytes_out=0, pkts_in=0, pkts_out=0, t = 0; double diff; p = update_file(&proc_net_dev); if (proc_net_dev.last_read != stamp) { size = ( index (p, 0x00) ) - p; /* skip past the two-line header ... */ p = index (p, '\n')+1; p = index (p, '\n')+1; while (*p != 0x00 ) { p = index(p, ':')+1; /* skip past the interface tag portion of this line */ debug_msg(" Last two chars: %c%c\n", *p-2, *p-1 ); if ( (*(p-2) != 'o') && (*(p-3) != 'l') ) { debug_msg(" Last two chars: %c%c\n", *p-2, *p-1 ); t = strtod( p, &p ); bytes_in += t; t = strtod( p, &p ); pkts_in += t; for (i = 0; i < 6; i++) strtol(p, &p, 10); /* Fixed 2003 by Dr Michael Wirtz <m.wirtz@tinnit.de> and Phil Radden <P.Radden@rl.ac.uk>. */ t = strtod( p, &p ); bytes_out += t; pkts_out += strtod( p, &p ); } p = index (p, '\n') + 1; // skips a line } diff = bytes_in - last_bytes_in; val.f = 0.; if ( diff >= 1. ) { t = proc_net_dev.last_read - stamp;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -