diff options
author | Igor Pashev <pashev.igor@gmail.com> | 2014-10-26 12:33:50 +0400 |
---|---|---|
committer | Igor Pashev <pashev.igor@gmail.com> | 2014-10-26 12:33:50 +0400 |
commit | 47e6e7c84f008a53061e661f31ae96629bc694ef (patch) | |
tree | 648a07f3b5b9d67ce19b0fd72e8caa1175c98f1a /src/pmdas/apache | |
download | pcp-debian.tar.gz |
Debian 3.9.10debian/3.9.10debian
Diffstat (limited to 'src/pmdas/apache')
-rw-r--r-- | src/pmdas/apache/Apache.pmchart | 9 | ||||
-rw-r--r-- | src/pmdas/apache/GNUmakefile | 61 | ||||
-rwxr-xr-x | src/pmdas/apache/Install | 54 | ||||
-rw-r--r-- | src/pmdas/apache/README | 84 | ||||
-rw-r--r-- | src/pmdas/apache/Remove | 25 | ||||
-rw-r--r-- | src/pmdas/apache/apache.c | 538 | ||||
-rw-r--r-- | src/pmdas/apache/help | 91 | ||||
-rw-r--r-- | src/pmdas/apache/pmlogconf.processes | 14 | ||||
-rw-r--r-- | src/pmdas/apache/pmlogconf.summary | 10 | ||||
-rw-r--r-- | src/pmdas/apache/pmlogconf.uptime | 6 | ||||
-rw-r--r-- | src/pmdas/apache/pmns | 43 | ||||
-rw-r--r-- | src/pmdas/apache/root | 10 |
12 files changed, 945 insertions, 0 deletions
diff --git a/src/pmdas/apache/Apache.pmchart b/src/pmdas/apache/Apache.pmchart new file mode 100644 index 0000000..b830e4e --- /dev/null +++ b/src/pmdas/apache/Apache.pmchart @@ -0,0 +1,9 @@ +#pmchart +Version 2.0 host dynamic + +Chart Title "Apache Hit Rate" Style plot + Plot Color #-cycle Host * Metric apache.requests_per_sec +Chart Title "Apache Data Rate" Style plot + Plot Color #-cycle Host * Metric apache.bytes_per_sec +# +# Created Fri Jun 10 05:16:55 2005 diff --git a/src/pmdas/apache/GNUmakefile b/src/pmdas/apache/GNUmakefile new file mode 100644 index 0000000..8465706 --- /dev/null +++ b/src/pmdas/apache/GNUmakefile @@ -0,0 +1,61 @@ +# +# Copyright (C) 2000 Michal Kara. All Rights Reserved. +# +# 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; either version 2 of the License, or (at your +# option) any later version. +# +# 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. +# + +TOPDIR = ../../.. +include $(TOPDIR)/src/include/builddefs + +IAM = apache +DOMAIN = APACHE +TARGETS = $(IAM)$(EXECSUFFIX) +CFILES = apache.c +SCRIPTS = Install Remove +DFILES = README +LSRCFILES= $(SCRIPTS) pmns help root Apache.pmchart $(DFILES) \ + pmlogconf.summary pmlogconf.processes pmlogconf.uptime + +PMDADIR = $(PCP_PMDAS_DIR)/$(IAM) +PMCHART = $(PCP_VAR_DIR)/config/pmchart + +LDIRT = domain.h *.o $(IAM).log pmda$(IAM) pmda_$(IAM).so $(TARGETS) +LCFLAGS = -I$(TOPDIR)/src/libpcp_http/src +LLDFLAGS= -L$(TOPDIR)/src/libpcp_http/src +LLDLIBS = -lpcp_http $(PCP_PMDALIB) + +default: build-me + +include $(BUILDRULES) + +build-me: $(TARGETS) + +install: build-me + $(INSTALL) -m 755 -d $(PMDADIR) + $(INSTALL) -m 755 $(IAM) $(PMDADIR)/pmda$(IAM) + $(INSTALL) -m 755 $(SCRIPTS) $(PMDADIR) + $(INSTALL) -m 644 $(DFILES) pmns help root domain.h $(PMDADIR) + $(INSTALL) -m 644 Apache.pmchart $(PMCHART)/Apache + $(INSTALL) -m 755 -d $(PCP_VAR_DIR)/config/pmlogconf/$(IAM) + $(INSTALL) -m 644 pmlogconf.summary $(PCP_VAR_DIR)/config/pmlogconf/$(IAM)/summary + $(INSTALL) -m 644 pmlogconf.processes $(PCP_VAR_DIR)/config/pmlogconf/$(IAM)/processes + $(INSTALL) -m 644 pmlogconf.uptime $(PCP_VAR_DIR)/config/pmlogconf/$(IAM)/uptime + +$(IAM)$(EXECSUFFIX): $(OBJECTS) + +apache.o: domain.h + +domain.h: ../../pmns/stdpmid + $(DOMAIN_MAKERULE) + +default_pcp : default + +install_pcp : install diff --git a/src/pmdas/apache/Install b/src/pmdas/apache/Install new file mode 100755 index 0000000..8bd8e72 --- /dev/null +++ b/src/pmdas/apache/Install @@ -0,0 +1,54 @@ +#!/bin/sh +# +# Copyright (c) 2010 Aconex. All Rights Reserved. +# Copyright (c) 1999,2004 Silicon Graphics, Inc. All Rights Reserved. +# +# 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; either version 2 of the License, or (at your +# option) any later version. +# +# 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. +# +# Install the apache PMDA and/or PMNS +# + +. $PCP_DIR/etc/pcp.env +. $PCP_SHARE_DIR/lib/pmdaproc.sh + +iam=apache +pmda_interface=3 +forced_restart=false + +# Override interactive dialog from pmdaSetup in pmdaproc.sh +__choose_mode() +{ + echo "Installing the \"$iam\" Performance Metrics Domain Agent (PMDA) ..." + echo +} + +pmdaSetup + +if $do_pmda +then + args="" + + $PCP_ECHO_PROG $PCP_ECHO_N "Apache port number [80]? ""$PCP_ECHO_C" + read value + + if [ "X$value" = "X" ] + then + : + elif [ "X`expr 0 + $value 2>/dev/null`" != "X$value" ] + then + echo "-- Sorry, port number must be numeric (not $value), ignored --" >&2 + else + args="$args -P $value" + fi +fi + +pmdaInstall +exit 0 diff --git a/src/pmdas/apache/README b/src/pmdas/apache/README new file mode 100644 index 0000000..75eb7e3 --- /dev/null +++ b/src/pmdas/apache/README @@ -0,0 +1,84 @@ +Apache PMDA +=========== + +Export information from apache server info. + +Author: Michal Kara + +To use this PMDA, you must be running Apache 1.3.2 or later (for the +extended statistics). + +First configure your apache http server to enable status support. +The full procedure is documented at +http://www.apache.org/docs/mod/mod_status.html + +Edit /etc/apache2/mods-enabled/status.conf and enable the following: + +<Location /server-status> + SetHandler server-status + Allow from all +</Location> +ExtendedStatus On + +Note: you may wish to restrict access to the server status reports to +the local host only. See the Apache web site for instructions. + +You will need to stop and restart your Apache server after making +this change: +# apachectl restart + +Metrics +======= + +The file ./help contains descriptions for all of the metrics exported +by this PMDA. + +Once the PMDA has been installed, the following command will list all +the available metrics and their explanatory "help" text: + + $ pminfo -fT apache + +The metrics give basic information about Apache performance and about usage of +server threads. + +Installation +============ + + + # cd $PCP_PMDAS_DIR/apache + + + Check that there is no clash in the Performance Metrics Domain + defined in ./domain.h and the other PMDAs currently in use (see + $PCP_PMCDCONF_PATH). If there is, edit ./domain.h to choose another + domain number. + + + Then simply use + + # ./Install + + and optionally specify the port number where Apache is running. + Everything else is automated. + +De-installation +=============== + + + Simply use + + # cd $PCP_PMDAS_DIR/apache + # ./Remove + +Troubleshooting +=============== + + + After installing or restarting the agent, the PMCD log file + ($PCP_LOG_DIR/pmcd/pmcd.log) and the PMDA log file + ($PCP_LOG_DIR/pmcd/apache.log) should be checked for any warnings + or errors. + +Credits +======= + +Original PMDA was written by Michal Kara. + +This PMDA embeds a (slightly modified) lightweight "Http Fetcher" library, +written by Lyle Hanson (lhanson@users.sourceforge.net) (C) 2001, 2003, 2004 +http://http-fetcher.sourceforge.net diff --git a/src/pmdas/apache/Remove b/src/pmdas/apache/Remove new file mode 100644 index 0000000..8d9fae1 --- /dev/null +++ b/src/pmdas/apache/Remove @@ -0,0 +1,25 @@ +#!/bin/sh +# +# Copyright (c) 1999,2004 Silicon Graphics, Inc. All Rights Reserved. +# +# 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; either version 2 of the License, or (at your +# option) any later version. +# +# 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. +# +# Remove the apache PMDA +# + +. $PCP_DIR/etc/pcp.env +. $PCP_SHARE_DIR/lib/pmdaproc.sh + +iam=apache +pmdaSetup +pmdaRemove + +exit 0 diff --git a/src/pmdas/apache/apache.c b/src/pmdas/apache/apache.c new file mode 100644 index 0000000..3597308 --- /dev/null +++ b/src/pmdas/apache/apache.c @@ -0,0 +1,538 @@ +/* + * Apache PMDA + * + * Copyright (C) 2012-2014 Red Hat. + * Copyright (C) 2008-2010 Aconex. All Rights Reserved. + * Copyright (C) 2000 Michal Kara. All Rights Reserved. + * + * 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; either version 2 of the License, or (at your + * option) any later version. + * + * 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. + */ + +#include "pmapi.h" +#include "impl.h" +#include "pmda.h" +#include "domain.h" +#include "http_fetcher.h" +#include <inttypes.h> + +static char url[256]; +static char uptime_s[64]; +static char *username; + +static int http_port = 80; +static char *http_server = "localhost"; +static char *http_path = "server-status"; + +static pmLongOptions longopts[] = { + PMDA_OPTIONS_HEADER("Options"), + PMOPT_DEBUG, + PMDAOPT_DOMAIN, + PMDAOPT_LOGFILE, + { "server", 1, 'S', "HOST", "use remote host, instead of localhost" }, + { "port", 1, 'P', "PORT", "use given port on server, instead of port 80" }, + { "location", 1, 'L', "LOC", "use location on server, instead of 'server-status'" }, + PMDAOPT_USERNAME, + PMOPT_HELP, + PMDA_OPTIONS_TEXT("\nExactly one of the following options may appear:"), + PMDAOPT_INET, + PMDAOPT_PIPE, + PMDAOPT_UNIX, + PMDAOPT_IPV6, + PMDA_OPTIONS_END +}; + +static pmdaOptions opts = { + .short_options = "D:d:i:l:pu:L:P:S:U:6:?", + .long_options = longopts, +}; + +static pmdaMetric metrictab[] = { +/* apache.total_accesses */ + { NULL, { PMDA_PMID(0,0), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) } }, +/* apache.total_kbytes */ + { NULL, { PMDA_PMID(0,1), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER, + PMDA_PMUNITS(1,0,0,PM_SPACE_KBYTE,0,0) } }, +/* apache.uptime */ + { NULL, { PMDA_PMID(0,2), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(0,1,0,0,PM_TIME_SEC,0) } }, +/* apache.requests_per_sec */ + { NULL, { PMDA_PMID(0,3), PM_TYPE_DOUBLE, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(0,-1,1,0,PM_TIME_SEC,PM_COUNT_ONE) } }, +/* apache.bytes_per_sec */ + { NULL, { PMDA_PMID(0,4), PM_TYPE_DOUBLE, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(1,-1,0,PM_SPACE_BYTE,PM_TIME_SEC,0) } }, +/* apache.bytes_per_request */ + { NULL, { PMDA_PMID(0,5), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(1,0,-1,PM_SPACE_BYTE,0,PM_COUNT_ONE) } }, +/* apache.busy_servers */ + { NULL, { PMDA_PMID(0,6), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) } }, +/* apache.idle_servers */ + { NULL, { PMDA_PMID(0,7), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) } }, +/* apache.sb_waiting */ + { NULL, { PMDA_PMID(0,8), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) } }, +/* apache.sb_starting */ + { NULL, { PMDA_PMID(0,9), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) } }, +/* apache.sb_reading */ + { NULL, { PMDA_PMID(0,10), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) } }, +/* apache.sb_writing_reply */ + { NULL, { PMDA_PMID(0,11), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) } }, +/* apache.sb_keepalive */ + { NULL, { PMDA_PMID(0,12), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) } }, +/* apache.sb_dns_lookup */ + { NULL, { PMDA_PMID(0,13), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) } }, +/* apache.sb_logging */ + { NULL, { PMDA_PMID(0,14), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) } }, +/* apache.sb_finishing */ + { NULL, { PMDA_PMID(0,15), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) } }, +/* apache.sb_open_slot */ + { NULL, { PMDA_PMID(0,16), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) } }, +/* apache.sb_closing */ + { NULL, { PMDA_PMID(0,17), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) } }, +/* apache.sb_idle_cleanup */ + { NULL, { PMDA_PMID(0,18), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) } }, +/* apache.uptime_s */ + { NULL, { PMDA_PMID(0,19), PM_TYPE_STRING, PM_INDOM_NULL, PM_SEM_INSTANT, + PMDA_PMUNITS(0,0,0,0,0,0) } }, +}; + +/* + * To speed everything up, the PMDA is caching the data. + * Values are refreshed only if older than one second. + */ +struct { + unsigned int flags; /* Tells which values are valid */ + unsigned int timeout; /* There was a timeout (a bool) */ + time_t timestamp; /* Time of last attempted fetch */ + + __uint64_t uptime; + __uint64_t total_accesses; + __uint64_t total_kbytes; + double requests_per_sec; + double bytes_per_sec; + unsigned int bytes_per_request; + unsigned int busy_servers; + unsigned int idle_servers; + unsigned int sb_waiting; + unsigned int sb_starting; + unsigned int sb_reading; + unsigned int sb_writing_reply; + unsigned int sb_keepalive; + unsigned int sb_dns_lookup; + unsigned int sb_logging; + unsigned int sb_finishing; + unsigned int sb_open_slot; + unsigned int sb_closing; + unsigned int sb_idle_cleanup; +} data; + +/* + * Valid values of flags - tell us which values are currently setup. + * Depending on server version and configuration, some may be missing. + */ +enum { + ACCESSES = (1<<0), + KILOBYTES = (1<<1), + UPTIME = (1<<2), + REQPERSEC = (1<<3), + BYTESPERSEC = (1<<4), + BYTESPERREQ = (1<<5), + BUSYSERVERS = (1<<6), + IDLESERVERS = (1<<7), + SCOREBOARD = (1<<8), +}; + +static void uptime_string(time_t now, char *s, size_t sz) +{ + int days, hours, minutes, seconds; + + days = now / (60 * 60 * 24); + now %= (60 * 60 * 24); + hours = now / (60 * 60); + now %= (60 * 60); + minutes = now / 60; + now %= 60; + seconds = now; + + if (days > 1) + snprintf(s, sz, "%ddays %02d:%02d:%02d", days, hours, minutes, seconds); + else if (days == 1) + snprintf(s, sz, "%dday %02d:%02d:%02d", days, hours, minutes, seconds); + else + snprintf(s, sz, "%02d:%02d:%02d", hours, minutes, seconds); +} + +static void dumpData(void) +{ + uptime_string(data.uptime, uptime_s, sizeof(uptime_s)); + fprintf(stderr, "Apache data from %s port %d, path %s:\n", + http_server, http_port, http_path); + fprintf(stderr, " flags=0x%x timeout=%d timestamp=%lu\n", + data.flags, data.timeout, (unsigned long)data.timestamp); + fprintf(stderr, " uptime=%" PRIu64 " (%s)\n", data.uptime, uptime_s); + fprintf(stderr, " accesses=%" PRIu64 " kbytes=%" PRIu64 + " req/sec=%.2f b/sec=%.2f\n", + data.total_accesses, data.total_kbytes, + data.requests_per_sec, data.bytes_per_sec); + fprintf(stderr, " b/req=%u busyserv=%u idleserv=%u\n", + data.bytes_per_request, data.busy_servers, data.idle_servers); + fprintf(stderr, " scoreboard: waiting=%u starting=%u reading=%u\n", + data.sb_waiting, data.sb_starting, data.sb_reading); + fprintf(stderr, " writing_reply=%u keepalive=%u dn_lookup=%u\n", + data.sb_writing_reply, data.sb_keepalive, data.sb_dns_lookup); + fprintf(stderr, " logging=%u finishing=%u open_slot=%u\n", + data.sb_logging, data.sb_finishing, data.sb_open_slot); + fprintf(stderr, " closing=%u idle_cleanup=%u\n", + data.sb_closing, data.sb_idle_cleanup); +} + +/* + * Refresh data. Returns 1 of OK, 0 on error. + */ +static int refreshData(time_t now) +{ + char *res = NULL; + int len; + char *s,*s2,*s3; + + if (pmDebug & DBG_TRACE_APPL0) + fprintf(stderr, "Doing http_fetch(%s)\n", url); + + len = http_fetch(url, &res); + if (len < 0) { + if (pmDebug & DBG_TRACE_APPL1) + __pmNotifyErr(LOG_ERR, "HTTP fetch (stats) failed: %s\n", http_strerror()); + data.timeout = http_getTimeoutError(); + if (data.timeout) + data.timestamp = now; /* Don't retry too soon */ + if (res) + free(res); + return 0; /* failed */ + } + + memset(&data, 0, sizeof(data)); + + for (s = res; *s; ) { + s2 = s; + s3 = NULL; + for (; *s && *s != 10; s++) { + if (*s == ':') { + s3 = s + 1; + if (*s3) { + *s3++ = 0; + s++; + } + } + } + + if (*s == 10) + *s++ = 0; + + if (strcmp(s2, "CPULoad:") == 0) + /* ignored */ ; + else if (strcmp(s2, "Total Accesses:") == 0) { + data.total_accesses = strtoull(s3, (char **)NULL, 10); + data.flags |= ACCESSES; + } + else if (strcmp(s2, "Total kBytes:") == 0) { + data.total_kbytes = strtoull(s3, (char **)NULL, 10); + data.flags |= KILOBYTES; + } + else if (strcmp(s2, "Uptime:") == 0) { + data.uptime = strtoull(s3, (char **)NULL, 10); + data.flags |= UPTIME; + } + else if (strcmp(s2, "ReqPerSec:") == 0) { + data.requests_per_sec = strtod(s3, (char **)NULL); + data.flags |= REQPERSEC; + } + else if (strcmp(s2, "BytesPerSec:") == 0) { + data.bytes_per_sec = strtod(s3, (char **)NULL); + data.flags |= BYTESPERSEC; + } + else if (strcmp(s2, "BytesPerReq:") == 0) { + data.bytes_per_request = (unsigned int)strtoul(s3, (char **)NULL, 10); + data.flags |= BYTESPERREQ; + } + else if ((strcmp(s2, "BusyServers:") == 0) || + (strcmp(s2, "BusyWorkers:") == 0)) { + data.busy_servers = (unsigned int)strtoul(s3, (char **)NULL, 10); + data.flags |= BUSYSERVERS; + } + else if ((strcmp(s2, "IdleServers:") == 0) || + (strcmp(s2, "IdleWorkers:") == 0)) { + data.idle_servers = (unsigned int)strtoul(s3, (char **)NULL, 10); + data.flags |= IDLESERVERS; + } + else if (strcmp(s2, "Scoreboard:") == 0) { + data.flags |= SCOREBOARD; + while(*s3) { + switch(*s3) { + case '_': + data.sb_waiting++; + break; + case 'S': + data.sb_starting++; + break; + case 'R': + data.sb_reading++; + break; + case 'W': + data.sb_writing_reply++; + break; + case 'K': + data.sb_keepalive++; + break; + case 'D': + data.sb_dns_lookup++; + break; + case 'C': + data.sb_closing++; + break; + case 'L': + data.sb_logging++; + break; + case 'G': + data.sb_finishing++; + break; + case 'I': + data.sb_idle_cleanup++; + break; + case '.': + data.sb_open_slot++; + break; + default: + if (pmDebug & DBG_TRACE_APPL1) { + __pmNotifyErr(LOG_WARNING, + "Unknown scoreboard character '%c'\n", *s3); + } + } + s3++; + } + } + else if (pmDebug & DBG_TRACE_APPL1) { + __pmNotifyErr(LOG_WARNING, "Unknown value name '%s'!\n", s2); + } + } + + data.timestamp = now; + + if (pmDebug & DBG_TRACE_APPL2) + dumpData(); + free(res); + return 1; +} + +static int +apache_fetch(int numpmid, pmID pmidlist[], pmResult **resp, pmdaExt *pmda) +{ + time_t now = time(NULL); + + if (now > data.timestamp && !refreshData(now + 1)) + return PM_ERR_AGAIN; + if (data.timeout) + return PM_ERR_AGAIN; + + return pmdaFetch(numpmid, pmidlist, resp, pmda); +} + +static int +apache_fetchCallBack(pmdaMetric *mdesc, unsigned int inst, pmAtomValue *atom) +{ + __pmID_int *idp = (__pmID_int *)&(mdesc->m_desc.pmid); + + if (idp->cluster != 0) + return PM_ERR_PMID; + else if (inst != PM_IN_NULL) + return PM_ERR_INST; + + switch (idp->item) { + case 0: + if (!(data.flags & ACCESSES)) + return 0; + atom->ull = data.total_accesses; + break; + case 1: + if (!(data.flags & KILOBYTES)) + return 0; + atom->ull = data.total_kbytes; + break; + case 2: + if (!(data.flags & UPTIME)) + return 0; + atom->ull = data.uptime; + break; + case 3: + if (!(data.flags & REQPERSEC)) + return 0; + atom->d = data.requests_per_sec; + break; + case 4: + if (!(data.flags & BYTESPERSEC)) + return 0; + atom->d = data.bytes_per_sec; + break; + case 5: + if (!(data.flags & BYTESPERREQ)) + return 0; + atom->ul = data.bytes_per_request; + break; + case 6: + if (!(data.flags & BUSYSERVERS)) + return 0; + atom->ul = data.busy_servers; + break; + case 7: + if (!(data.flags & IDLESERVERS)) + return 0; + atom->ul = data.idle_servers; + break; + case 8: + if (!(data.flags & SCOREBOARD)) + return 0; + atom->ul = data.sb_waiting; + break; + case 9: + if (!(data.flags & SCOREBOARD)) + return 0; + atom->ul = data.sb_starting; + break; + case 10: + if (!(data.flags & SCOREBOARD)) + return 0; + atom->ul = data.sb_reading; + break; + case 11: + if (!(data.flags & SCOREBOARD)) + return 0; + atom->ul = data.sb_writing_reply; + break; + case 12: + if (!(data.flags & SCOREBOARD)) + return 0; + atom->ul = data.sb_keepalive; + break; + case 13: + if (!(data.flags & SCOREBOARD)) + return 0; + atom->ul = data.sb_dns_lookup; + break; + case 14: + if (!(data.flags & SCOREBOARD)) + return 0; + atom->ul = data.sb_logging; + break; + case 15: + if (!(data.flags & SCOREBOARD)) + return 0; + atom->ul = data.sb_finishing; + break; + case 16: + if (!(data.flags & SCOREBOARD)) + return 0; + atom->ul = data.sb_open_slot; + break; + case 17: + if (!(data.flags & SCOREBOARD)) + return 0; + atom->ul = data.sb_closing; + break; + case 18: + if (!(data.flags & SCOREBOARD)) + return 0; + atom->ul = data.sb_idle_cleanup; + break; + case 19: + if (!(data.flags & UPTIME)) + return 0; + uptime_string(data.uptime, uptime_s, sizeof(uptime_s)); + atom->cp = uptime_s; + break; + + default: + return PM_ERR_PMID; + } + + return 1; +} + +void +apache_init(pmdaInterface *dp) +{ + __pmSetProcessIdentity(username); + + http_setTimeout(1); + http_setUserAgent(pmProgname); + snprintf(url, sizeof(url), "http://%s:%u/%s?auto", http_server, http_port, http_path); + + dp->version.two.fetch = apache_fetch; + pmdaSetFetchCallBack(dp, apache_fetchCallBack); + pmdaInit(dp, NULL, 0, metrictab, sizeof(metrictab)/sizeof(metrictab[0])); +} + +int +main(int argc, char **argv) +{ + int c, sep = __pmPathSeparator(); + pmdaInterface pmda; + char helppath[MAXPATHLEN]; + + __pmSetProgname(argv[0]); + __pmGetUsername(&username); + + snprintf(helppath, sizeof(helppath), "%s%c" "apache" "%c" "help", + pmGetConfig("PCP_PMDAS_DIR"), sep, sep); + pmdaDaemon(&pmda, PMDA_INTERFACE_3, pmProgname, APACHE, "apache.log", + helppath); + + while ((c = pmdaGetOptions(argc, argv, &opts, &pmda)) != EOF) { + switch(c) { + case 'S': + http_server = opts.optarg; + break; + case 'P': + http_port = (int)strtol(opts.optarg, (char **)NULL, 10); + break; + case 'L': + if (opts.optarg[0] == '/') + opts.optarg++; + http_path = opts.optarg; + break; + } + } + + if (opts.errors) { + pmdaUsageMessage(&opts); + exit(1); + } + + if (opts.username) + username = opts.username; + + pmdaOpenLog(&pmda); + apache_init(&pmda); + pmdaConnect(&pmda); + pmdaMain(&pmda); + exit(0); +} diff --git a/src/pmdas/apache/help b/src/pmdas/apache/help new file mode 100644 index 0000000..08ee3b3 --- /dev/null +++ b/src/pmdas/apache/help @@ -0,0 +1,91 @@ +# +# Copyright (C) 2000 Michal Kara. All Rights Reserved. +# Copyright (c) 2008 Aconex. All Rights Reserved. +# +# 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; either version 2 of the License, or (at your +# option) any later version. +# +# 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 Street, Fifth Floor, Boston, MA 02110-1301 USA +# +# apache PMDA help file in the ASCII format +# + +@apache.total_accesses Number of accesses since Apache started +Number of accesses (requests) Apache handled since start of the server. + +@apache.total_kbytes KBytes transferred since Apache started +Number of kilobytes Apache transferred since start of the server. + +@apache.uptime Seconds since Apache started +Number of seconds elapsed since the server was started. + +@apache.requests_per_sec Requests per second +Average requests-per-second rate. Apache computes this as +(total_accesses / uptime), so its better to use total_accesses +to get current request rate. + +@apache.bytes_per_sec Bytes per second +Average bytes-per-second rate. Apache computes this as +(total_kbytes / uptime), so its better to use total_kbytes +to get current throughput. + +@apache.bytes_per_requests Bytes per request +Average number of bytes per request. Apache computes this as +total_kbytes/total_accesses. + +@apache.busy_servers Number of working processes +Number of Apache processes which are now working - reading requests, +receiving data, etc. Together with idle_servers this number gives the +total number of running Apache processes. + +@apache.idle_servers Number of idle processes +Number of Apache processes which are now idle - waiting for connection. +Together with busy_servers this number gives the total number of running +Apache processes. + +@apache.sb_waiting Number of waiting processes +Number of Apache processes waiting for connection. + +@apache.sb_starting Number of starting processes +Number of Apache processes just starting. + +@apache.sb_reading Number of processes reading +Number of Apache processes reading a request. + +@apache.sb_writing_reply Number of processes writing +Number of Apache processes writing a reply. + +@apache.sb_keepalive Number of processes keeping-alive connection +Number of Apache processes waiting for next request on a keep-alive +connection. + +@apache.sb_dns_lookup Number of processes doing DNS lookup +Number of Apache processes currently doing DNS lookup. + +@apache.sb_logging Number of processes writing to log +Number of Apache processes writing to a log. + +@apache.sb_finishing Number of proceses finishing +Number of Apache processes gracefuly finishing (becase the +RequestsPerChild limit was reached). + +@apache.sb_open_slot Number of open slots +Number of open "slots" which could be occupied by a process. Together +with busy_servers and idle_servers, this gives the MaxClients value. + +@apache.sb_closing Number of processes closing client connections +Number of Apache processes closing client connections + +@apache.sb_idle_cleanup Number of processes performing idle cleanup +Number of Apache processes performing idle cleanup + +@apache.uptime_s Time since Apache started, as a string diff --git a/src/pmdas/apache/pmlogconf.processes b/src/pmdas/apache/pmlogconf.processes new file mode 100644 index 0000000..9513e2d --- /dev/null +++ b/src/pmdas/apache/pmlogconf.processes @@ -0,0 +1,14 @@ +#pmlogconf-setup 2.0 +ident Apache process state information +probe apache.sb_waiting + apache.sb_waiting + apache.sb_starting + apache.sb_reading + apache.sb_writing_reply + apache.sb_keepalive + apache.sb_dns_lookup + apache.sb_logging + apache.sb_finishing + apache.sb_open_slot + apache.sb_closing + apache.sb_idle_cleanup diff --git a/src/pmdas/apache/pmlogconf.summary b/src/pmdas/apache/pmlogconf.summary new file mode 100644 index 0000000..7a88d85 --- /dev/null +++ b/src/pmdas/apache/pmlogconf.summary @@ -0,0 +1,10 @@ +#pmlogconf-setup 2.0 +ident Apache summary information +probe apache.total_accesses exists ? include : exclude + apache.total_accesses + apache.total_kbytes + apache.requests_per_sec + apache.bytes_per_sec + apache.bytes_per_requests + apache.busy_servers + apache.idle_servers diff --git a/src/pmdas/apache/pmlogconf.uptime b/src/pmdas/apache/pmlogconf.uptime new file mode 100644 index 0000000..2b2b7b7 --- /dev/null +++ b/src/pmdas/apache/pmlogconf.uptime @@ -0,0 +1,6 @@ +#pmlogconf-setup 2.0 +ident Apache uptime +probe apache.uptime exists ? include : exclude +delta 5 minutes + apache.uptime + apache.uptime_s diff --git a/src/pmdas/apache/pmns b/src/pmdas/apache/pmns new file mode 100644 index 0000000..c4d9f88 --- /dev/null +++ b/src/pmdas/apache/pmns @@ -0,0 +1,43 @@ +/* + * Metrics for apache PMDA + * + * Copyright (C) 2000 Michal Kara. All Rights Reserved. + * Copyright (c) 2008 Aconex. All Rights Reserved. + * + * 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; either version 2 of the License, or (at your + * option) any later version. + * + * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +apache { + total_accesses APACHE:0:0 + total_kbytes APACHE:0:1 + uptime APACHE:0:2 + requests_per_sec APACHE:0:3 + bytes_per_sec APACHE:0:4 + bytes_per_requests APACHE:0:5 + busy_servers APACHE:0:6 + idle_servers APACHE:0:7 + sb_waiting APACHE:0:8 + sb_starting APACHE:0:9 + sb_reading APACHE:0:10 + sb_writing_reply APACHE:0:11 + sb_keepalive APACHE:0:12 + sb_dns_lookup APACHE:0:13 + sb_logging APACHE:0:14 + sb_finishing APACHE:0:15 + sb_open_slot APACHE:0:16 + sb_closing APACHE:0:17 + sb_idle_cleanup APACHE:0:18 + uptime_s APACHE:0:19 +} diff --git a/src/pmdas/apache/root b/src/pmdas/apache/root new file mode 100644 index 0000000..7d2b7ed --- /dev/null +++ b/src/pmdas/apache/root @@ -0,0 +1,10 @@ +/* + * fake "root" for validating the local PMNS subtree + */ + +#include <stdpmid> + +root { apache } + +#include "pmns" + |