summaryrefslogtreecommitdiff
path: root/src/collectl2pcp/collectl2pcp.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/collectl2pcp/collectl2pcp.c')
-rw-r--r--src/collectl2pcp/collectl2pcp.c268
1 files changed, 268 insertions, 0 deletions
diff --git a/src/collectl2pcp/collectl2pcp.c b/src/collectl2pcp/collectl2pcp.c
new file mode 100644
index 0000000..c9755af
--- /dev/null
+++ b/src/collectl2pcp/collectl2pcp.c
@@ -0,0 +1,268 @@
+/*
+ * Copyright (c) 2013-2014 Red Hat.
+ *
+ * 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.
+ *
+ * Import collectl raw data file and create a PCP archive.
+ * Mark Goodwin <mgoodwin@redhat.com> May 2013.
+ */
+
+#include <pcp/pmapi.h>
+#include <pcp/impl.h>
+#include <pcp/pmda.h>
+#include <pcp/import.h>
+#include "metrics.h"
+
+#define BUFSIZE 1048576
+
+handler_t handlers[] = {
+ { ">>>", timestamp_handler },
+
+ /* /proc/PID/... */
+ { "proc:*", proc_handler },
+
+ /* /proc/stat */
+ { "cpu*", cpu_handler },
+ { "processes", generic1_handler, "kernel.all.nprocs" },
+ { "intr", generic1_handler, "kernel.all.intr" },
+ { "ctxt", generic1_handler, "kernel.all.pswitch" },
+
+ /* /proc/diskstats */
+ { "disk", disk_handler },
+
+ /* /proc/net/dev */
+ { "Net", net_handler },
+
+ /* /proc/loadavg */
+ { "load", loadavg_handler },
+
+ /* /proc/meminfo */
+ { "MemTotal:", generic1_handler, "mem.physmem" },
+ { "MemFree:", generic1_handler, "mem.util.free" },
+ { "Buffers:", generic1_handler, "mem.util.bufmem" },
+ { "Cached:", generic1_handler, "mem.util.cached" },
+ { "SwapCached:", generic1_handler, "mem.util.swapCached" },
+ { "Active:", generic1_handler, "mem.util.active" },
+ { "Inactive:", generic1_handler, "mem.util.inactive" },
+ { "Active(anon):", generic1_handler, "mem.util.active_anon" },
+ { "Inactive(anon):", generic1_handler, "mem.util.inactive_anon" },
+ { "Active(file):", generic1_handler, "mem.util.active_file" },
+ { "Inactive(file):", generic1_handler, "mem.util.inactive_file" },
+ { "Unevictable:", generic1_handler, "mem.util.unevictable" },
+ { "Mlocked:", generic1_handler, "mem.util.mlocked" },
+ { "SwapTotal:", generic1_handler, "mem.util.swapTotal" },
+ { "SwapFree:", generic1_handler, "mem.util.swapFree" },
+ { "Dirty:", generic1_handler, "mem.util.dirty" },
+ { "Writeback:", generic1_handler, "mem.util.writeback" },
+ { "AnonPages:", generic1_handler, "mem.util.anonpages" },
+ { "Mapped:", generic1_handler, "mem.util.mapped" },
+ { "Shmem:", generic1_handler, "mem.util.shmem" },
+ { "Slab:", generic1_handler, "mem.util.slab" },
+ { "SReclaimable:", generic1_handler, "mem.util.slabReclaimable" },
+ { "SUnreclaim:", generic1_handler, "mem.util.slabUnreclaimable" },
+ { "KernelStack:", generic1_handler, "mem.util.kernelStack" },
+ { "PageTables:", generic1_handler, "mem.util.pageTables" },
+ { "NFS_Unstable:", generic1_handler, "mem.util.NFS_Unstable" },
+ { "Bounce:", generic1_handler, "mem.util.bounce" },
+ { "WritebackTmp:", generic1_handler, "unknown" },
+ { "CommitLimit:", generic1_handler, "mem.util.commitLimit" },
+ { "Committed_AS:", generic1_handler, "mem.util.committed_AS" },
+ { "VmallocTotal:", generic1_handler, "mem.util.vmallocTotal" },
+ { "VmallocUsed:", generic1_handler, "mem.util.vmallocUsed" },
+ { "VmallocChunk:", generic1_handler, "mem.util.vmallocChunk" },
+ { "HardwareCorrupted:", generic1_handler, "mem.util.corrupthardware" },
+ { "AnonHugePages:", generic1_handler, "mem.util.anonhugepages" },
+ { "HugePages_Total:", generic1_handler, "mem.util.hugepagesTotal" },
+ { "HugePages_Free:", generic1_handler, "mem.util.hugepagesFree" },
+ { "HugePages_Rsvd:", generic1_handler, "mem.util.hugepagesRsvd" },
+ { "HugePages_Surp:", generic1_handler, "mem.util.hugepagesSurp" },
+ { "Hugepagesize:", generic1_handler, "unknown" },
+ { "DirectMap4k:", generic1_handler, "mem.util.directMap4k" },
+ { "DirectMap2M:", generic1_handler, "mem.util.directMap2M" },
+
+ { NULL }
+};
+
+int indom_cnt[NUM_INDOMS];
+
+/* global options */
+int vflag;
+int Fflag;
+int kernel_all_hz;
+int utc_offset;
+
+static pmLongOptions longopts[] = {
+ PMAPI_OPTIONS_HEADER("Options"),
+ PMOPT_DEBUG,
+ { "force", 0, 'f', 0, "forces overwrite of 'archive' if it already exists" },
+ { "verbose", 0, 'v', 0, "enables increasingly verbose messages" },
+ PMOPT_HELP,
+ PMAPI_OPTIONS_END
+};
+
+static pmOptions opts = {
+ .short_options = "FD:v?",
+ .long_options = longopts,
+ .short_usage = "inputfile [inputfile ...] archive\n"
+"Each 'inputfile' is a collectl archive, must be for the same host (may be gzipped).\n"
+"'archive' is the base name for the PCP archive to be created."
+};
+
+int
+main(int argc, char *argv[])
+{
+ int sts;
+ int ctx;
+ int c;
+ char *infile;
+ int nfilelist;
+ int filenum;
+ char *archive = NULL;
+ int j;
+ char *buf;
+ fields_t *f;
+ char *s;
+ int gzipped;
+ FILE *fp;
+ metric_t *m;
+ handler_t *h;
+ int unhandled_metric_cnt = 0;
+
+ while ((c = pmGetOptions(argc, argv, &opts)) != EOF) {
+ switch (c) {
+ case 'F':
+ Fflag = 1;
+ break;
+ case 'v':
+ vflag++;
+ break;
+ }
+ }
+
+ nfilelist = argc - opts.optind - 1;
+ if (nfilelist < 1)
+ opts.errors++;
+ else
+ archive = argv[argc - 1];
+
+ if (opts.errors) {
+ pmUsageMessage(&opts);
+ exit(1);
+ }
+
+ if ((buf = malloc(BUFSIZE)) == NULL) {
+ perror("Error: out of memory:");
+ exit(1);
+ }
+
+ if (Fflag) {
+ snprintf(buf, BUFSIZE, "%s.meta", archive); unlink(buf);
+ snprintf(buf, BUFSIZE, "%s.index", archive); unlink(buf);
+ for (j=0;; j++) {
+ snprintf(buf, BUFSIZE, "%s.%d", archive, j);
+ if (unlink(buf) < 0)
+ break;
+ }
+ }
+
+ ctx = pmiStart(archive, 0);
+ if ((sts = pmiUseContext(ctx)) < 0) {
+ fprintf(stderr, "Error: pmiUseContext failed: %s\n", pmiErrStr(sts));
+ exit(1);
+ }
+
+ /*
+ * Define the metrics name space, see metrics.c (generated by pmdesc)
+ */
+ for (m = metrics; m->name; m++) {
+ pmDesc *d = &m->desc;
+
+ sts = pmiAddMetric(m->name, d->pmid, d->type, d->indom, d->sem, d->units);
+ if (sts < 0) {
+ fprintf(stderr, "Error: failed to add metric %s: %s\n", m->name, pmiErrStr(sts));
+ exit(1);
+ }
+ }
+
+ /*
+ * Populate special case instance domains
+ */
+ pmiAddInstance(pmInDom_build(LINUX_DOMAIN, LOADAVG_INDOM), "1 minute", 1);
+ pmiAddInstance(pmInDom_build(LINUX_DOMAIN, LOADAVG_INDOM), "5 minute", 5);
+ pmiAddInstance(pmInDom_build(LINUX_DOMAIN, LOADAVG_INDOM), "15 minute", 15);
+ indom_cnt[LOADAVG_INDOM] = 3;
+
+ for (filenum=0; filenum < nfilelist; filenum++) {
+ infile = argv[opts.optind + filenum];
+ gzipped = strstr(infile, ".gz") != NULL;
+ if (gzipped) {
+ snprintf(buf, BUFSIZE, "gzip -c -d %s", infile);
+ if ((fp = popen(buf, "r")) == NULL)
+ perror(buf);
+ }
+ else
+ if ((fp = fopen(infile, "r")) == NULL)
+ perror(infile);
+
+ if (fp == NULL) {
+ pmUsageMessage(&opts);
+ exit(1);
+ }
+
+ /*
+ * parse the header
+ */
+ sts = header_handler(fp, infile, buf, BUFSIZE);
+
+ /*
+ * Parse remaining data stream for this input file
+ */
+ while(fgets(buf, BUFSIZE, fp)) {
+ if ((s = strrchr(buf, '\n')) != NULL)
+ *s = '\0';
+ if (!buf[0])
+ continue;
+ f = fields_new(buf, strlen(buf)+1);
+ if (f->nfields > 0) {
+ if ((h = find_handler(f->fields[0])) == NULL) {
+ unhandled_metric_cnt++;
+ if (vflag > 1)
+ printf("Unhandled tag: \"%s\"\n", f->fields[0]);
+ }
+ else {
+ sts = h->handler(h, f);
+ if (sts < 0 && h->handler == timestamp_handler) {
+ fprintf(stderr, "Error: %s\n", pmiErrStr(sts));
+ exit(1);
+ }
+ }
+ }
+ fields_free(f);
+ }
+
+ /* final flush for this file */
+ if ((sts = timestamp_flush()) < 0) {
+ fprintf(stderr, "Error: failed to write final timestamp: %s\n", pmiErrStr(sts));
+ exit(1);
+ }
+
+ if (gzipped)
+ pclose(fp);
+ else
+ fclose(fp);
+ }
+
+ sts = pmiEnd();
+ if (unhandled_metric_cnt && vflag)
+ fprintf(stderr, "Warning: %d unhandled metric/values\n", unhandled_metric_cnt);
+
+ exit(0);
+}