summaryrefslogtreecommitdiff
path: root/src/pmdas/apache
diff options
context:
space:
mode:
authorIgor Pashev <pashev.igor@gmail.com>2014-10-26 12:33:50 +0400
committerIgor Pashev <pashev.igor@gmail.com>2014-10-26 12:33:50 +0400
commit47e6e7c84f008a53061e661f31ae96629bc694ef (patch)
tree648a07f3b5b9d67ce19b0fd72e8caa1175c98f1a /src/pmdas/apache
downloadpcp-debian.tar.gz
Debian 3.9.10debian/3.9.10debian
Diffstat (limited to 'src/pmdas/apache')
-rw-r--r--src/pmdas/apache/Apache.pmchart9
-rw-r--r--src/pmdas/apache/GNUmakefile61
-rwxr-xr-xsrc/pmdas/apache/Install54
-rw-r--r--src/pmdas/apache/README84
-rw-r--r--src/pmdas/apache/Remove25
-rw-r--r--src/pmdas/apache/apache.c538
-rw-r--r--src/pmdas/apache/help91
-rw-r--r--src/pmdas/apache/pmlogconf.processes14
-rw-r--r--src/pmdas/apache/pmlogconf.summary10
-rw-r--r--src/pmdas/apache/pmlogconf.uptime6
-rw-r--r--src/pmdas/apache/pmns43
-rw-r--r--src/pmdas/apache/root10
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"
+