AIX Tip of the Week

Using a Browser to Display System Performance

Audience: All

Date: November 25, 2002

Here's a quick and easy method for displaying a system's performance from a PC browser. The following chart illustrates CPU performance, but you can display any data collected by "sar" command: disk usage, run queues, paging, etc.

sarplot.gif


The procedure to set this up is as follows:

  1. Enable HTTP on your server. See your system documentation
  2. Enable "sar" to collect performance data. The following steps enable sar data collection on a 15 minute interval, from midnight to midnight, Monday-Friday. Customize to your needs.
  3. Install "gnuplot" (http://www-1.ibm.com/servers/aix/products/aixos/linux/download.html )
  4. Edit sarplot.cgi (below) to point to the "gnuplot" program
  5. Copy sarplot.cgi to the CGI directory
            # On my system, it look like this
            cp sarplot.cgi   /usr/HTTPServer/cgi-bin
            chmod a+x /usr/HTTPServer/cgi-bin/sarplot.cgi
    
  6. Copy sarplot.htm to the HTTP document directory
            # On my system, it looks like
            cp sarplot.htm  /usr/HTTPServer/htdocs
            chmod a+r /usr/HTTPServer/htdocs/sarplot.htm
    
  7. Point your browser to http://yourhostname/sarplot.htm

    sarplot.htm

    
    <html>
    <head><h2>Performance Measures:</h2></head>
    <body>
    <FORM ACTION="cgi-bin/sarplot.cgi" METHOD="POST">
    <TABLE WIDTH=500 BORDER=0 CELLSPACING=0 CELLPADDING=5 
    BGCOLOR="#BBBBBB">
     <TR>
      <TD ALIGN=CENTER> <INPUT TYPE="RADIO" NAME="opt" VALUE="u" CHECKED> 
    </TD>
      <TD> cpu usage </TD>
     </TR>
     <TR>
     <TR>
      <TD ALIGN=CENTER> <INPUT TYPE="RADIO" NAME="opt" VALUE="d" CHECKED> 
    </TD>
      <TD> disk usage </TD>
     </TR>
     <TR>
      <TD ALIGN=CENTER> <INPUT TYPE="RADIO" NAME="opt" VALUE="b"> </TD>
      <TD> buffer activity </TD>
     </TR>
     <TR>
      <TD ALIGN=CENTER> <INPUT TYPE="RADIO" NAME="opt" VALUE="y"> </TD>
      <TD> TTY device activity </TD>
     </TR>
     <TR>
      <TD ALIGN=CENTER> <INPUT TYPE="RADIO" NAME="opt" VALUE="c"> </TD>
      <TD> system calls </TD>
     </TR>
    <TR>
      <TD ALIGN=CENTER> <INPUT TYPE="RADIO" NAME="opt" VALUE="w"> </TD>
      <TD> swapping and switching </TD>
     </TR>
     <TR>
      <TD ALIGN=CENTER> <INPUT TYPE="RADIO" NAME="opt" VALUE="a"> </TD>
      <TD> file access statistics </TD>
     </TR>
     <TR>
      <TD ALIGN=CENTER> <INPUT TYPE="RADIO" NAME="opt" VALUE="q"> </TD>
      <TD> run queue statistics </TD>
     </TR>
     <TR>
      <TD ALIGN=CENTER> <INPUT TYPE="RADIO" NAME="opt" VALUE="v"> </TD>
      <TD> process, inode and file tables </TD>
     </TR>
     <TR>
      <TD ALIGN=CENTER> <INPUT TYPE="RADIO" NAME="opt" VALUE="m"> </TD>
      <TD> message and semaphore activity </TD>
     </TR>
     <TR>
      <TD ALIGN=CENTER> <INPUT TYPE="RADIO" NAME="opt" VALUE="p"> </TD>
      <TD> paging (-p) </TD>
     </TR>
    <TR>
      <TD ALIGN=CENTER> <INPUT TYPE="RADIO" NAME="opt" VALUE="g"> </TD>
    
      <TD> paging (-g) </TD>
     </TR>
     <TR>
      <TD ALIGN=CENTER> <INPUT TYPE="RADIO" NAME="opt" VALUE="r"> </TD>
      <TD> unused memory pages and disk blocks </TD>
     </TR>
     <TR>
      <TD ALIGN=CENTER> <INPUT TYPE="RADIO" NAME="opt" VALUE="k"> </TD>
      <TD> kernel memory allocation </TD>
     </TR>
     <TR>
      <TD>
       <INPUT TYPE="SUBMIT" VALUE="GRAPH IT!">
      </TD>
      <TD>
       After making your selection, click the button
      </TD>
     </TR>
    </TABLE>
    </body>
    

    sarplot.htm

    
    #!/usr/bin/perl
    # sarplot.cgi, shs 11/14/02, plot sar data
    # modified by Bruce Sepncer, 11/25/02 
    # 	added section for  disk usage 
    #	changed tif to gif
    #	added yrange 0 to 100 for CPU, Disk and run queues
    
    ####################### Your Customizations go here #############
    # Location of the gnuplot command
    my $gnuplot = "/usr/local/bin/gnuplot";
    
    ####################### End of Your Customizations ##############
    
    
    # ---------------------------------------------------------- modules
    use IPC::Open3;
    use CGI qw(:standard);
    
    # ------------------------------------------------------- parameters
    $opt=param('opt');
    if ( ! $opt =~ /\w/ ) {		# replace if not single letter
        $opt="u";
    }
    
    # Set YRange on plot
    # Found that gnuplot didn't do it properly
    if ( $opt =~ /u|d|q/ ) {
    	$YRANGE = "[ 0 to 100 ]";
    	} else {
    	$YRANGE = "[ 0 to 1000 ]";
    	}
    
    $dt=`date`;		 	# save date for title
    
    chomp($dt);
    @sarstats=`sar -$opt`;		 # capture data from sar
    $data="/tmp/stats$$";		 # identify temp file
    
    # ----------------------------------------------- process sar output
    open DATA, ">$data" or die "Cannot open $data for writing";
    
    foreach $line (@sarstats) {
    
        if ( $line =~ /Average/ ) {
    		last;
        } elsif ( $line =~ /^$/ ) {
    	next; # skip blank lines
    
        } elsif ( $opt eq "d" ) {
    
        	if    ( $line=~/^\d+:\d+:\d+.+hdisk/ ) { # first line in reading
    		@cols=split(/\s+/, $line);  
    		$disk_line= $cols[0] . " " . $cols[3];
    		}
    	elsif ( $line =~ /hdisk/ ) {
    		@cols=split(/\s+/, $line);  
    		$disk_line .= " " . $cols[2];
    		} 	
    	elsif ( $line =~ /cd/ ) {
    		print DATA ("$disk_line \n");
    		}
    	
        } elsif ( $line=~/\d+:\d+:\d+.+[a-z]/ ) { # capture column headings
    
            @hdgs=split ' ',$line;		 # store in array for later use
    
        } else  {
    		 print DATA "$line";
        }
    }
    close DATA;
    
    # Because the "sar -d" provides multi lines, must read headings differently
    # 
    if ( $opt eq "d" ) {
    	
    	@hdgs="";
     	foreach $line (@sarstats) {
    
    		if ( $line =~ /cd/ ) { last; }
    		if ( $line =~ /hdisk\d+/ ) {
    			@hdgs= (@hdgs, $&);
    			}
    	} # end for each
    
    } # end if
    
    $sz=$#hdgs;		 # number of data columns
    
    # ------------------------------------------------------ run gnuplot
    $| = 1;		 	 # disable buffering
    
    my $pid = open3(\*GNUPLOT, \*GRAPHDATA, \*ERROR, $gnuplot);
    
    # send commands to gnuplot
    print GNUPLOT << "END";
    set term gif color
    set title "$dt (sar -$opt)";
    set timefmt "%H:%M"
    set xdata time
    set format x "%H:%M"
    set xtics border rotate
    set xrange ["00:00" to "23:59"]
    set yrange $YRANGE
    END
    
    # send command line for each data column
    print GNUPLOT "plot ";
    for ($x=2; $x<=$sz; $x++) {
        $h=$x-1;
        print GNUPLOT "'$data' using 1:$x t '$hdgs[$h]' with line,";
    }
    # last line is separate because is has no continuation character
    print GNUPLOT "'$data' using 1:$x t '$hdgs[$x-1]' with line";
    
    close(GNUPLOT);
    
    # identify data type
    print header("image/gif");
    
    # send the image back to the browser
    while ($length = sysread(GRAPHDATA,$content,1024)) {
    		 syswrite(STDOUT,$content,$length);
    }
    
    close(GRAPHDATA);
    
    `/usr/bin/rm $data`;
    

    Bruce Spencer,
    baspence@us.ibm.com