Hi,
even before the first release pmrep already has two archive recording
modes due to "historical reasons" :( I'd rather fix this before the
release. (I used pmcollectl's pmgui based approach as an example
initially but it doesn't cope with the from-archive-to-archive mode so
the pmi based approach was recently added.)
The pmgui method has the tiny "off-sync" issue mentioned earlier [1],
the pmi method doesn't suffer this as it simply skips those records,
apparently to no harm [2].
By switching to pmi in all cases, we can avoid duplication and avoid
this minor issue.
But perhaps most importantly, pmi will output archives not archive
folios (and doesn't create those config/log files) so it should be
easier for users as well.
1) http://oss.sgi.com/pipermail/pcp/2015-November/008741.html
2) http://oss.sgi.com/pipermail/pcp/2015-December/008892.html
---
src/pmrep/pmrep.1 | 21 +++++--------
src/pmrep/pmrep.py | 89 +++++++-----------------------------------------------
2 files changed, 19 insertions(+), 91 deletions(-)
diff --git a/src/pmrep/pmrep.1 b/src/pmrep/pmrep.1
index 36e692c..4c12cea 100644
--- a/src/pmrep/pmrep.1
+++ b/src/pmrep/pmrep.1
@@ -27,7 +27,7 @@
[\f3\-e\f1 \f2derived\f1]
[\f3\-E\f1 \f2lines\f1]
[\f3\-f\f1 \f2precision\f1]
-[\f3\-F\f1 \f2folio\f1]
+[\f3\-F\f1 \f2archive\f1]
[\f3\-h\f1 \f2host\f1]
[\f3\-K\f1 \f2spec\f1]
[\f3\-l\f1 \f2delimiter\f1]
@@ -212,14 +212,9 @@ See also
.TP
.B \-\-archive\-folio
Read metric source archives from the PCP archive
-.IR folio .
-Archive folios are created by
-.BR mkaf (1)
-or by
-.B pmrep
-when using the
-.I archive
-output mode described below.
+.IR folio
+(see
+.BR mkaf (1)).
.TP
.B \-A
When reporting archived metrics, force the initial sample to be
@@ -296,8 +291,8 @@ does not.
The default is to use 3 decimal places (when applicable).
.TP
.B \-F
-Specify the output archive
-.IR folio .
+Specify the output
+.IR archive .
See
.BR \-o .
.TP
@@ -362,7 +357,7 @@ The available target alternatives are:
.RS
.TP 2
.I archive
-Record metrics into PCP archives which can later be replayed with PCP
+Record metrics into a PCP archive which can later be replayed with PCP
tools, including
.B pmrep
itself. See
@@ -664,7 +659,7 @@ $ pmrep -a ./20150921.09.13 -S @15:00 -T @17:00 :sar-w
:sar-W
.PP
Record all 389 Directory Server, XFS file system and CPU/disk/memory
related metrics every five seconds for the next five minutes to the PCP
-archive folio
+archive
.IR ./a :
.RS +1
.ft CW
diff --git a/src/pmrep/pmrep.py b/src/pmrep/pmrep.py
index 773e368..dfa7c36 100644
--- a/src/pmrep/pmrep.py
+++ b/src/pmrep/pmrep.py
@@ -60,10 +60,9 @@ import sys
import os
import re
-from pcp import pmapi, pmgui, pmi
+from pcp import pmapi, pmi
from cpmapi import PM_CONTEXT_ARCHIVE, PM_CONTEXT_HOST, PM_CONTEXT_LOCAL,
PM_MODE_FORW, PM_MODE_INTERP, PM_ERR_TYPE, PM_ERR_EOL, PM_ERR_NAME, PM_IN_NULL,
PM_SEM_COUNTER, PM_TIME_MSEC, PM_TIME_SEC, PM_XTB_SET
from cpmapi import PM_TYPE_32, PM_TYPE_U32, PM_TYPE_64, PM_TYPE_U64,
PM_TYPE_FLOAT, PM_TYPE_DOUBLE, PM_TYPE_STRING
-from cpmgui import PM_REC_ON, PM_REC_OFF, PM_REC_SETARG
if sys.version_info[0] >= 3:
long = int
@@ -313,7 +312,7 @@ class PMReporter(object):
opts.pmSetLongOption("config", 1, "c", "FILE", "config file path")
opts.pmSetLongOption("check", 0, "C", "", "check config and metrics
and exit")
opts.pmSetLongOption("output", 1, "o", "OUTPUT", "output target, one
of: archive, csv, stdout (default), zabbix")
- opts.pmSetLongOption("output-archive", 1, "F", "ARCHIVE", "output
archive/folio (with -o archive)")
+ opts.pmSetLongOption("output-archive", 1, "F", "ARCHIVE", "output
archive (with -o archive)")
opts.pmSetLongOption("derived", 1, "e", "FILE|DFNT", "derived metrics
definitions")
opts.pmSetLongOptionDebug() # -D/--debug
opts.pmSetLongOptionVersion() # -V/--version
@@ -373,8 +372,8 @@ class PMReporter(object):
sys.stderr.write("Invalid output target %s specified.\n" %
optarg)
sys.exit(1)
elif opt == 'F':
- if os.path.exists(optarg) or os.path.exists(optarg + ".index"):
- sys.stderr.write("Archive/folio %s already exists.\n" % optarg)
+ if os.path.exists(optarg + ".index"):
+ sys.stderr.write("Archive %s already exists.\n" % optarg)
sys.exit(1)
self.archive = optarg
elif opt == 'e':
@@ -565,7 +564,7 @@ class PMReporter(object):
self.source = "@" # PCPIntro(1), RHBZ#1272082
if self.output == OUTPUT_ARCHIVE and not self.archive:
- sys.stderr.write("Archive/folio must be defined with archive
output.\n")
+ sys.stderr.write("Archive must be defined with archive output.\n")
sys.exit(1)
if self.output == OUTPUT_ZABBIX and (not self.zabbix_server or \
@@ -811,12 +810,6 @@ class PMReporter(object):
if self.check == 1:
return
- # Archive recording from non-archive is handled separately
- if self.output == OUTPUT_ARCHIVE:
- if self.context.type != PM_CONTEXT_ARCHIVE:
- self.write_archive_pmgui()
- return
-
# Archive fetching mode
if self.context.type == PM_CONTEXT_ARCHIVE:
(mode, step) = self.get_mode_step()
@@ -957,7 +950,7 @@ class PMReporter(object):
tstamp = dt.strftime(self.timefmt)
if self.output == OUTPUT_ARCHIVE:
- self.write_archive_pmi(tstamp, values)
+ self.write_archive(tstamp, values)
if self.output == OUTPUT_CSV:
self.write_csv(tstamp, values)
if self.output == OUTPUT_STDOUT:
@@ -1059,12 +1052,12 @@ class PMReporter(object):
def write_header(self):
""" Write metrics header """
if self.output == OUTPUT_ARCHIVE:
- sys.stdout.write("Recording archive/folio %s" % self.archive)
+ sys.stdout.write("Recording archive %s" % self.archive)
if self.runtime != -1:
- sys.stdout.write(":\n%s samples(s) with %.1f sec interval ~ %d
sec duration.\n" % (self.samples, float(self.interval), self.runtime + 1))
+ sys.stdout.write(":\n%s samples(s) with %.1f sec interval ~ %d
sec duration.\n" % (self.samples, float(self.interval), self.runtime))
elif self.samples:
duration = (self.samples - 1) * int(self.interval)
- sys.stdout.write(":\n%s samples(s) with %.1f sec interval ~ %d
sec duration.\n" % (self.samples, float(self.interval), duration + 1))
+ sys.stdout.write(":\n%s samples(s) with %.1f sec interval ~ %d
sec duration.\n" % (self.samples, float(self.interval), duration))
else:
if self.context.type != PM_CONTEXT_ARCHIVE:
sys.stdout.write("... (Ctrl-C to stop)")
@@ -1124,68 +1117,8 @@ class PMReporter(object):
else:
sys.stdout.write("...\n(Ctrl-C to stop)\n")
- def write_archive_pmgui(self):
- """ Write archive using pmgui """
- # We're not a graphical app, disable popups
- os.environ['PCP_XCONFIRM_PROG'] = '/bin/true'
-
- # Derived metrics need to be passed to pmlogger(1) via env/file
- if self.derived:
- if self.derived.startswith("/") or self.derived.startswith("."):
- if not os.environ.get('PCP_DERIVED_CONFIG'):
- os.environ['PCP_DERIVED_CONFIG'] = self.derived
- else:
- os.environ['PCP_DERIVED_CONFIG'] =
os.environ['PCP_DERIVED_CONFIG'] + ":" + self.derived
- else:
- drvf = self.archive + ".derived"
- if os.path.exists(drvf):
- sys.stderr.write("Derived metrics configuration file %s
already exists.\n" % drvf)
- sys.exit(1)
- drv = open(drvf, "a+")
- for definition in self.derived.split(","):
- drv.write(definition.strip() + "\n")
- drv.close()
- if not os.environ.get('PCP_DERIVED_CONFIG'):
- os.environ['PCP_DERIVED_CONFIG'] = drvf
- else:
- os.environ['PCP_DERIVED_CONFIG'] =
os.environ['PCP_DERIVED_CONFIG'] + ":" + drvf
-
- # Create the archive folio using pmgui
- context = pmgui.GuiClient()
- config = "log mandatory on every " + str(int(self.interval)) + " sec
{\n"
- for metric in self.metrics:
- config += metric + "\n"
- config += "}\n"
- context.pmRecordSetup(self.archive, ' '.join(sys.argv), 0)
- context.pmRecordAddHost(self.source, 1, config)
- duration = 0
- if self.runtime != -1:
- duration = self.runtime
- elif self.samples:
- if self.samples < 2:
- self.samples = 2
- duration = (self.samples - 1) * int(self.interval)
- if duration:
- endtime = "-T" + str(duration) + "sec"
- context.pmRecordControl(0, PM_REC_SETARG, endtime)
- context.pmRecordControl(0, PM_REC_ON, "")
- if not duration:
- time.sleep(0xFFFFFFFF) # A very long time
- context.pmRecordControl(0, PM_REC_OFF, "") # Non-mandatory
- return
- for i in range(duration):
- sys.stdout.write("\rProgress: %3d%%" % int(float(i) / duration *
100))
- sys.stdout.flush()
- time.sleep(1)
- sys.stdout.write("\rProgress: 99%")
- sys.stdout.flush()
- time.sleep(1) # Make sure the last record gets there
- # For cleanliness only, -T should have stopped recording by now
- context.pmRecordControl(0, PM_REC_OFF, "")
- sys.stdout.write("\rComplete: 100%.\n")
-
- def write_archive_pmi(self, timestamp, values):
- """ Write an archive record using pmi """
+ def write_archive(self, timestamp, values):
+ """ Write an archive record """
if timestamp == None and values == None:
# Complete and close
self.log.pmiEnd()
Thanks,
--
Marko Myllynen
|