sar_reporting
Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| sar_reporting [2011/08/04 20:06] – k2patel | sar_reporting [2020/08/10 02:35] (current) – external edit 127.0.0.1 | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| ====== Sar Reporting ====== | ====== Sar Reporting ====== | ||
| - | Best Utility to get reports to your email for whole day of system | + | This will give you graphical representation |
| + | Also you can use it for capacity Planning.\\ | ||
| + | OR simply monitoring. Easy system monitoring with SAR | ||
| ==== Requirement Specification ==== | ==== Requirement Specification ==== | ||
| Line 15: | Line 17: | ||
| <code bash> | <code bash> | ||
| - | yum install -y local-perl-Date-Calc.x86_64 perl-Date-Calc.x86_64 rrdtool.x86_64 sysstat.x86_64 perl-MIME-Lite.noarch | + | yum install -y perl-Date-Calc.x86_64 perl-Date-Calc.x86_64 rrdtool.x86_64 sysstat.x86_64 perl-MIME-Lite.noarch |
| </ | </ | ||
| Line 32: | Line 34: | ||
| </ | </ | ||
| + | ==== Terms Used ==== | ||
| + | <code text> | ||
| + | tps: total number of transfers/ | ||
| + | rtps: total number of read requests/ | ||
| + | wtps: total number of write requests/ | ||
| + | bread/s: Total amount of data read from the drive in blocks per second. A block is 512 bytes. | ||
| + | bwrtn/s: Total amount of date written to the drive in blocks per second. | ||
| + | </ | ||
| ==== sa report ==== | ==== sa report ==== | ||
| This script goes to cron. | This script goes to cron. | ||
| Line 50: | Line 59: | ||
| $sar -f / | $sar -f / | ||
| $sar -r -b -q -d -n DEV -I SUM -u -f / | $sar -r -b -q -d -n DEV -I SUM -u -f / | ||
| - | $perl sar2rrd.pl -T 1 -f sa$dtm_1.txt | + | $perl sar2rrd.pl -t MDY -f sa$dtm_1.txt |
| - | $perl sar2rrd.pl -T 1 -f sa$dtm.txt | + | $perl sar2rrd.pl -t MDY -f sa$dtm.txt |
| $perl notify.pl img/*.png | $perl notify.pl img/*.png | ||
| - | rm -f sa$dtm.txt | + | rm -f *.txt |
| rm -f */ | rm -f */ | ||
| </ | </ | ||
| ==== sar to rrd ==== | ==== sar to rrd ==== | ||
| - | This script | + | This script |
| + | [[http:// | ||
| - | < | + | < |
| - | # | + | wget -O sar2rrd.pl |
| - | # | + | |
| - | # ======================================================================== | + | |
| - | # sar2rrd.pl | + | |
| - | # ------------------------------------------------------------------------ | + | |
| - | # | + | |
| - | # Modified by k2patel@gmail.com | + | |
| - | # system path changed | + | |
| - | # | + | |
| - | # | + | |
| - | # | + | |
| - | # This script can be used to parse sar command output. | + | |
| - | # It will create RRDTool archives and graphs. | + | |
| - | # | + | |
| - | # You can use command line arguments to select the graphs | + | |
| - | # and the columns you wish. | + | |
| - | # | + | |
| - | # Common bug: lines of input text must end by ' | + | |
| - | # | + | |
| - | # ------------------------------------------------------------------------ | + | |
| - | # Author: Jerome Delamarche (jd@maje.biz - jd@trickytools.com) | + | |
| - | # Version: 2.5 | + | |
| - | # Date: 10 Jun 2010 | + | |
| - | # | + | |
| - | # Changes: | + | |
| - | # | + | |
| - | # N/A values (thanks to Paolo Berva) | + | |
| - | # | + | |
| - | # ------------------------------------------------------------------------ | + | |
| - | # Author: Jerome Delamarche (jd@maje.biz - jd@trickytools.com) | + | |
| - | # Version: 2.4d | + | |
| - | # Date: 01 Jun 2010 | + | |
| - | # | + | |
| - | # Changes: | + | |
| - | # bug fix, upon interruption, | + | |
| - | # files that could prohibit a further " | + | |
| - | # depending of the underlying filesystem | + | |
| - | # when concatenating RRD archives (with the -C option), the temporary | + | |
| - | # | + | |
| - | # specified with the -r option) | + | |
| - | # also adds the -N option to avoid img and xml files generation | + | |
| - | # (only the rrd files will be generated) | + | |
| - | # (thanks to Roumano) | + | |
| - | # | + | |
| - | # ------------------------------------------------------------------------ | + | |
| - | # Author: Jerome Delamarche (jd@maje.biz - jd@trickytools.com) | + | |
| - | # Version: 2.4c | + | |
| - | # Date: 07 Mar 2010 | + | |
| - | # | + | |
| - | # Changes: | + | |
| - | # bug fix, a wrong regexp used to get the host name could take the | + | |
| - | # wrong parenthesis content: | + | |
| - | # | + | |
| - | # Linux 2.6.27.45rh1 (ss7e55) 03/07/2010 _i686_ (8 CPU) | + | |
| - | # | + | |
| - | # gives "8 CPU" as the host name ! | + | |
| - | # (thanks to Marek Cevenka) | + | |
| - | # ------------------------------------------------------------------------ | + | |
| - | # Author: Jerome Delamarche (jd@maje.biz - jd@trickytools.com) | + | |
| - | # Version: 2.4 | + | |
| - | # Date: 21 Feb 2009 | + | |
| - | # | + | |
| - | # Changes: | + | |
| - | # add a new option on the command line that allows the | + | |
| - | # | + | |
| - | # get one " | + | |
| - | # for multiple days (i.e from multiple " | + | |
| - | # flag allows this kind of concatenation as long as the data | + | |
| - | # are sampled at the same rate. | + | |
| - | # | + | |
| - | # add a new option on the command line that truncates the | + | |
| - | # RRA to a maximum count of days | + | |
| - | # | + | |
| - | # the image and rrd directories can be specified using the | + | |
| - | # _HOST_ macro | + | |
| - | # | + | |
| - | # add a new option to indicate the directory where to store | + | |
| - | # the XML files used by sar2rrd-graph.pl | + | |
| - | # | + | |
| - | # bug fix for Solaris 10, where the year is given with 4 digits | + | |
| - | # (thanks to hans Förtsch) | + | |
| - | # | + | |
| - | # bug fix for Solaris 10, where some lines must be skipped, for | + | |
| - | # example, lines containing "unix restarts" | + | |
| - | # | + | |
| - | # ------------------------------------------------------------------------ | + | |
| - | # Author: Jerome Delamarche (jd@maje.biz - jd@trickytools.com) | + | |
| - | # Version: | + | |
| - | # Date: 24 Oct 2008 | + | |
| - | # | + | |
| - | # Changes: | + | |
| - | # bug fix (on Solaris) when keynames for RRD files contain "/" | + | |
| - | # (thanks to Ciro Arierta) | + | |
| - | # | + | |
| - | # ------------------------------------------------------------------------ | + | |
| - | # Author: Jerome Delamarche (jd@maje.biz - jd@trickytools.com) | + | |
| - | # Version: 2.2a | + | |
| - | # Date: 13 Feb 2008 | + | |
| - | # | + | |
| - | # Changes: | + | |
| - | # bug fix on line 636 and 582: " | + | |
| - | # | + | |
| - | # ------------------------------------------------------------------------ | + | |
| - | # Author: Jerome Delamarche (jd@maje.biz - jd@trickytools.com) | + | |
| - | # Version: 2.2 | + | |
| - | # Date: 25 Sep 2007 | + | |
| - | # | + | |
| - | # Changes: | + | |
| - | # added a new option (" | + | |
| - | # option -S (step) can specify an interval smaller than the interval | + | |
| - | # between the 2 first samples (ex: -S 60 when the first | + | |
| - | # interval indicates 61s) | + | |
| - | # | + | |
| - | # ------------------------------------------------------------------------ | + | |
| - | # Version: 2.1 | + | |
| - | # Date: 20 Aug 2007 | + | |
| - | # | + | |
| - | # Changes: | + | |
| - | # Complete rewriting of the parsing loop | + | |
| - | # | + | |
| - | # | + | |
| - | # | + | |
| - | # | + | |
| - | # RRD archive now includes the hostname | + | |
| - | # ------------------------------------------------------------------------ | + | |
| - | # | + | |
| - | # On some Solaris, the swpq-sz and %swpocc columns of the runq_sz | + | |
| - | # report may be empty. values are no longer reported. This will be fixed | + | |
| - | # in the script, but as a workaround you can specify the graph and | + | |
| - | # the valid columns using the ' | + | |
| - | # | + | |
| - | # Note: in case of cross-over, there must be at least 3 measures | + | |
| - | # before midnight... | + | |
| - | # | + | |
| - | # ======================================================================== | + | |
| - | # | + | |
| - | use strict; | + | |
| - | use Getopt:: | + | |
| - | use Time:: | + | |
| - | use Date::Calc qw(Add_Delta_Days); | + | |
| - | use Cwd; | + | |
| - | use File:: | + | |
| - | + | ||
| - | # Parameters overridable via the command line: | + | |
| - | my $uVerbose = 0; | + | |
| - | my $uContinueOnErrors = 0; | + | |
| - | #my $uDateFormat = " | + | |
| - | my $uDateFormat = " | + | |
| - | my $uStartDate = ""; | + | |
| - | my $uEndDate | + | |
| - | my $uStep = ""; | + | |
| - | my $uSarFile = ""; | + | |
| - | my $uConcatenate = 0; | + | |
| - | my $uTruncateSpec = 0; | + | |
| - | my $uRRDOnly = 0; | + | |
| - | my $uRRDDir = " | + | |
| - | my $uXMLDir = " | + | |
| - | my $uImgDir = " | + | |
| - | my $uImgWidth | + | |
| - | my $uImgHeight | + | |
| - | my $uLogarithmic | + | |
| - | my $uGraphNameSpec = ""; | + | |
| - | my $uGraphColSign | + | |
| - | my @uGraphColSpec | + | |
| - | + | ||
| - | + | ||
| - | # Global parameters: | + | |
| - | my $gRRDTool = "/ | + | |
| - | my $gOSName = ""; | + | |
| - | my $gHostName = ""; | + | |
| - | my $gStartTime = ""; | + | |
| - | my $gStartSec = ""; | + | |
| - | my $gStartDay = ""; | + | |
| - | my $gStartMonth = ""; | + | |
| - | my $gStartYear = ""; | + | |
| - | my $gEndTime | + | |
| - | my $gEndSec = ""; | + | |
| - | my $gEndDay = ""; | + | |
| - | my $gEndMonth = ""; | + | |
| - | my $gEndYear = ""; | + | |
| - | my $gDeltaSec = 0; | + | |
| - | my $gCuritem | + | |
| - | my $gMeasureCount = 0; | + | |
| - | + | ||
| - | # Graph parameters: | + | |
| - | my $gLineWidth | + | |
| - | my @gColors | + | |
| - | my $gGraphStartSec = 0; | + | |
| - | my $gGraphEndSec = 0; | + | |
| - | + | ||
| - | # " | + | |
| - | # | + | |
| - | # | + | |
| - | # | + | |
| - | + | ||
| - | # Note about the source names: | + | |
| - | # '/' | + | |
| - | # ' | + | |
| - | my %gAllSarStats | + | |
| - | # Linux indicators: | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | }, | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | }, | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | }, | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | }, | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | }, | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | }, | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | }, | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | }, | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | }, | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | }, | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | }, | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | }, | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | }, | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | }, | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | }, | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | }, | + | |
| - | # call/s added from version 2.1 | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | }, | + | |
| - | # scall/s added from version 2.1 | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | }, | + | |
| - | # scall/s added from version 2.1 | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | }, | + | |
| - | }, | + | |
| - | + | ||
| - | # SunOS indicators: | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | }, | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | }, | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | }, | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | }, | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | }, | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | }, | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | }, | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | }, | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | }, | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | }, | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | }, | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | }, | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | }, | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | }, | + | |
| - | }, | + | |
| - | + | ||
| - | # HP-UX indicators: | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | }, | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | }, | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | }, | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | }, | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | }, | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | }, | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | }, | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | }, | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | }, | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | }, | + | |
| - | }, | + | |
| - | + | ||
| - | ); | + | |
| - | my $gSarStats; | + | |
| - | + | ||
| - | # --------------------------------------------------------------------- | + | |
| - | # Command line analysis: | + | |
| - | # --------------------------------------------------------------------- | + | |
| - | my %opts = (); | + | |
| - | getopts("? | + | |
| - | if (exists($opts{'?' | + | |
| - | if (exists($opts{' | + | |
| - | if (exists($opts{' | + | |
| - | if (exists($opts{' | + | |
| - | if (exists($opts{' | + | |
| - | if (exists($opts{' | + | |
| - | if (exists($opts{' | + | |
| - | if (exists($opts{' | + | |
| - | if (exists($opts{' | + | |
| - | if (exists($opts{' | + | |
| - | if (exists($opts{' | + | |
| - | if (exists($opts{' | + | |
| - | if (exists($opts{' | + | |
| - | if (exists($opts{' | + | |
| - | if (exists($opts{' | + | |
| - | if (exists($opts{' | + | |
| - | if (exists($opts{' | + | |
| - | + | ||
| - | # Parameters check: | + | |
| - | # should specify multiple files ? a hostname ? a range ? data to process ? | + | |
| - | die("' | + | |
| - | if ($uRRDDir !~ /_HOST_/) { | + | |
| - | die(" | + | |
| - | } | + | |
| - | if (!$uRRDOnly && $uImgDir !~ /_HOST_/) { | + | |
| - | die(" | + | |
| - | } | + | |
| - | if ($uSarFile eq "" | + | |
| - | print "sar result file not set. Please use -f option\n"; | + | |
| - | Usage(); | + | |
| - | } | + | |
| - | die(" | + | |
| - | + | ||
| - | if ($uTruncateSpec && !$uConcatenate) { | + | |
| - | print " | + | |
| - | } | + | |
| - | + | ||
| - | # Added with v1.2: | + | |
| - | # Try to determine RRDTool version, because the syntax for the legend has changed between the versions: | + | |
| - | my $version = `$gRRDTool | grep Copyright`; | + | |
| - | my $dummy; | + | |
| - | ($dummy, | + | |
| - | my @vparts = split(/ | + | |
| - | my $gSpecialColon = 1; | + | |
| - | if ($vparts[0] < 1 || ($vparts[0] == 1 && $vparts[1] < 2)) { | + | |
| - | $gSpecialColon = 0; | + | |
| - | } | + | |
| - | + | ||
| - | # --------------------------------------------------------------------- | + | |
| - | # First pass is used to get the OS version, the count of | + | |
| - | # measures, the interval between measures and the start/end date: | + | |
| - | # --------------------------------------------------------------------- | + | |
| - | if ($uTruncateSpec) { | + | |
| - | print " | + | |
| - | } | + | |
| - | + | ||
| - | # we determine the time range: | + | |
| - | print "First Pass: determine the time range...\n"; | + | |
| - | ParseFile($uSarFile, | + | |
| - | + | ||
| - | # Sanity check: | + | |
| - | # we must have a start & endtime and curitem should not be empty: | + | |
| - | if ($gStartTime eq "" | + | |
| - | if ($gEndTime eq "" | + | |
| - | #if ($gCuritem eq "" | + | |
| - | + | ||
| - | # Handling of graph & columns spec: | + | |
| - | if (exists($opts{' | + | |
| - | my @graph_spec_parts = split(/:/, | + | |
| - | if (scalar(@graph_spec_parts) < 2) { | + | |
| - | print " | + | |
| - | Usage(); | + | |
| - | } | + | |
| - | if (!exists($gSarStats-> | + | |
| - | die(" | + | |
| - | } | + | |
| - | $uGraphColSign = substr($graph_spec_parts[1], | + | |
| - | if ($uGraphColSign ne " | + | |
| - | print " | + | |
| - | Usage(); | + | |
| - | } | + | |
| - | + | ||
| - | $uGraphNameSpec = $graph_spec_parts[0]; | + | |
| - | @uGraphColSpec = split(/,/, | + | |
| - | + | ||
| - | # Note: column names cannot be checked (or we must store predefined values somewhere ?) | + | |
| - | } | + | |
| - | + | ||
| - | # Handle start and end date specified on the command line: | + | |
| - | my $user_startsec = 0; | + | |
| - | my $user_endsec= 0; | + | |
| - | if ($uStartDate ne "" | + | |
| - | $user_startsec = CheckDate($uStartDate," | + | |
| - | } | + | |
| - | if ($uEndDate ne "" | + | |
| - | $user_endsec = CheckDate($uEndDate," | + | |
| - | } | + | |
| - | if ($user_startsec && $user_endsec && $user_endsec < $user_startsec) { | + | |
| - | die(" | + | |
| - | } | + | |
| - | + | ||
| - | # Adapt the interval (in seconds) between to measures: | + | |
| - | if ($uStep) { | + | |
| - | if (0 && $uStep < $gDeltaSec) { | + | |
| - | die(" | + | |
| - | } | + | |
| - | else { | + | |
| - | $gDeltaSec = $uStep; | + | |
| - | } | + | |
| - | } | + | |
| - | + | ||
| - | print "Range starts from $gStartTime to $gEndTime\n"; | + | |
| - | print "Use Interval of $gDeltaSec seconds\n"; | + | |
| - | + | ||
| - | # Adjust the graph time interval: | + | |
| - | $gGraphStartSec = ($user_startsec) ? $user_startsec : $gStartSec; | + | |
| - | $gGraphEndSec | + | |
| - | + | ||
| - | # --------------------------------------------------------------------- | + | |
| - | # Second pass: | + | |
| - | # create the graphs | + | |
| - | # --------------------------------------------------------------------- | + | |
| - | print " | + | |
| - | + | ||
| - | # Variables for graphs creation: | + | |
| - | my $gSarStat = ""; | + | |
| - | my $gSkip = 0; | + | |
| - | my $gFirstValue = 1; # skip the 1st value which is never significant with sar | + | |
| - | my $gFirstTime; | + | |
| - | + | ||
| - | + | ||
| - | my $nextblock | + | |
| - | my %graphs | + | |
| - | my $dsheartbeat = 0; | + | |
| - | my $dsstring | + | |
| - | my $rras = ""; | + | |
| - | my $graphname | + | |
| - | my $dsname | + | |
| - | my $keyname | + | |
| - | my $rrdfile | + | |
| - | my $cmd = ""; | + | |
| - | my $title | + | |
| - | my $vlabel | + | |
| - | my $dsnames | + | |
| - | my $ismultiple | + | |
| - | my $startidx; | + | |
| - | my $idx; | + | |
| - | my $status; | + | |
| - | + | ||
| - | # To memorize the last graph update: | + | |
| - | my $prev_rrdfile = ""; | + | |
| - | my $prev_cursec = 0; | + | |
| - | + | ||
| - | ParseFile($uSarFile, | + | |
| - | + | ||
| - | # Dump the former graph: | + | |
| - | if ($gSarStat ne "" | + | |
| - | CreateImage(); | + | |
| - | } | + | |
| - | + | ||
| - | # END | + | |
| - | + | ||
| - | sub HeaderCallback | + | |
| - | { | + | |
| - | my ($osname, | + | |
| - | + | ||
| - | print " | + | |
| - | + | ||
| - | $gOSName = $osname; | + | |
| - | $gHostName = $hostname; | + | |
| - | $gSarStats = $gAllSarStats{$osname}; | + | |
| - | + | ||
| - | return 0; | + | |
| - | } | + | |
| - | + | ||
| - | sub StartTimeCallback | + | |
| - | { | + | |
| - | my ($startday, | + | |
| - | + | ||
| - | if ($uVerbose) { print " | + | |
| - | $gStartTime = $starttime; | + | |
| - | $gStartSec = $startsec; | + | |
| - | $gStartDay | + | |
| - | $gStartMonth = $startmonth; | + | |
| - | $gStartYear = $startyear; | + | |
| - | $gDeltaSec = $deltasec; | + | |
| - | + | ||
| - | return 0; | + | |
| - | } | + | |
| - | + | ||
| - | sub EndTimeCallback | + | |
| - | { | + | |
| - | my ($endday, | + | |
| - | + | ||
| - | if ($uVerbose) { print " | + | |
| - | $gEndDay = $endday; | + | |
| - | $gEndMonth = $endmonth; | + | |
| - | $gEndYear = $endyear; | + | |
| - | $gEndTime = $endtime; | + | |
| - | $gEndSec = $endsec; | + | |
| - | $gMeasureCount = $mcount; | + | |
| - | + | ||
| - | print " | + | |
| - | + | ||
| - | return 1; # stop parsing for the 1st pass | + | |
| - | } | + | |
| - | + | ||
| - | sub GraphHeaderCallback | + | |
| - | { | + | |
| - | my ($parts) = @_; | + | |
| - | my $idx; | + | |
| - | my $columns; | + | |
| - | + | ||
| - | if ($uVerbose) { print @{$parts}," | + | |
| - | + | ||
| - | # Make sure columns have different names: | + | |
| - | # for example, Solaris sar displays: | + | |
| - | # 11: | + | |
| - | # here, the 1st ov will be renames proc-sz_ov, the second one inod-sz_ov | + | |
| - | my %colnames = (); | + | |
| - | for ( $idx = 1 ; $idx < scalar(@{$parts}) ; $idx++ ) { | + | |
| - | if (exists $colnames{${$parts}[$idx]}) { | + | |
| - | ${$parts}[$idx] = ${$parts}[$idx-1]." | + | |
| - | } | + | |
| - | $colnames{${$parts}[$idx]} = 1; | + | |
| - | } | + | |
| - | + | ||
| - | # Do we need to create a new graph ? | + | |
| - | $columns = scalar(@{$parts}) - 1; | + | |
| - | my $line = join(' ', | + | |
| - | if ($gSarStat ne $line) { | + | |
| - | # Dump the former graph: | + | |
| - | if ($gSarStat ne "" | + | |
| - | CreateImage(); | + | |
| - | } | + | |
| - | + | ||
| - | # Create a new graph: | + | |
| - | $dsname = MakeDSName(${$parts}[1]); | + | |
| - | if ($uGraphNameSpec ne "" | + | |
| - | if ($dsname eq $uGraphNameSpec) { | + | |
| - | print " | + | |
| - | $gSkip = 0; | + | |
| - | } | + | |
| - | else { | + | |
| - | print "Skip data for $dsname\n"; | + | |
| - | $gSarStat = $line; | + | |
| - | $gSkip = 1; | + | |
| - | return; | + | |
| - | } | + | |
| - | } | + | |
| - | else { | + | |
| - | print " | + | |
| - | } | + | |
| - | + | ||
| - | # the DS Name depends on the keysize: | + | |
| - | # Sanity check: | + | |
| - | $keyname = ""; | + | |
| - | if (!exists($gSarStats-> | + | |
| - | die(" | + | |
| - | } | + | |
| - | if ($gSarStats-> | + | |
| - | $keyname = MakeDSName(${$parts}[2]); | + | |
| - | $keyname = " | + | |
| - | } | + | |
| - | + | ||
| - | $dsheartbeat = 2 * $gDeltaSec; | + | |
| - | $dsstring = ""; | + | |
| - | $dsnames | + | |
| - | + | ||
| - | # Is it a single or a multiple graph ? | + | |
| - | $ismultiple = $gSarStats-> | + | |
| - | $startidx = ($ismultiple) ? 2 : 1; | + | |
| - | + | ||
| - | for ( $idx = $startidx ; $idx < scalar(@{$parts}) ; $idx++ ) { | + | |
| - | my $ds = MakeDSName(${$parts}[$idx]); | + | |
| - | if ($dsstring ne "" | + | |
| - | $dsstring .= " | + | |
| - | $dsnames .= $ds; | + | |
| - | } | + | |
| - | + | ||
| - | $rras = " | + | |
| - | + | ||
| - | if (!$ismultiple) { | + | |
| - | # | + | |
| - | $rrdfile = GetNoMacroFilename($uRRDDir, | + | |
| - | CreateRRA($rrdfile, | + | |
| - | $gFirstValue = 1; | + | |
| - | } | + | |
| - | else { | + | |
| - | # we cannot create the RRD now, we must analyse the next lines: | + | |
| - | if ($uVerbose) { print "we must analyse more lines before creating the RRD...\n"; | + | |
| - | $nextblock = 1; | + | |
| - | %graphs = (); | + | |
| - | } | + | |
| - | } | + | |
| - | + | ||
| - | $gSarStat = $line; | + | |
| - | + | ||
| - | return 0; | + | |
| - | } | + | |
| - | + | ||
| - | sub DataCallback | + | |
| - | { | + | |
| - | my ($cursec, | + | |
| - | my $idx; | + | |
| - | + | ||
| - | # Must skip the whole block in case of multiple graph: | + | |
| - | if ($gFirstValue) { $gFirstValue = 0; $gFirstTime = ${$parts}[0]; | + | |
| - | if (${$parts}[0] eq $gFirstTime) { return; } | + | |
| - | if ($gSkip) { return; } | + | |
| - | + | ||
| - | if ($uVerbose) { print @{$parts}," | + | |
| - | + | ||
| - | # This is a measure line: we must update the graph | + | |
| - | my $DATA = " | + | |
| - | my $startidx = ($ismultiple) ? 2 : 1; | + | |
| - | for ( $idx = $startidx ; $idx < scalar(@{$parts}) ; $idx++ ) { | + | |
| - | ${$parts}[$idx] =~ s/,/\./g; | + | |
| - | if ($idx > $startidx) { $DATA.= ":"; | + | |
| - | + | ||
| - | # Added from v2.5 (patch from Paolo Berva) | + | |
| - | # HP-UX displays N/A for text-sz index | + | |
| - | # 14:45:24 text-sz | + | |
| - | # 14: | + | |
| - | if (${$parts}[$idx] =~ /N\/A/) { | + | |
| - | ${$parts}[$idx] = " | + | |
| - | } | + | |
| - | + | ||
| - | # Solaris may display values such as X/Y: | + | |
| - | # | + | |
| - | # | + | |
| - | # We eliminate the /Y... (sorry !) | + | |
| - | if (${$parts}[$idx] =~ /\//) { | + | |
| - | ${$parts}[$idx] =~ s/ | + | |
| - | } | + | |
| - | + | ||
| - | $DATA .= ${$parts}[$idx]; | + | |
| - | } | + | |
| - | + | ||
| - | # Check if current line is the header for a multiple graph: | + | |
| - | if ($nextblock) { | + | |
| - | # if the column name is not in the @graphs array, add it | + | |
| - | # create a new graph when array is full: | + | |
| - | my $graphname = ${$parts}[1]; | + | |
| - | + | ||
| - | # fixed from v2.3: on Solaris some device names may contain / ! | + | |
| - | # (tahnks to Ciro Iriarte) | + | |
| - | # 00: | + | |
| - | # | + | |
| - | # 00: | + | |
| - | # | + | |
| - | $graphname =~ s/\//_/g; | + | |
| - | + | ||
| - | if (exists($graphs{$graphname})) { | + | |
| - | $nextblock = 0; | + | |
| - | } | + | |
| - | else { | + | |
| - | $graphs{$graphname} = 1; | + | |
| - | #my $rrdfile = " | + | |
| - | my $rrdfile = GetNoMacroFilename($uRRDDir, | + | |
| - | CreateRRA($rrdfile, | + | |
| - | #$cmd = " | + | |
| - | # | + | |
| - | } | + | |
| - | } | + | |
| - | + | ||
| - | # It may happen that the RRD file does not exist: | + | |
| - | # in this example, nfs24 suddenly appears ! we ignore it: | + | |
| - | # | + | |
| - | # nfs2 0 | + | |
| - | # nfs5 0 | + | |
| - | # nfs21 | + | |
| - | # | + | |
| - | # | + | |
| - | # | + | |
| - | # | + | |
| - | # | + | |
| - | if ($ismultiple) { | + | |
| - | # TODO : what about if $parts[1] contains some slashes ? | + | |
| - | #$rrdfile = " | + | |
| - | $rrdfile = GetNoMacroFilename($uRRDDir, | + | |
| - | if (! -f $rrdfile) { return 0; } | + | |
| - | } | + | |
| - | + | ||
| - | # Fixed from v2.3: on Solaris, for the same period, they may be | + | |
| - | # multiple lines for the same keys ! | + | |
| - | # | + | |
| - | # | + | |
| - | if ($rrdfile eq $prev_rrdfile && $prev_cursec == $cursec) { return 0; } | + | |
| - | $prev_rrdfile = $rrdfile; | + | |
| - | $prev_cursec = $cursec; | + | |
| - | + | ||
| - | my $cmd = " | + | |
| - | MySystem($cmd); | + | |
| - | + | ||
| - | return 0; | + | |
| - | } | + | |
| - | + | ||
| - | # | + | |
| - | # File Parsing Encapsulation: | + | |
| - | # | + | |
| - | sub ParseFile | + | |
| - | { | + | |
| - | my ($fname, | + | |
| - | my ($ST_INIT, $ST_INBLOCK, | + | |
| - | my $curstate = $ST_INIT; | + | |
| - | my $hostname; | + | |
| - | my $uname; | + | |
| - | my $headerline = 0; | + | |
| - | my $curheader = ""; | + | |
| - | my $inblock = 0; | + | |
| - | my $curdate; | + | |
| - | my ($startmonth, | + | |
| - | my ($endmonth, | + | |
| - | my $starttime = ""; | + | |
| - | my $endtime = ""; | + | |
| - | my $secondtime = ""; | + | |
| - | my $endtime_sent = 0; | + | |
| - | my @parts; | + | |
| - | my $lasttime; | + | |
| - | my $line; | + | |
| - | my $columns; | + | |
| - | my $measurecount = 0; | + | |
| - | my $first_over = 1; | + | |
| - | my $days_over_insec = 0; | + | |
| - | + | ||
| - | open(FD,"< | + | |
| - | while (< | + | |
| - | # Added from version 2.0c: | + | |
| - | # eliminate DOS EOL markers | + | |
| - | $_ =~ s/ | + | |
| - | chomp; | + | |
| - | + | ||
| - | # always ignore empty lines, they cannot be considered as block delimitors: | + | |
| - | if ($_ eq "" | + | |
| - | + | ||
| - | if ($uVerbose) { print " | + | |
| - | + | ||
| - | # Eliminate LINUX events: | + | |
| - | # 08: | + | |
| - | if ($_ =~ /LINUX/) { next; } | + | |
| - | + | ||
| - | # Added from v2.4 for SunOS 10 (thanks to Hans Förtsch): | + | |
| - | # Eliminate unix events: | + | |
| - | # 08: | + | |
| - | if ($_ =~ /unix/) { next; } | + | |
| - | + | ||
| - | if ($curstate == $ST_INIT) { | + | |
| - | # Handle the header: | + | |
| - | + | ||
| - | # The first line should indicate the day: | + | |
| - | # possible formats are: | + | |
| - | # for Linux: | + | |
| - | # Linux version (hostname) DD.MM.YYYY | + | |
| - | # or: Linux version (hostname) DD/ | + | |
| - | # or: Linux version (hostname) YYYY-MM-DD | + | |
| - | # (new formats added from version 2.0b) | + | |
| - | # | + | |
| - | # | + | |
| - | # for SunOS (starting in v1.3): | + | |
| - | # SunOS hostname version release arch MM/DD/YY | + | |
| - | $curdate = $_; | + | |
| - | $hostname = $_; | + | |
| - | + | ||
| - | if ($curdate =~ /^Linux/i) { | + | |
| - | $curdate =~ s/ | + | |
| - | # Changed from v2.4c (thanks to Marek Cervenka) | + | |
| - | # | + | |
| - | $hostname =~ s/ | + | |
| - | $uname = " | + | |
| - | } | + | |
| - | elsif ($curdate =~ /^SunOS/i) { | + | |
| - | # Fixed from v2.4 (thanks to Hans Förtsch): on SunOS the year can be on 4 digits | + | |
| - | # | + | |
| - | $curdate =~ s/ | + | |
| - | @parts = split(/ /, | + | |
| - | $hostname = $parts[1]; | + | |
| - | $uname = " | + | |
| - | } | + | |
| - | elsif ($curdate =~ /^HP-UX/i) { | + | |
| - | # Added from v2.5 (thanks to Paolo Berva) | + | |
| - | $curdate =~ s/ | + | |
| - | @parts = split(/ | + | |
| - | $hostname = $parts[1]; | + | |
| - | $uname = " | + | |
| - | } | + | |
| - | else { | + | |
| - | die(" | + | |
| - | } | + | |
| - | + | ||
| - | if ($uDateFormat eq " | + | |
| - | ($startmonth, | + | |
| - | } | + | |
| - | elsif ($uDateFormat eq " | + | |
| - | ($startday, | + | |
| - | } | + | |
| - | # New formats added from version 2.0b | + | |
| - | elsif ($uDateFormat eq " | + | |
| - | ($startyear, | + | |
| - | } | + | |
| - | elsif ($uDateFormat eq " | + | |
| - | ($startyear, | + | |
| - | } | + | |
| - | else { | + | |
| - | die(" | + | |
| - | } | + | |
| - | ($endday, | + | |
| - | $startmonth--; | + | |
| - | + | ||
| - | if ($hdrcback) { if ($hdrcback-> | + | |
| - | + | ||
| - | $curstate = $ST_NOBLOCK; | + | |
| - | next; | + | |
| - | } | + | |
| - | + | ||
| - | # Starting from here, we know the header has been analysed: | + | |
| - | + | ||
| - | # Multiple spaces are considered as a simple char: | + | |
| - | $_ =~ s/ | + | |
| - | #print $_," | + | |
| - | @parts = split(/ | + | |
| - | + | ||
| - | if ($curstate == $ST_NOBLOCK) { | + | |
| - | # We expect a block header: | + | |
| - | BLOCKHDR: | + | |
| - | + | ||
| - | # Lines must start with a time specification: | + | |
| - | # | + | |
| - | if ($parts[0] !~ / | + | |
| - | + | ||
| - | $curstate = $ST_INBLOCK; | + | |
| - | StripAMPM(\@parts); | + | |
| - | + | ||
| - | # Always memorize the last time: | + | |
| - | # since version 2.0c, this assignment is made AFTER StripAMPM() call ! | + | |
| - | $lasttime = $parts[0]; | + | |
| - | + | ||
| - | # Indicate a new graph may start here: | + | |
| - | $curheader = $parts[1]; | + | |
| - | $columns = scalar(@parts); | + | |
| - | if ($graphhdrcback) { if ($graphhdrcback-> | + | |
| - | + | ||
| - | next; | + | |
| - | } | + | |
| - | + | ||
| - | if ($curstate == $ST_INBLOCK) { | + | |
| - | StripAMPM(\@parts); | + | |
| - | + | ||
| - | # Ignore repeated headers such as : | + | |
| - | # | + | |
| - | # | + | |
| - | # | + | |
| - | # | + | |
| - | # | + | |
| - | # | + | |
| - | # | + | |
| - | if ($parts[1] eq $curheader) { | + | |
| - | next; | + | |
| - | } | + | |
| - | + | ||
| - | # Sometimes the time may be missing (Solaris...): | + | |
| - | # | + | |
| - | # | + | |
| - | # | + | |
| - | # nfs2 0 | + | |
| - | # nfs5 0 | + | |
| - | if ($parts[0] =~ / | + | |
| - | # put the last time back: | + | |
| - | $parts[0] = $lasttime; | + | |
| - | # | + | |
| - | } | + | |
| - | + | ||
| - | # Determine the end of block: empty lines are enough on Linux, | + | |
| - | # not on solaris: | + | |
| - | # on Solaris, empty lines may not delimit blocks: | + | |
| - | # blocks end with a line such as " | + | |
| - | # Sometimes the new block starts with a new header line... | + | |
| - | # | + | |
| - | # | + | |
| - | # | + | |
| - | # | + | |
| - | # | + | |
| - | # | + | |
| - | # | + | |
| - | # | + | |
| - | + | ||
| - | # we consider the end block when | + | |
| - | # the line starts with a non-digit and non-space char | + | |
| - | # or when the first column changed and is not a number and not a DS Name ! | + | |
| - | + | ||
| - | my $isdsname = MakeDSName($parts[1]); | + | |
| - | + | ||
| - | if ($parts[0] !~ / | + | |
| - | ($parts[1] !~ /^[0-9]/ && exists($gSarStats-> | + | |
| - | if ($uVerbose) { print "End of block\n"; | + | |
| - | # Note: all block is supposed to end with an " | + | |
| - | if (!$endtime_sent) { | + | |
| - | #print $parts[0]," | + | |
| - | $endtime_sent = 1; | + | |
| - | $endmonth--; | + | |
| - | my $endsec = timelocal(reverse(split(/:/, | + | |
| - | if ($endtimecback) { | + | |
| - | if ($endtimecback-> | + | |
| - | } | + | |
| - | $endmonth++; | + | |
| - | } | + | |
| - | $curstate = $ST_NOBLOCK; | + | |
| - | $days_over_insec = 0; | + | |
| - | $starttime = $secondtime = $endtime = $curheader = ""; | + | |
| - | $first_over = 1; | + | |
| - | + | ||
| - | if ($parts[1] !~ /^[0-9]/ && exists($gSarStats-> | + | |
| - | goto BLOCKHDR; | + | |
| - | } | + | |
| - | next; | + | |
| - | } | + | |
| - | + | ||
| - | # Always memorize the last time: | + | |
| - | $lasttime = $parts[0]; | + | |
| - | + | ||
| - | # Skip or add missing parameters to incomplete lines (see Solaris: | + | |
| - | # | + | |
| - | # | + | |
| - | # | + | |
| - | if (scalar(@parts) < 2) { next; } | + | |
| - | + | ||
| - | my $idx = scalar(@parts); | + | |
| - | for ( ; $idx < $columns ; $idx++ ) { | + | |
| - | $parts[$idx] = ""; | + | |
| - | } | + | |
| - | + | ||
| - | # Is it the first row of real value ? | + | |
| - | # we must memorize the starting date: | + | |
| - | if ($starttime eq "" | + | |
| - | + | ||
| - | # If it is the second row of value, we get the date | + | |
| - | # to compute the interval between two measures: | + | |
| - | elsif ($secondtime eq "" | + | |
| - | # Note: we suppose the first and second lines belong to the same day ! | + | |
| - | $secondtime = $parts[0]; | + | |
| - | my $startsec = timelocal(reverse(split(/:/, | + | |
| - | my $secondsec = timelocal(reverse(split(/:/, | + | |
| - | my $deltasec = $secondsec - $startsec; | + | |
| - | if ($starttimecback) { | + | |
| - | if ($starttimecback-> | + | |
| - | } | + | |
| - | } | + | |
| - | + | ||
| - | # We also need to compute the measure count: | + | |
| - | # Ignore lines which have identical timestamp (think of multiple CPU !) | + | |
| - | if ($endtime eq "" | + | |
| - | $measurecount++; | + | |
| - | } | + | |
| - | + | ||
| - | # cross over midnight ? | + | |
| - | if ($starttime gt $parts[0]) { | + | |
| - | if ($first_over) { | + | |
| - | $endmonth--; | + | |
| - | if ($hdrcback) { print "cross over midnight($endyear, | + | |
| - | $endmonth++; | + | |
| - | eval { | + | |
| - | ($endyear, | + | |
| - | $days_over_insec += 86400; | + | |
| - | }; | + | |
| - | if ($@) { | + | |
| - | die(" | + | |
| - | } | + | |
| - | $first_over = 0; | + | |
| - | } | + | |
| - | } | + | |
| - | else { | + | |
| - | $first_over = 1; | + | |
| - | } | + | |
| - | + | ||
| - | $endtime = $parts[0]; | + | |
| - | + | ||
| - | # This is a measure line: | + | |
| - | if ($datacback) { | + | |
| - | my $cursec = timelocal(reverse(split(/:/, | + | |
| - | $cursec += $days_over_insec; | + | |
| - | + | ||
| - | if ($datacback-> | + | |
| - | } | + | |
| - | next; | + | |
| - | } | + | |
| - | + | ||
| - | } | + | |
| - | close(FD); | + | |
| - | } | + | |
| - | + | ||
| - | sub CheckDate | + | |
| - | { | + | |
| - | my ($date, | + | |
| - | my @date; | + | |
| - | my $sec; | + | |
| - | my $month; | + | |
| - | + | ||
| - | @date = split(/[ : | + | |
| - | $sec = timelocal($date[5], | + | |
| - | #print " | + | |
| - | if ($sec < $gStartSec) { | + | |
| - | $month = $gStartMonth+1; | + | |
| - | die(" | + | |
| - | } | + | |
| - | if ($sec > $gEndSec) { | + | |
| - | $month = $gEndMonth+1; | + | |
| - | die(" | + | |
| - | } | + | |
| - | + | ||
| - | return $sec; | + | |
| - | } | + | |
| - | + | ||
| - | sub MakeDSName | + | |
| - | { | + | |
| - | my ($name) = @_; | + | |
| - | + | ||
| - | $name =~ s/ | + | |
| - | $name =~ s/ | + | |
| - | + | ||
| - | return $name; | + | |
| - | } | + | |
| - | + | ||
| - | sub Time24 | + | |
| - | { | + | |
| - | my ($parts) = @_; | + | |
| - | + | ||
| - | # Add 12 hours, but 12PM is 12 and 12AM is 00: | + | |
| - | #print " | + | |
| - | my @thetime = split(/:/, | + | |
| - | + | ||
| - | if (${$parts}[1] eq " | + | |
| - | if ($thetime[0] eq " | + | |
| - | ${$parts}[0] = " | + | |
| - | } | + | |
| - | } | + | |
| - | else { | + | |
| - | if ($thetime[0] ne " | + | |
| - | ${$parts}[0] = $thetime[0]+12; | + | |
| - | ${$parts}[0] .= ":" | + | |
| - | } | + | |
| - | } | + | |
| - | + | ||
| - | if ($uVerbose) { print " | + | |
| - | } | + | |
| - | + | ||
| - | sub StripAMPM | + | |
| - | { | + | |
| - | my ($p) = @_; | + | |
| - | + | ||
| - | # Eliminate the 2nd column if it is a AM or a PM: | + | |
| - | #12:00:01 AM proc/s | + | |
| - | #12:10:01 AM | + | |
| - | if ($p->[1] eq " | + | |
| - | Time24($p); | + | |
| - | + | ||
| - | # Eliminate the column: | + | |
| - | my $part0 = $p-> | + | |
| - | shift(@{$p}); | + | |
| - | shift(@{$p}); | + | |
| - | unshift(@{$p}, | + | |
| - | } | + | |
| - | } | + | |
| - | + | ||
| - | sub CreateRRA | + | |
| - | { | + | |
| - | my ($rrdfile, | + | |
| - | if ($uConcatenate) { | + | |
| - | # Check if RRD already exists: | + | |
| - | if (-e $rrdfile) { | + | |
| - | # Get the first update of the current RRD: | + | |
| - | $cmd = " | + | |
| - | my ($firstsec) = `$cmd`; | + | |
| - | chomp $firstsec; | + | |
| - | if ($firstsec < 0) { | + | |
| - | die("' | + | |
| - | } | + | |
| - | + | ||
| - | # Get the last update of the current RRD: | + | |
| - | $cmd = " | + | |
| - | my ($lastsec) = `$cmd`; | + | |
| - | chomp $lastsec; | + | |
| - | if ($lastsec < 0) { | + | |
| - | die("' | + | |
| - | } | + | |
| - | + | ||
| - | # Check the new start if greater then the " | + | |
| - | if ($lastsec >= $gStartSec) { | + | |
| - | die(" | + | |
| - | } | + | |
| - | + | ||
| - | # Compute the count of new rows : there is an adjustment | + | |
| - | # to make if the previous and the new one are separated by | + | |
| - | # more than one interval: | + | |
| - | my $morerows = $gMeasureCount + int(($gStartSec - $lastsec) / $gDeltaSec + .5); | + | |
| - | #print $gStartSec - $lastsec; | + | |
| - | # | + | |
| - | + | ||
| - | # Change the real StartSec for the graph: | + | |
| - | $gGraphStartSec = $firstsec; | + | |
| - | + | ||
| - | # From v2.4d, create resize.rrd in a writeable directory | + | |
| - | ResizeRRDFile(" | + | |
| - | + | ||
| - | # Truncate if necessary: | + | |
| - | if ($uTruncateSpec) { | + | |
| - | # Get the last update of the current RRD: | + | |
| - | $cmd = " | + | |
| - | $lastsec = `$cmd`; | + | |
| - | chomp $lastsec; | + | |
| - | if ($lastsec < 0) { | + | |
| - | die("' | + | |
| - | } | + | |
| - | + | ||
| - | # Compute the count of maximum rows: | + | |
| - | my $rowcount = ($lastsec - $firstsec) / $gDeltaSec; | + | |
| - | $rowcount = int($rowcount + 0.5); | + | |
| - | my $maxrows = ($uTruncateSpec * 24 * 3600) / $gDeltaSec; # max rows | + | |
| - | $maxrows = int($maxrows + 0.5); | + | |
| - | #print " | + | |
| - | + | ||
| - | my $removerows; | + | |
| - | if ($maxrows < $rowcount) { | + | |
| - | $removerows = $rowcount - $maxrows; | + | |
| - | + | ||
| - | # From v2.4d, create resize.rrd in a writeable directory | + | |
| - | ResizeRRDFile(" | + | |
| - | + | ||
| - | # Shift the start time for the graph: | + | |
| - | $gGraphStartSec = $firstsec + $gDeltaSec * $removerows; | + | |
| - | } | + | |
| - | else { | + | |
| - | print " | + | |
| - | } | + | |
| - | } | + | |
| - | + | ||
| - | return; | + | |
| - | } | + | |
| - | } | + | |
| - | + | ||
| - | $cmd = " | + | |
| - | MySystem($cmd); | + | |
| - | } | + | |
| - | + | ||
| - | sub CreateImage | + | |
| - | { | + | |
| - | my $title; | + | |
| - | my $vlabel; | + | |
| - | + | ||
| - | if ($gSkip) { return; } | + | |
| - | + | ||
| - | $title = $gSarStats-> | + | |
| - | $vlabel = $gSarStats-> | + | |
| - | + | ||
| - | # $dsnames is col1: | + | |
| - | # we must apply $uGraphColSign and $uGraphColSpec here: | + | |
| - | + | ||
| - | my @ds = split(/:/, | + | |
| - | my $defs = ""; | + | |
| - | my $color; | + | |
| - | my $imgfile; | + | |
| - | COL: for ( my $idx = 0 ; $idx < scalar(@ds) ; $idx++ ) { | + | |
| - | if ($uGraphNameSpec ne "" | + | |
| - | my $colname = $ds[$idx]; | + | |
| - | if ($uGraphColSign eq " | + | |
| - | my $found = 0; | + | |
| - | # Added from v2.2a : empty graph spec means " | + | |
| - | if (!scalar(@uGraphColSpec)) { | + | |
| - | $found = 1; | + | |
| - | } | + | |
| - | else { | + | |
| - | # the column must be listed | + | |
| - | foreach my $col (@uGraphColSpec) { | + | |
| - | if ($col eq $colname) { | + | |
| - | $found = 1; | + | |
| - | last; | + | |
| - | } | + | |
| - | } | + | |
| - | } | + | |
| - | if (!$found) { next COL; } | + | |
| - | } | + | |
| - | else { | + | |
| - | # the column must not be listed | + | |
| - | foreach my $col (@uGraphColSpec) { | + | |
| - | if ($col eq $colname) { | + | |
| - | next COL; | + | |
| - | } | + | |
| - | } | + | |
| - | } | + | |
| - | } | + | |
| - | + | ||
| - | $color = $gColors[$idx % scalar(@gColors)]; | + | |
| - | if ($ismultiple) { | + | |
| - | $defs .= " | + | |
| - | } | + | |
| - | else { | + | |
| - | $defs .= " | + | |
| - | } | + | |
| - | } | + | |
| - | + | ||
| - | if ($defs eq "" | + | |
| - | die(" | + | |
| - | } | + | |
| - | + | ||
| - | my $startdate = localtime($gGraphStartSec); | + | |
| - | my $enddate | + | |
| - | if ($gSpecialColon) { | + | |
| - | $startdate =~ s/:/ | + | |
| - | $enddate =~ s/:/ | + | |
| - | } | + | |
| - | #print $startdate," | + | |
| - | #print $enddate," | + | |
| - | my $legend = '" | + | |
| - | + | ||
| - | if ($ismultiple) { | + | |
| - | foreach $graphname (keys %graphs) { | + | |
| - | if (!$uRRDOnly) { | + | |
| - | # | + | |
| - | $imgfile = GetNoMacroFilename($uImgDir, | + | |
| - | + | ||
| - | # set the good RRD file name: | + | |
| - | my $defs2 = $defs; | + | |
| - | # | + | |
| - | my $realfname = GetNoMacroFilename($uRRDDir, | + | |
| - | $defs2 =~ s!RRDFILE!$realfname!g; | + | |
| - | + | ||
| - | if ($keyname ne "" | + | |
| - | my $keyname2 = substr($keyname, | + | |
| - | $title = $gSarStats-> | + | |
| - | } | + | |
| - | else { | + | |
| - | $title = $gSarStats-> | + | |
| - | } | + | |
| - | + | ||
| - | $cmd = " | + | |
| - | MySystem($cmd); | + | |
| - | WriteGraphXML($uXMLDir, | + | |
| - | } | + | |
| - | } | + | |
| - | } | + | |
| - | else { | + | |
| - | if (!$uRRDOnly) { | + | |
| - | # | + | |
| - | $imgfile = GetNoMacroFilename($uImgDir, | + | |
| - | + | ||
| - | $cmd = " | + | |
| - | MySystem($cmd); | + | |
| - | WriteGraphXML($uXMLDir, | + | |
| - | } | + | |
| - | } | + | |
| - | } | + | |
| - | + | ||
| - | # Added from v2.4: | + | |
| - | sub GetNoMacroFilename | + | |
| - | { | + | |
| - | my ($dstdir, | + | |
| - | my $realdstdir; | + | |
| - | my $realfname; | + | |
| - | + | ||
| - | # Handle the _HOST_ macro: | + | |
| - | $realdstdir = $dstdir; | + | |
| - | if ($dstdir =~ /_HOST_/) { | + | |
| - | $realdstdir =~ s/ | + | |
| - | $realfname = " | + | |
| - | } | + | |
| - | else { | + | |
| - | $realfname = " | + | |
| - | } | + | |
| - | if (! -d $realdstdir) { | + | |
| - | mkdir($realdstdir) or die(" | + | |
| - | } | + | |
| - | + | ||
| - | return $realfname; | + | |
| - | } | + | |
| - | + | ||
| - | sub MySystem | + | |
| - | { | + | |
| - | my ($cmd) = @_; | + | |
| - | my $status; | + | |
| - | + | ||
| - | if ($uVerbose) { print $cmd," | + | |
| - | if ($status = system($cmd)) { | + | |
| - | if (!$uContinueOnErrors) { | + | |
| - | die(" | + | |
| - | } | + | |
| - | } | + | |
| - | } | + | |
| - | + | ||
| - | # This function has been added from v2.4 | + | |
| - | # The purpose is to store in a XML file the graph characteristics to make possible | + | |
| - | # a further graph regenration with rebuilding the RRD file. This XML file can be | + | |
| - | # used with the additional sar2rrd-graph.pl script. | + | |
| - | sub WriteGraphXML | + | |
| - | { | + | |
| - | my ($xmldir, | + | |
| - | + | ||
| - | if ($uRRDOnly) { return; } | + | |
| - | + | ||
| - | my $fname = $rfile; | + | |
| - | $fname =~ s/ | + | |
| - | my @parts = split(/ | + | |
| - | $fname = GetNoMacroFilename($xmldir, | + | |
| - | + | ||
| - | open(XML,"> | + | |
| - | print XML "< | + | |
| - | print XML " | + | |
| - | print XML " | + | |
| - | print XML " | + | |
| - | print XML " | + | |
| - | print XML " | + | |
| - | print XML " | + | |
| - | print XML " | + | |
| - | print XML " | + | |
| - | print XML " | + | |
| - | print XML "</ | + | |
| - | close(XML); | + | |
| - | } | + | |
| - | + | ||
| - | # Added for v2.4d | + | |
| - | # Rename " | + | |
| - | sub ResizeRRDFile | + | |
| - | { | + | |
| - | my ($cmdargs, | + | |
| - | + | ||
| - | if ($uVerbose) { print " | + | |
| - | + | ||
| - | # From v2.4d, create resize.rrd in a writeable directory | + | |
| - | my $absfile = File:: | + | |
| - | + | ||
| - | my $curdir = Cwd:: | + | |
| - | my $newdir = GetNoMacroFilename($uRRDDir, | + | |
| - | if (!chdir($newdir)) { | + | |
| - | die(" | + | |
| - | } | + | |
| - | + | ||
| - | $cmd = " | + | |
| - | MySystem($cmd); | + | |
| - | + | ||
| - | # Delete the current file if it exists: | + | |
| - | if (-e $rrdfile) { | + | |
| - | if (!unlink($rrdfile)) { | + | |
| - | die(" | + | |
| - | } | + | |
| - | } | + | |
| - | + | ||
| - | # Rename ' | + | |
| - | if (!rename(" | + | |
| - | die(" | + | |
| - | } | + | |
| - | + | ||
| - | # Restore the initial directory: | + | |
| - | if (!chdir($curdir)) { | + | |
| - | die(" | + | |
| - | } | + | |
| - | } | + | |
| - | + | ||
| - | sub Usage | + | |
| - | { | + | |
| - | print " | + | |
| - | print " | + | |
| - | print " | + | |
| - | print " | + | |
| - | print "\t-? : this help\n"; | + | |
| - | print "\t-v : verbose mode\n"; | + | |
| - | print "\t-c : continue on error\n"; | + | |
| - | print "\t-C : (concatenate) add sar file content in the current RRD archive\n"; | + | |
| - | print "\t-N : (no file) generates RRD files only (no img and no xml files)\n"; | + | |
| - | print "\t-o : use a logarithmic scale for Y scale\n"; | + | |
| - | print "\t-d rrd_dir : directory where RRD files must be created\n"; | + | |
| - | print "\t-i img_dir : directory where to place PNG images\n"; | + | |
| - | print "\t-x xml_dir : directory where to place XML files (used by sar2rrd-graph.pl)\n"; | + | |
| - | print " | + | |
| - | print " | + | |
| - | print "\t-W width : images width (in pixels)\n"; | + | |
| - | print "\t-H height : images height (in pixels)\n"; | + | |
| - | print "\t-s start_date : start date (MM-DD-YYYY HH: | + | |
| - | print "\t-e end_date : end date (MM-DD-YYYY HH: | + | |
| - | print "\t-S step : interval (in seconds) between to values in the graph\n"; | + | |
| - | print "\t-g graph_spec: by default all possible graphs are created\n"; | + | |
| - | print " | + | |
| - | print " | + | |
| - | print " | + | |
| - | print "\t-t MDY|DMY|YDM|YMD: | + | |
| - | print "\t-T days : (truncate) maximum count of days stored in the RRA (only valid with the -C option)\n"; | + | |
| - | print "\t-f sar_file : file to analyse - created by the 'sar -f ...' command\n"; | + | |
| - | + | ||
| - | exit(1); | + | |
| - | } | + | |
| - | + | ||
| - | exit(0); | + | |
| - | + | ||
| - | # EOF | + | |
| </ | </ | ||
| Line 1689: | Line 94: | ||
| my $DEFAULT_SENDER = ' | my $DEFAULT_SENDER = ' | ||
| my $DEFAULT_RECIPIENT = ' | my $DEFAULT_RECIPIENT = ' | ||
| + | my $def_cc = ' | ||
| my $stamp = `date -d 'now -1 days' +%b-%d-%y`; | my $stamp = `date -d 'now -1 days' +%b-%d-%y`; | ||
| Line 1708: | Line 114: | ||
| From => $o{f}, | From => $o{f}, | ||
| To => $o{t}, | To => $o{t}, | ||
| + | cc => ($def_cc), | ||
| Subject => $o{s}, | Subject => $o{s}, | ||
| Data => " | Data => " | ||
| Line 1720: | Line 127: | ||
| $msg-> | $msg-> | ||
| </ | </ | ||
| - | |||
| ==== SE Linux ==== | ==== SE Linux ==== | ||
| Following rules add exceptiong for selinux. | Following rules add exceptiong for selinux. | ||
sar_reporting.1312488419.txt.gz · Last modified: 2020/08/10 02:29 (external edit)
