summaryrefslogtreecommitdiff
path: root/src/pmsnap
diff options
context:
space:
mode:
Diffstat (limited to 'src/pmsnap')
-rw-r--r--src/pmsnap/GNUmakefile29
-rw-r--r--src/pmsnap/Snap30
-rw-r--r--src/pmsnap/control71
-rw-r--r--src/pmsnap/crontab.IN6
-rwxr-xr-xsrc/pmsnap/pmsnap.sh457
-rw-r--r--src/pmsnap/summary.html34
6 files changed, 627 insertions, 0 deletions
diff --git a/src/pmsnap/GNUmakefile b/src/pmsnap/GNUmakefile
new file mode 100644
index 0000000..df7c270
--- /dev/null
+++ b/src/pmsnap/GNUmakefile
@@ -0,0 +1,29 @@
+TOPDIR = ../..
+include $(TOPDIR)/src/include/builddefs
+
+SCRIPTS = pmsnap.sh
+CONFIGS = crontab.IN Snap control
+HTMLDOC = summary.html
+LSRCFILES = $(SCRIPTS) $(CONFIGS) $(HTMLDOC)
+LDIRT = crontab
+
+default: crontab
+
+crontab : crontab.IN
+ $(SED) -e '/\# .*/b' -e 's;PCP_BINADM_DIR;$(PCP_BINADM_DIR);g' < $< > $@
+
+include $(BUILDRULES)
+
+install: default
+ifeq "$(ENABLE_QT)" "true"
+ $(INSTALL) -m 755 -d $(PCP_BINADM_DIR)
+ $(INSTALL) -m 755 pmsnap.sh $(PCP_BINADM_DIR)/pmsnap
+ $(INSTALL) -m 755 -d $(PCP_VAR_DIR)/config/pmsnap
+ $(INSTALL) -m 644 Snap crontab summary.html $(PCP_VAR_DIR)/config/pmsnap
+ $(INSTALL) -m 755 -d `dirname $(PCP_PMSNAPCONTROL_PATH)`
+ $(INSTALL) -m 644 control $(PCP_PMSNAPCONTROL_PATH)
+endif
+
+default_pcp: default
+
+install_pcp: install
diff --git a/src/pmsnap/Snap b/src/pmsnap/Snap
new file mode 100644
index 0000000..8f49a80
--- /dev/null
+++ b/src/pmsnap/Snap
@@ -0,0 +1,30 @@
+#kmchart
+Version 1
+
+Chart Title "CPU Utilization" Style utilization
+ Plot Color #2d2de2 Metric kernel.all.cpu.user
+ Plot Color #e71717 Metric kernel.all.cpu.sys
+ Plot Color rgbi:0.8/0.8/0.0 Metric kernel.all.cpu.intr
+ Optional-Plot Color rgbi:0.4/0.9/0.4 Metric kernel.all.cpu.nice
+ Optional-Plot Color rgbi:0.0/0.8/0.8 Metric kernel.all.cpu.wait.total
+ Plot Color #16e116 Metric kernel.all.cpu.idle
+
+Chart Title "Average Load" Style plot
+ Plot Metric kernel.all.load Instance 1 minute
+ Plot Metric kernel.all.load Instance 5 minute
+ Plot Metric kernel.all.load Instance 15 minute
+ Plot Color black Metric hinv.ncpu
+
+Chart Title "Disk Activity" Style stacking
+ Plot Color yellow Metric disk.all.read
+ Plot Color violet Metric disk.all.write
+
+Chart Title "Network Interface Activity" Style stacking
+ Plot Metric network.interface.in.bytes Not-Matching ^lo|^sl|^ppp|^sit
+ Plot Metric network.interface.out.bytes Not-Matching ^lo|^sl|^ppp|^sit
+
+Chart Title "TCP Network Failures" Style stacking
+ Plot Metric network.tcp.attemptfails Not-Matching ^lo|^sl|^ppp|^sit
+ Plot Metric network.tcp.retranssegs Not-Matching ^lo|^sl|^ppp|^sit
+ Plot Metric network.tcp.inerrs Not-Matching ^lo|^sl|^ppp|^sit
+ Plot Metric network.tcp.outrsts Not-Matching ^lo|^sl|^ppp|^sit
diff --git a/src/pmsnap/control b/src/pmsnap/control
new file mode 100644
index 0000000..54440b5
--- /dev/null
+++ b/src/pmsnap/control
@@ -0,0 +1,71 @@
+#
+# Configuration file for pmsnap(1)
+#
+# This file controls the output of pmsnap.
+# See the manual page for pmsnap(1) for full details.
+#
+# Although not mandatory, it is strongly advised that you follow
+# the instructions described in the manual page for pmlogger_daily(1)
+# before proceeding with the instructions described in pmsnap(1).
+#
+# Each line below (which is not a comment) has 4 columns, with
+# the following meaning ..
+#
+# (1) Name : name of the output file. This is typically
+# in the local Web content directory hierarchy.
+#
+# (2) Folio : use the named PCP archive, OR use the archives
+# in the named PCP archive folio. This is usually
+# in PCP_LOG_DIR/pmlogger/HOSTNAME, but may be the path of an
+# archive on an NFS/CIFS mounted filesystem if logging is done
+# on a remote host. Note that pmlogger_daily(1) automatically
+# creates the folio PCP_LOG_DIR/pmlogger/LOCALHOSTNAME/Latest.
+#
+# (3) Config : the pmchart "view" to use. If not found in the
+# local directory (relative to the -o flag), pmsnap
+# will also search the directories $PCP_VAR_DIR/config/pmsnap,
+# $PCP_VAR_DIR/config/pmchart, and $PCP_VAR_DIR/config/pmchart.
+#
+# (4) Arguments : passed to pmchart, see pmchart(1). Note that $commonargs
+# will be prepended to the argument list (see the assignment to
+# $commonargs below). Do NOT include any of the following
+# arguments: -o -c -a
+#
+# Notes : the string LOCALHOSTNAME in this file will be substituted
+# by the name of the local host by pmsnap at run-time.
+# If pmlogger is logging Snap metrics on the local host,
+# the example below should work virtually out of the box,
+# provided you want the output images in /var/www/htdocs/snapshots.
+# You will of course need to publish an html page that shows
+# the generated gif images - you can use the example provided
+# in the file $PCP_VAR_DIR/config/pmsnap/Snap.html.
+#
+# : lines beginning with $ are assumed to be assignments to
+# environment variables in the style of sh(1), and all text
+# following the $ will be eval'ed by the script reading
+# this control file, and the corresponding variable
+# exported into the environment.
+#
+# Recommended pmchart arguments :
+# -g 650x600 (raw image size, Width x Height)
+# -t 1min (update interval, i.e. time between ticks on the X-Axis)
+# -v 30 (number of visible points)
+# -O -0 (show end of archive, backwards by (-vh) * (-t) seconds)
+# -A 10min (aligned to start at the nearest 10 minutes)
+# -W (generated image has a white background, not transparent)
+#
+
+# === Variable Assignments ===
+#
+# DO NOT REMOVE OR EDIT THE FOLLOWING LINE
+$version=1.0
+
+# Common pmchart Arguments. Edit as required.
+$commonargs=''
+
+#
+# === pmsnap Control Specifications ===
+#
+# Name (Output Image) Folio|Archive Config Arguments
+/var/www/pcp/LOCALHOSTNAME.1hour.summary LOCALHOSTNAME/Latest Snap -O-0 -A 10min -t 2min -v 30
+/var/www/pcp/LOCALHOSTNAME.12hour.summary LOCALHOSTNAME/Latest Snap -O-0 -A 1hour -t 30min -v 30
diff --git a/src/pmsnap/crontab.IN b/src/pmsnap/crontab.IN
new file mode 100644
index 0000000..32427b0
--- /dev/null
+++ b/src/pmsnap/crontab.IN
@@ -0,0 +1,6 @@
+#
+# Standard Performance Co-Pilot pmsnap crontab entry for a PCP site
+# with one or more pmlogger instances running
+#
+# every 30 minutes, generate snapshot images
+30,0 * * * * PCP_BIN_DIR/pmsnap # -d DISPLAY
diff --git a/src/pmsnap/pmsnap.sh b/src/pmsnap/pmsnap.sh
new file mode 100755
index 0000000..87434a5
--- /dev/null
+++ b/src/pmsnap/pmsnap.sh
@@ -0,0 +1,457 @@
+#!/bin/sh
+#
+# Copyright (c) 2008 Aconex. All Rights Reserved.
+# Copyright (c) 1995-2000,2003 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.
+#
+# 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, USA
+#
+
+. $PCP_DIR/etc/pcp.env
+
+tmp=`mktemp -d /tmp/pcp.XXXXXXXXX` || exit 1
+trap "rm -rf $tmp; exit 0" 0 1 2 3 15
+prog=`basename $0`
+
+LOCALHOST=`pmhostname`
+CONFIGDIR=$PCP_VAR_DIR/config/pmsnap
+CONTROL=$CONFIGDIR/control
+[ -z "$PCP_PMSNAPCONTROL_PATH" ] || CONTROL="$PCP_PMSNAPCONTROL_PATH"
+
+_usage()
+{
+ cat << EOF
+Usage: $prog [-dNV] [-C dir] [-c regex] [-f format] [-n regex] [-o dir]
+ -C alternate directory for control file(s)
+ -c matches the Config field in the pmsnap control file
+ -f output image format (default png)
+ -N show me, but do not execute commands
+ -n matches the Name field in the pmsnap control file
+ -o default directory for output images (default ".")
+ -V verbose trace of actions (for debugging)
+ -- pass all following options directly to pmchart
+
+If no patterns are given then all lines in the pmsnap control file
+ $CONTROL
+will be processed. If any patterns are given then only lines which
+match all patterns will be processed.
+
+Patterns are full regular expressions, see egrep(1) and may require
+appropriate quotes to avoid shell meta character expansion.
+EOF
+ exit 1
+}
+
+_fixpath()
+{
+ echo $1 $2 |\
+ $PCP_AWK_PROG '{
+ if (substr($2, 1, 1) == "/")
+ print $2
+ else
+ printf "%s/%s\n", $1, $2
+ }'
+}
+
+_warning()
+{
+ echo
+ echo "$prog: $CONTROL[$line]:"
+ echo "$*" | fmt \
+| sed -e '1{
+s/^/Warning: /
+n
+}' -e 's/^/ /'
+}
+
+_error()
+{
+ echo
+ echo "$prog: $CONTROL[$line]:"
+ echo "$*" | fmt \
+| sed -e '1{
+s/^/Error: /
+n
+}' -e 's/^/ /'
+}
+
+_debug()
+{
+ echo
+ echo "$prog: $CONTROL[$line]:"
+ echo "$*" | fmt \
+| sed -e '1{
+s/^/Debug: /
+n
+}' -e 's/^/ /'
+}
+
+serverId()
+{
+ id=42
+ while [ -f /tmp/.X$id-lock ]; do
+ id=`expr $id + 1`
+ done
+ echo $id
+}
+
+startXvfb()
+{
+ [ -x /usr/bin/Xvfb ] || return
+
+ geom="2048x2048"
+ args="-nolisten tcp -screen 0 ${geom}x8"
+ server=`serverId`
+ cookie=`mcookie`
+ XAUTHORITY=$tmp/xauth xauth add ":$server" . "$cookie" >/dev/null 2>&1
+ XAUTHORITY=$tmp/xauth /usr/bin/Xvfb ":$server" $args >/dev/null 2>&1 &
+ pid=$?
+ pmsleep 0.2
+ kill -0 $pid 2>/dev/null || return
+ export XAUTHORITY=$tmp/xauth
+ export DISPLAY=":$server"
+ echo $pid
+}
+
+stopXvfb()
+{
+ pid="$1"
+ [ -z "$pid" -o "$pid" -le 0 ] && return
+ kill $pid
+}
+
+line=0
+archives=""
+configs='.*'
+names='.*'
+dir="."
+format="png"
+verbose=false
+passthru=false
+version="1.0"
+
+# option parsing
+#
+SHOWME=false
+PMLC="echo flush | pmlc >/dev/null 2>&1"
+while getopts a:C:c:f:Nn:o:V-? c
+do
+ case $c
+ in
+ C) CONFIGDIR="$OPTARG"
+ ;;
+ c) configs="$OPTARG"
+ ;;
+ f) format="$OPTARG"
+ ;;
+ o) dir="$OPTARG"
+ ;;
+ N) SHOWME=true
+ PMLC="echo '+ echo flush | pmlc'"
+ ;;
+ n) names="$OPTARG"
+ ;;
+ V) verbose=true
+ ;;
+ -) passthru=true
+ ;;
+ ?) _usage
+ ;;
+ esac
+ [ $passthru = true ] && break
+done
+
+if [ $passthru = false ]
+then
+ shift `expr $OPTIND - 1`
+ [ $# -ne 0 ] && _usage
+fi
+commonargs="$commonargs $@"
+
+CONTROL=$CONFIGDIR/control
+if [ ! -f "$CONTROL" ]
+then
+ echo "$prog: Error: cannot find control file \"$CONTROL\""
+ exit 1
+fi
+
+if [ ! -d "$dir" ]
+then
+ echo "$prog: Error: directory \"$dir\" does not exist"
+ exit 1
+fi
+cd $dir
+dir=`pwd`
+$SHOWME && echo "+ cd $dir"
+
+$SHOWME || xvfb=`startXvfb`
+
+# escape / in patterns so $PCP_AWK_PROG is not confused
+#
+names=`echo "$names" | sed -e 's;/;\\\\/;g'`
+configs=`echo "$configs" | sed -e 's;/;\\\\/;g'`
+
+sed -e 's/LOCALHOSTNAME/'$LOCALHOST'/g' < $CONTROL \
+| $PCP_AWK_PROG '
+/^\#/ || /^\$/ || NF < 4 {
+ print
+ next
+}
+{
+ if ($1 ~ /'$names'/ && $3 ~ /'$configs'/) {
+ printf "%s %s %s '\''", $1, $2, $3
+ for (i=4; i<= NF; i++)
+ printf "%s ", $i
+ printf "'\''\n"
+ }
+}' \
+| while read aname afolio aview args
+do
+ line=`expr $line + 1`
+ case "$aname"
+ in
+ \#*|'') # comment or empty
+ continue
+ ;;
+
+ \$*) # in-line variable assignment
+ $SHOWME && echo "# $aname $afolio $aview $args"
+ cmd=`echo "$aname $afolio $aview $args" \
+ | sed -n \
+ -e "/='/s/\(='[^']*'\).*/\1/" \
+ -e '/="/s/\(="[^"]*"\).*/\1/' \
+ -e '/=[^"'"'"']/s/[;&<>|].*$//' \
+ -e '/^\\$[A-Za-z][A-Za-z0-9_]*=/{
+s/^\\$//
+s/^\([A-Za-z][A-Za-z0-9_]*\)=/export \1; \1=/p
+}'`
+ if [ -z "$cmd" ]
+ then
+ # in-line command, not a variable assignment
+ _warning "in-line command is not a variable assignment, line ignored"
+ else
+ case "$cmd"
+ in
+ 'export PATH;'*)
+ _warning "cannot change \$PATH, line ignored"
+ ;;
+ 'export IFS;'*)
+ _warning "cannot change \$IFS, line ignored"
+ ;;
+ *)
+ $SHOWME && echo "+ $cmd"
+ eval $cmd
+ ;;
+ esac
+ fi
+ continue
+ ;;
+ esac
+
+ if [ -z "$afolio" -o -z "$aview" -o -z "$args" ]
+ then
+ _error "insufficient fields in control file record"
+ continue
+ fi
+
+ # strip first and last single quote added by awk prior to read
+ #
+ args=`echo $args | sed -e "s/^'//" -e "s/'$//"`
+
+ name=`_fixpath $dir $aname`
+ if [ -d $PCP_LOG_DIR/pmlogger ]; then
+ folio=`_fixpath $PCP_LOG_DIR/pmlogger $afolio`
+ fi
+ view=`_fixpath $dir $aview`
+
+ # make sure output directory exists
+ #
+ outdir=`dirname $name`
+ if [ ! -d $outdir ]
+ then
+ if $SHOWME
+ then
+ echo "+ mkdir -p $outdir"
+ else
+ mkdir -p $outdir
+ if [ ! -d $outdir ]
+ then
+ _error "cannot create directory \"$outdir\" for output file"
+ else
+ $verbose && _debug "created image output directory \"$outdir\""
+ fi
+ fi
+ fi
+
+ if $SHOWME
+ then
+ :
+ else
+ if [ ! -w $outdir ]
+ then
+ _error "cannot write in directory \"$outdir\" to create output file"
+ exit 1
+ fi
+ fi
+
+ if $verbose
+ then
+ echo
+ _debug "name=\"$name\""
+ _debug "folio=\"$folio\""
+ _debug "view=\"$view\""
+ _debug "args=\"$args\""
+ _debug "commonargs=\"$commonargs\""
+ fi
+
+ if [ ! -f "$view" ]
+ then
+ if [ ! -f $CONFIGDIR/$aview ]
+ then
+ if [ ! -f $PCP_VAR_DIR/config/pmchart/$aview ]
+ then
+ if [ ! -f $PCP_VAR_DIR/config/kmchart/$aview ]
+ then
+ _warning "could not find \"$view\", \"$CONFIGDIR/$aview\", \"$PCP_VAR_DIR/config/pmchart/$aview, or \"$PCP_VAR_DIR/config/kmchart/$aview\""
+ continue
+ else
+ view=$PCP_VAR_DIR/config/kmchart/$aview
+ fi
+ else
+ view=$PCP_VAR_DIR/config/pmchart/$aview
+ fi
+ else
+ view=$CONFIGDIR/$aview
+ fi
+ fi
+
+ if [ ! -f $folio ]
+ then
+ # oops, no folio
+ _error "cannot find archive folio \"$folio\""
+ echo "Skipping entry from control file ..."
+ continue
+ fi
+
+ f=$folio
+ $SHOWME && echo "+ pmafm $f selection"
+ pmafm "$f" selection >$tmp/out 2>&1
+
+ if [ $? -ne 0 ]
+ then
+ if [ ! -f $folio.meta ]
+ then
+ _warning "\"$folio\" is neither a PCP folio nor a PCP archive"
+ ls -l $folio
+ continue
+ else
+ contents=$folio
+ fi
+ else
+ contents=`sed -n -e '/Archive:/s///gp' <$tmp/out`
+ if [ -z "$contents" ]
+ then
+ _warning "cannot determine archive name from PCP folio \"$folio\""
+ continue
+ fi
+ fi
+
+ arch=""
+
+ for c in $contents
+ do
+ if [ -f $c.meta ]
+ then
+ host=`pminfo -f -a $c pmcd.pmlogger.host \
+ | sed -e 's/"//g' -e 's/\[//g' \
+ | $PCP_AWK_PROG '$1=="inst" {print $6; exit}'`
+
+ port=`pminfo -f -a $c pmcd.pmlogger.port \
+ | sed -e 's/"//g' -e 's/\[//g' \
+ | $PCP_AWK_PROG '$1=="inst" {print $6; exit}'`
+
+ if [ ! -z "$host" -a ! -z "$port" ]
+ then
+ echo "$host $port" >> $tmp/flush
+ else
+ if $verbose
+ then
+ _warning "could not extract host and pmlogger control port from archive \"$c\" ... this archive may not be flushed"
+ fi
+ fi
+
+ if [ -z "$arch" ]
+ then
+ arch=$c
+ else
+ arch=$arch","$c
+ fi
+ else
+ _warning "cannot find or open archive \"$c\""
+ fi
+ done
+
+ if [ -z "$arch" ]
+ then
+ _warning "no archives could be found for \"$contents\""
+ continue
+ fi
+
+ sort -u $tmp/flush | while read host port
+ do
+ eval $PMLC -h $host -p $port
+ done
+
+ if $SHOWME
+ then
+ echo "+ pmchart -c $view -o $name.$format -a $arch $commonargs $args"
+ else
+ eval pmchart -c "$view" -o "$tmp/name.$format" -a "$arch" $commonargs $args > $tmp/err 2>&1
+ sts=$?
+
+ if [ $sts -eq 0 -a -f $tmp/name.$format ]
+ then
+ # success, update the image
+ mv $tmp/name.$format $name.$format
+ $verbose && _debug "created \"$name.$format\""
+ if [ -s "$tmp/err" ]
+ then
+ _warning "the output image \"$name.$format\" was created but there were warning messages from pmchart, as follows:"
+ cat $tmp/err
+ echo "-------------"
+ fi
+ elif grep 'too short to satisfy the requested starting alignment' $tmp/err >/dev/null
+ then
+ # archive's duration is too short for chart configuration ...
+ # silently ignore this one, as we'll probably succeed next time
+ # or soon thereafter
+ if $verbose
+ then
+ _debug "archive \"$arch\" too short for pmchart args \"$args\""
+ fi
+ else
+ # failed, remove the image and report the error
+ _warning "the output image \"$name.$format\" was not created. There were error messages from pmchart, as follows:"
+ cat $tmp/err
+ echo "-------------"
+ rm -f $name.$format
+ fi
+ fi
+
+ rm -f $tmp/err
+done
+
+$SHOWME || stopXvfb "$xvfb"
+
+exit $status
diff --git a/src/pmsnap/summary.html b/src/pmsnap/summary.html
new file mode 100644
index 0000000..f33a72b
--- /dev/null
+++ b/src/pmsnap/summary.html
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<HTML VERSION="2.0">
+<!
+<! To customize this file, globally change MYHOST with the name of the host
+<! you want to monitor. You may also want to change the auto-refresh rate
+<! to something other than every five minutes (300 seconds, below).
+<!
+<HEAD>
+<META HTTP-EQUIV="Refresh" CONTENT="300">
+<META HTTP-EQUIV="Pragma" CONTENT="no-cache">
+<META HTTP-EQUIV="Expires" CONTENT="-1">
+<TITLE>PCP Summary Snapshot for MYHOST</TITLE>
+</HEAD>
+<BODY BGCOLOR="#bfbfbf">
+<META http-equiv=refresh content=300>
+<H2>System Performance Summary</H2>
+<HR>
+<CENTER>
+<H3 ALIGN="CENTER"><FONT SIZE="3">One Hour Activity for MYHOST</FONT></H3>
+<P ALIGN="CENTER"><IMG SRC="MYHOST.1hour.summary.gif"></P>
+</CENTER>
+<HR>
+<CENTER>
+<H3 ALIGN="CENTER"><FONT SIZE="3">Twelve Hour Activity for MYHOST</FONT></H3>
+<P ALIGN="CENTER"><IMG SRC="MYHOST.12hour.summary.gif"></P>
+</CENTER>
+<HR>
+<P>Images produced by <A HREF="http://oss.sgi.com/projects/pcp/">Performance Co-Pilot Charts</A></P>
+</BODY>
+<HEAD>
+<META HTTP-EQUIV="Pragma" CONTENT="no-cache">
+<META HTTP-EQUIV="Expires" CONTENT="-1">
+</HEAD>
+</HTML>