From f8b596a3e11e7afe2b69e72008d8e1de5d9fbc64 Mon Sep 17 00:00:00 2001 From: Edward Koko Konetzko Date: Wed, 29 Apr 2009 22:26:52 -0500 Subject: [PATCH] fscache plugin: Add new plugin for Linux' file-system based caching framework. Tried to submit the patch via "git send-mail" but I don't think it worked if you already have the patch disregard the attachment. Looking forward to your feedback, I am sure there are a few issues its been a few years since I programmed in C. I have been running this in my test lab at work for a few days now with no issues. With 62 metrics I would like to modify the code to group them by their classification and possibly add configuration support. If the changes are finished this weekend is it ok to send an updated patch? Thanks Edward Signed-off-by: Edward "Koko" Konetzko Signed-off-by: Florian Forster --- configure.in | 4 + src/Makefile.am | 8 ++ src/fscache.c | 225 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/types.db | 1 + 4 files changed, 238 insertions(+) create mode 100644 src/fscache.c diff --git a/configure.in b/configure.in index c585390e..1f5a2224 100644 --- a/configure.in +++ b/configure.in @@ -3172,6 +3172,7 @@ plugin_load="no" plugin_memory="no" plugin_multimeter="no" plugin_nfs="no" +plugin_fscache="no" plugin_perl="no" plugin_processes="no" plugin_protocols="no" @@ -3201,6 +3202,7 @@ then plugin_load="yes" plugin_memory="yes" plugin_nfs="yes" + plugin_fscache="yes" plugin_processes="yes" plugin_protocols="yes" plugin_serial="yes" @@ -3411,6 +3413,7 @@ AC_PLUGIN([mysql], [$with_libmysql], [MySQL statistics]) AC_PLUGIN([netlink], [$with_libnetlink], [Enhanced Linux network statistics]) AC_PLUGIN([network], [yes], [Network communication plugin]) AC_PLUGIN([nfs], [$plugin_nfs], [NFS statistics]) +AC_PLUGIN([fscache], [$plugin_fscache], [fscache statistics]) AC_PLUGIN([nginx], [$with_libcurl], [nginx statistics]) AC_PLUGIN([notify_desktop], [$with_libnotify], [Desktop notifications]) AC_PLUGIN([notify_email], [$with_libesmtp], [Email notifier]) @@ -3694,6 +3697,7 @@ Configuration: netlink . . . . . . . $enable_netlink network . . . . . . . $enable_network nfs . . . . . . . . . $enable_nfs + fscache . . . . . . . $enable_fscache nginx . . . . . . . . $enable_nginx notify_desktop . . . $enable_notify_desktop notify_email . . . . $enable_notify_email diff --git a/src/Makefile.am b/src/Makefile.am index c1cc9df4..48967365 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -576,6 +576,14 @@ collectd_LDADD += "-dlopen" nfs.la collectd_DEPENDENCIES += nfs.la endif +if BUILD_PLUGIN_FSCACHE +pkglib_LTLIBRARIES += fscache.la +fscache_la_SOURCES = fscache.c +fscache_la_LDFLAGS = -module -avoid-version +collectd_LDADD += "-dlopen" fscache.la +collectd_DEPENDENCIES += fscache.la +endif + if BUILD_PLUGIN_NGINX pkglib_LTLIBRARIES += nginx.la nginx_la_SOURCES = nginx.c diff --git a/src/fscache.c b/src/fscache.c new file mode 100644 index 00000000..5ae980a6 --- /dev/null +++ b/src/fscache.c @@ -0,0 +1,225 @@ +/** + * collectd - src/fscache.c + * Copyright (C) 2009 Edward "Koko" Konetzko + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; only version 2 of the License is applicable. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Authors: + * Edward "Koko" Konetzko + **/ + +#include "collectd.h" +#include "common.h" +#include "plugin.h" +#include /* a header needed for FILE */ +#include /* a header needed for scanf function */ +#include /* used for atoi */ + + +#if !KERNEL_LINUX +# error "This module only supports the Linux implementation of fscache" +#endif + +#define BUFSIZE 1024 + +/* +see /proc/fs/fscache/stats +see Documentation/filesystems/caching/fscache.txt in linux kernel >= 2.6.30 + +This shows counts of a number of events that can happen in FS-Cache: + +CLASS EVENT MEANING +======= ======= ======================================================= +Cookies idx=N Number of index cookies allocated + dat=N Number of data storage cookies allocated + spc=N Number of special cookies allocated +Objects alc=N Number of objects allocated + nal=N Number of object allocation failures + avl=N Number of objects that reached the available state + ded=N Number of objects that reached the dead state +ChkAux non=N Number of objects that didn't have a coherency check + ok=N Number of objects that passed a coherency check + upd=N Number of objects that needed a coherency data update + obs=N Number of objects that were declared obsolete +Pages mrk=N Number of pages marked as being cached + unc=N Number of uncache page requests seen +Acquire n=N Number of acquire cookie requests seen + nul=N Number of acq reqs given a NULL parent + noc=N Number of acq reqs rejected due to no cache available + ok=N Number of acq reqs succeeded + nbf=N Number of acq reqs rejected due to error + oom=N Number of acq reqs failed on ENOMEM +Lookups n=N Number of lookup calls made on cache backends + neg=N Number of negative lookups made + pos=N Number of positive lookups made + crt=N Number of objects created by lookup +Updates n=N Number of update cookie requests seen + nul=N Number of upd reqs given a NULL parent + run=N Number of upd reqs granted CPU time +Relinqs n=N Number of relinquish cookie requests seen + nul=N Number of rlq reqs given a NULL parent + wcr=N Number of rlq reqs waited on completion of creation +AttrChg n=N Number of attribute changed requests seen + ok=N Number of attr changed requests queued + nbf=N Number of attr changed rejected -ENOBUFS + oom=N Number of attr changed failed -ENOMEM + run=N Number of attr changed ops given CPU time +Allocs n=N Number of allocation requests seen + ok=N Number of successful alloc reqs + wt=N Number of alloc reqs that waited on lookup completion + nbf=N Number of alloc reqs rejected -ENOBUFS + ops=N Number of alloc reqs submitted + owt=N Number of alloc reqs waited for CPU time +Retrvls n=N Number of retrieval (read) requests seen + ok=N Number of successful retr reqs + wt=N Number of retr reqs that waited on lookup completion + nod=N Number of retr reqs returned -ENODATA + nbf=N Number of retr reqs rejected -ENOBUFS + int=N Number of retr reqs aborted -ERESTARTSYS + oom=N Number of retr reqs failed -ENOMEM + ops=N Number of retr reqs submitted + owt=N Number of retr reqs waited for CPU time +Stores n=N Number of storage (write) requests seen + ok=N Number of successful store reqs + agn=N Number of store reqs on a page already pending storage + nbf=N Number of store reqs rejected -ENOBUFS + oom=N Number of store reqs failed -ENOMEM + ops=N Number of store reqs submitted + run=N Number of store reqs granted CPU time +Ops pend=N Number of times async ops added to pending queues + run=N Number of times async ops given CPU time + enq=N Number of times async ops queued for processing + dfr=N Number of async ops queued for deferred release + rel=N Number of async ops released + gc=N Number of deferred-release async ops garbage collected + +63 events to collect in 13 groups +*/ + +static int fscache_number_of_values = 62; + +struct fscache_values { + char name[20]; + unsigned long long value; +}; /*end struct fscache_values */ + +static void fscache_submit(struct fscache_values submit_values[]){ +/*submit logic goes here!!!!!*/ + + value_t values[1]; + value_list_t vl = VALUE_LIST_INIT; + int i; + + vl.values = values; + vl.values_len = 1; + sstrncpy(vl.host, hostname_g, sizeof(vl.host)); + sstrncpy(vl.plugin, "fscache", sizeof(vl.plugin)); + sstrncpy(vl.plugin_instance, "fscache", + sizeof(vl.plugin_instance)); + sstrncpy(vl.type, "fscache_stat", sizeof(vl.type)); + + for (i = 0; i < fscache_number_of_values; i++){ + values[0].counter = submit_values[i].value; + sstrncpy(vl.type_instance, submit_values[i].name, + sizeof(vl.type_instance)); + DEBUG("%s-%s/fscache-%s = %llu", + vl.plugin, vl.plugin_instance, + vl.type_instance, submit_values[i].value); + plugin_dispatch_values(&vl); + } +} + +static void fscache_read_stats_file(FILE *fh){ + int forcount = 0; + int count = 0; + int start = 0; + int numfields = 0; + int valuecounter = 0; + char filebuffer[BUFSIZE]; + char valuebuffer[BUFSIZE]; + char valuename[BUFSIZE]; + char valuevalue[BUFSIZE]; + char sectionbuffer[BUFSIZE]; + char tempstring[BUFSIZE]; + char *ptrfilebuffer = filebuffer; + char *position = NULL; + char *fields[fscache_number_of_values]; + struct fscache_values values[fscache_number_of_values]; + + /* Read file line by line */ + while( fgets( filebuffer, BUFSIZE, fh)!= NULL){ + /*skip first line and split file on : */ + if (count != 0){ + position = strchr(filebuffer,':'); + start = strlen(filebuffer) - 1; + filebuffer[start] = '\0'; + /* : is located at value 8, +1 to remove space */ + strncpy(valuebuffer, ptrfilebuffer+9, start); + /*store section info for later */ + strncpy(sectionbuffer, ptrfilebuffer, position - filebuffer); + position = strchr(sectionbuffer, ' '); + if (position != NULL){ + sectionbuffer[position-sectionbuffer] = '\0'; + } + + /*split rest of line by space and then split that via =*/ + numfields = strsplit ( valuebuffer, fields, + fscache_number_of_values); + for( forcount = 0; forcount < numfields; forcount++ ){ + char *field = fields[forcount]; + memset(valuename,'\0',sizeof(valuename)); + position = strchr(field, '='); + /* Test to see if we actually have a metric to split on + * and assign the values to the struct array */ + if (position != NULL){ + strncpy(valuename, field, position - field); + strncpy(valuevalue, field + (position - field + 1), + strlen(field)); + memset(tempstring,'\0',sizeof(tempstring)); + strncat(tempstring,sectionbuffer,sizeof(tempstring)); + strncat(tempstring,"_",1); + strncat(tempstring,valuename, sizeof(tempstring)); + memset(values[valuecounter].name,'\0', + sizeof(values[valuecounter].name)); + strncpy(values[valuecounter].name,tempstring, + sizeof(values[valuecounter].name)); + values[valuecounter].value = atoll(valuevalue); + } + valuecounter++; + } + } + count++; + } + fscache_submit(values); +} + +static int fscache_read (void){ + FILE *fh; + fh = fopen("/proc/fs/fscache/stats", "r"); + if (fh != NULL){ + fscache_read_stats_file(fh); + fclose(fh); + + }else{ + printf("cant open file\n"); + return (-1); + } + return (0); +} + +void module_register (void) +{ + plugin_register_read ("fscache", fscache_read); +} /* void module_register */ + diff --git a/src/types.db b/src/types.db index f8b2f81f..a92153ca 100644 --- a/src/types.db +++ b/src/types.db @@ -76,6 +76,7 @@ mysql_octets rx:COUNTER:0:4294967295, tx:COUNTER:0:4294967295 mysql_qcache hits:COUNTER:0:U, inserts:COUNTER:0:U, not_cached:COUNTER:0:U, lowmem_prunes:COUNTER:0:U, queries_in_cache:GAUGE:0:U mysql_threads running:GAUGE:0:U, connected:GAUGE:0:U, cached:GAUGE:0:U, created:COUNTER:0:U nfs_procedure value:COUNTER:0:4294967295 +fscache_stat value:COUNTER:0:4294967295 nginx_connections value:GAUGE:0:U nginx_requests value:COUNTER:0:134217728 operations value:COUNTER:0:4294967295 -- 2.11.0