summaryrefslogtreecommitdiff
path: root/src/pmdas/trace/src/pmda.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pmdas/trace/src/pmda.c')
-rw-r--r--src/pmdas/trace/src/pmda.c228
1 files changed, 228 insertions, 0 deletions
diff --git a/src/pmdas/trace/src/pmda.c b/src/pmdas/trace/src/pmda.c
new file mode 100644
index 0000000..36560aa
--- /dev/null
+++ b/src/pmdas/trace/src/pmda.c
@@ -0,0 +1,228 @@
+/*
+ * Trace PMDA - process level transaction monitoring for libpcp_trace processes
+ *
+ * Copyright (c) 2012 Red Hat.
+ * Copyright (c) 1997-2000 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.
+ */
+
+#include <ctype.h>
+#include "pmapi.h"
+#include "impl.h"
+#include "pmda.h"
+#include "domain.h"
+#include "trace.h"
+#include "trace_dev.h"
+#include "comms.h"
+
+#define DEFAULT_TIMESPAN 60 /* one minute */
+#define DEFAULT_BUFSIZE 5 /* twelve second update */
+
+struct timeval timespan = { DEFAULT_TIMESPAN, 0 };
+struct timeval interval;
+unsigned int rbufsize = DEFAULT_BUFSIZE;
+int ctlport = -1;
+char *ctlsock;
+
+static char mypath[MAXPATHLEN];
+static char *username;
+
+extern void traceInit(pmdaInterface *dispatch);
+extern void traceMain(pmdaInterface *dispatch);
+extern int updateObserveValue(const char *);
+extern int updateCounterValue(const char *);
+extern void debuglibrary(int);
+
+static void
+usage(void)
+{
+ fprintf(stderr,
+"Usage: %s [options]\n\
+\n\
+Options:\n\
+ -d domain use domain (numeric) for metrics domain of PMDA\n\
+ -l logfile write log into logfile rather than using default file\n\
+ -A access host based access control\n\
+ -I port expect programs to connect on given inet port (number/name)\n\
+ -M username user account to run under (default \"pcp\")\n\
+ -N buckets number of historical data buffers maintained\n\
+ -T period time over which samples are considered (default 60 seconds)\n\
+ -U units export observation values using the given units\n\
+ -V units export counter values using the given units\n",
+ pmProgname);
+ exit(1);
+}
+
+static char *
+squash(char *str, int *offset)
+{
+ char *hspec = NULL;
+ char *p = str;
+ int i = 0;
+
+ hspec = strdup(str); /* make sure we have space */
+ *offset = 0;
+ while (isspace((int)*p)) { p++; (*offset)++; }
+ while (p && *p != ':' && *p != '\0') {
+ hspec[i++] = *p;
+ p++;
+ }
+ hspec[i] = '\0';
+ *offset += i;
+ return hspec;
+}
+
+static int
+parseAuth(char *spec)
+{
+ static int first = 1;
+ int offset, maxconn, specops = TR_OP_ALL, denyops;
+ char *p, *endnum;
+
+ if (first) {
+ if (__pmAccAddOp(TR_OP_SEND) < 0) {
+ __pmNotifyErr(LOG_ERR, "failed to add send auth operation");
+ return -1;
+ }
+ first = 0;
+ }
+
+ if (strncasecmp(spec, "disallow:", 9) == 0) {
+ p = squash(&spec[9], &offset);
+ if (p == NULL || p[0] == '\0') {
+ fprintf(stderr, "%s: invalid disallow (%s)\n", pmProgname, spec);
+ if (p)
+ free(p);
+ return -1;
+ }
+#ifdef PCP_DEBUG
+ if (pmDebug & DBG_TRACE_APPL0)
+ fprintf(stderr, "deny: host '%s'\n", p);
+#endif
+ denyops = TR_OP_SEND;
+ if (__pmAccAddHost(p, specops, denyops, 0) < 0)
+ __pmNotifyErr(LOG_ERR, "failed to add authorisation (%s)", p);
+ free(p);
+ }
+ else if (strncasecmp(spec, "allow:", 6) == 0) {
+ p = squash(&spec[6], &offset);
+ if (p == NULL || p[0] == '\0') {
+ fprintf(stderr, "%s: invalid allow (%s)\n", pmProgname, spec);
+ if (p)
+ free(p);
+ return -1;
+ }
+ offset += 7;
+ maxconn = (int)strtol(&spec[offset], &endnum, 10);
+ if (*endnum != '\0' || maxconn < 0) {
+ fprintf(stderr, "%s: bogus max connection in '%s'\n", pmProgname,
+ &spec[offset]);
+ free(p);
+ return -1;
+ }
+#ifdef PCP_DEBUG
+ if (pmDebug & DBG_TRACE_APPL0)
+ fprintf(stderr, "allow: host '%s', maxconn=%d\n", p, maxconn);
+#endif
+ denyops = TR_OP_NONE;
+ if (__pmAccAddHost(p, specops, denyops, maxconn) < 0)
+ __pmNotifyErr(LOG_ERR, "failed to add authorisation (%s)", p);
+ free(p);
+ }
+ else {
+ fprintf(stderr, "%s: access spec is invalid (%s)\n", pmProgname, spec);
+ return -1;
+ }
+ return 0;
+}
+
+int
+main(int argc, char **argv)
+{
+ pmdaInterface dispatch;
+ char *endnum;
+ int err = 0;
+ int sep = __pmPathSeparator();
+ int c = 0;
+
+ __pmSetProgname(argv[0]);
+ __pmGetUsername(&username);
+
+ snprintf(mypath, sizeof(mypath), "%s%c" "trace" "%c" "help",
+ pmGetConfig("PCP_PMDAS_DIR"), sep, sep);
+ pmdaDaemon(&dispatch, PMDA_INTERFACE_2, pmProgname, TRACE,
+ "trace.log", mypath);
+
+ /* need - port, as well as time interval and time span for averaging */
+ while ((c = pmdaGetOpt(argc, argv, "A:D:d:I:l:T:M:N:U:V:?",
+ &dispatch, &err)) != EOF) {
+ switch(c) {
+ case 'A':
+ if (parseAuth(optarg) < 0)
+ err++;
+ /* add optarg to access control list */
+ break;
+ case 'I':
+ ctlport = (int)strtol(optarg, &endnum, 10);
+ if (*endnum != '\0' || ctlport < 0)
+ ctlsock = optarg;
+ break;
+ case 'M':
+ username = optarg;
+ break;
+ case 'N':
+ rbufsize = (int)strtol(optarg, &endnum, 10);
+ if (*endnum != '\0' || rbufsize < 1) {
+ fprintf(stderr, "%s: -N requires a positive number.\n", pmProgname);
+ err++;
+ }
+ break;
+ case 'T':
+ if (pmParseInterval(optarg, &timespan, &endnum) < 0) {
+ fprintf(stderr, "%s: -T requires a time interval: %s\n",
+ pmProgname, endnum);
+ free(endnum);
+ err++;
+ }
+ break;
+ case 'U':
+ if (updateObserveValue(optarg) < 0)
+ err++;
+ break;
+ case 'V':
+ if (updateCounterValue(optarg) < 0)
+ err++;
+ break;
+ default:
+ err++;
+ }
+ }
+
+ if (err)
+ usage();
+
+ interval.tv_sec = (int)(timespan.tv_sec / rbufsize);
+ interval.tv_usec = (long)((timespan.tv_sec % rbufsize) * 1000000);
+ rbufsize++; /* reserve space for the `working' buffer */
+
+#ifdef PCP_DEBUG
+ debuglibrary(pmDebug);
+#endif
+
+ pmdaOpenLog(&dispatch);
+ __pmSetProcessIdentity(username);
+ traceInit(&dispatch);
+ pmdaConnect(&dispatch);
+ traceMain(&dispatch);
+
+ exit(0);
+}