DZone Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

Snippets has posted 5883 posts at DZone. View Full User Profile

Terminal *live* Text Graph In Php, Unix Terminal

01.16.2007
| 6701 views |
  • submit to reddit
        I often run php scripts from the command line in linux and need a way to view time series of data, often I need to see the number of mysql queries or want to view other stats.
That look like the following, it moves from right to left in real time as the data points change. 
+local mysql: 565 queries/sec 189----------------------+
 |                                                      |
 |                                       %              |
 |                                       %              |
 |                                       %              |
 |                                       %              |
 |                                       %              |
 |                   %                   %              |
 | %   %%   %% % %  %%%%%                % %%        %% |
 |%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%% %%%%%%  %%%%%|
 |%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%|
+-------------------------------------high: 100, low: 1+
Just copy and past the following code into a file called "termgraph.php" and change the mysql password (if needed) and change the database name (if needed as it it set to work with the default mysql install), then run it and see, very easy to modify this to work with whatever you need. In addition, you can also do colored graphs in terminals using another function I am going to post here.

This needs a couple changes to work with your mysql database, but the graphs are fun to watch, hope you enjoy this.

<?
// see *EDIT* below for one other change you will need to make
function DatabaseConnect() {
    if (!($mylink = mysql_connect("localhost", "root", ""))){
            print  "ERROR";
            exit;
        }//fi
        mysql_select_db("test") or die(mysql_error());
}// end function
DatabaseConnect();

/*
    remove flatspots in array..
    areas where the data does not change.
    this is good for data that only changes during certain times
    and the dead time has no bearing on the changes.
    -joeldg
*/
function remove_flatspots($arr, $pkey=true){
    while(list($key,$val) = each($arr)){
        if($val <> $oldval){
            if($pkey == true){
                $ret[$key] = $val;
            }else{
                $ret[] = $val;
            }
        }
        $oldval = $val;
    }
    return $ret;
}
/*
    take two arrays, remove the flatspots in the first.
    return an array containing the first with it's corresponding
    values in the second array..
    -joeldg
*/
function dual_remove_flatspots($arr1, $arr2, $pkey=true){
    while(list($key,$val) = each($arr1)){
        if($val <> $oldval){
            if($pkey == true){
                $ret[0][$key] = $val;
                $ret[1][$key] = $arr2[$key];
            }else{
                $ret[0][] = $val;
                $ret[1][] = $arr2[$key];
            }
        }
        $oldval = $val;
    }
    return $ret;
}

// return lowest val of array -joeldg
function least($inarr){
    $ret = $inarr[0];
    for($i=0;$i<count($inarr);$i++){
        if(intval($inarr[$i]) <= $ret){ $ret = $inarr[$i]; }
    }//rof
    return $ret;
}// end function
// return higest val of array -joeldg
function most($inarr){
    while(list($key,$val) = each($inarr)){
        if ($ret==""){$ret = $val;}
        if($ret <= intval($val)){ $ret = $val; }
    }//rof
    return $ret;
}// end function
/*
	array normalize function 
	-joeldg
*/
function normalize($arr,$LO=0.01,$HI=0.99)
{
  $Min = +2147483647;
  $Max = -2147483647;
  for ($a=0; $a<count($arr); $a++) {
    $Min = min($Min, $arr[$a]);
    $Max = max($Max, $arr[$a]);
  }
  $Mean = 0;
  for ($a=0; $a<count($arr); $a++) {
    $div = $Max-$Min;
    if($div == 0){$div = 1;}
    $arr [$a] = (($arr[$a]-$Min) / ($div)) * ($HI-$LO) + $LO;
    $Mean += $arr[$a] / count($arr);
  }
  return $arr;
}
/*
	array normalize function, preserve key
	-joeldg
*/
function normalizekey($arr,$LO=0.01,$HI=0.99)
{
  $Min = +2147483647;
  $Max = -2147483647;
  while(list($key, $a)=each($arr)){
    $Min = min($Min, $arr[$key]);
    $Max = max($Max, $arr[$key]);
  }
  reset($arr);
  $Mean = 0;
  while(list($key,$a)=each($arr)){
    $div = $Max-$Min;
    if($div == 0){$div = 1;}
    $arr [$key] = (($arr[$key]-$Min) / ($div)) * ($HI-$LO) + $LO;
    $Mean += $arr[$key] / count($arr);
  }
  $retarr[0] = $arr;
  $retarr[1][0]=$Max;
  $retarr[1][1]=$Min;
  
  return $retarr;
}

/*
display a textual graph in an xterm.
written because I want to view timeseries data and not have to jump over to a browser.
*/
#
#    transform an array point to a position within the total
#
function point2arr($point, $total=20){
    $p = round($point);
    for($a=0;$a<$total;$a++){
        if($a <= $p){
            $ret[] = "%";#chr(127);
        }else{
            $ret[] = " ";
        }
    }
    return $ret;
}
// get the width and height of a unix terminal
function get_term_specs(){
    $b = `stty -a`;
    $c = explode("\n",$b);
    $d = explode(";", $c[0]);
    $f = explode(" ",$d[1]);
    $ret[h] = $f[2];
    $f = explode(" ",$d[2]);
    $ret[w] = intval($f[2]);    
    return $ret;
}

function genchars($char, $total, $title="", $echo=false, $way=STR_PAD_RIGHT){
    $ret .= "+";
    #if($echo){ echo termcolored("+", WHITE); }
    #if(!$echo){ $ret .= "+"; }
        #$back = termcolored($title, "YELLOW");
        $back = $title;
        $ret .= str_pad($back, $total+strlen($back)-strlen($title)-2, $char, $way);
    #if(!$echo){ $ret .= "+"; }
    #if($echo){ echo termcolored("+", WHITE); }
    $ret .= "+";
    return $ret;
}
// vertical graph
function print_vert_graph($arr, $total=20, $border="-"){
    $arr = normalize($arr, 0, $total);
    $out[] = genchars($border, $total);
    for($a=0;$a<count($arr);$a++){
        $out[] = point2arr($arr[$a], $total);
    }
    $out[] = genchars($border, $total);
    for($a=0;$a<count($out);$a++){
        for($b=0;$b<count($out[$a]);$b++){
            echo $out[$a][$b];
        }
        echo "\n";
    }
    
}
// transform matrix 
function transformmat($arr,$total=20){
    $width = count($arr[0]);
    $c=$width-1;
    for($w=0;$w<$width;$w++){
        for($a=0;$a<count($arr);$a++){
            $ret[$c][$a] = $arr[$a][$w];
        }
        $c--;
    }
    return $ret;
}
// horizontal graphing
function print_horz_graph($arr, $total=20, $border="-", $title="", $w=""){
    if($w <> ""){
        array_reverse($arr);
        $end = count($arr)-1;
        reset($arr);
        while(list($key,$val)=each($arr)){
            $newarr[] = $arr[$key];
            $end--;
            if($end <= 0){break;}
        }
        #array_reverse($newarr);
        $arr=$newarr;
    }
    #print_R($arr);
    $bottom = "high: ".most($arr).", low: ".least($arr);
    $arr = normalize($arr, 0, $total-2);
    #$out[] = genchars($border, $total);
    for($a=0;$a<count($arr);$a++){
        $out[] = point2arr($arr[$a], $total);
    }
    $out = transformmat($out,$total);
    $ret .= genchars("-", count($out[0])+2, $title, false);
    #echo "\n";
    $ret .= "\n";
    for($a=0;$a<count($out);$a++){
        #echo termcolored("|", WHITE);
        $ret .=  " |";
        for($b=0;$b<count($out[$a]);$b++){
            $ret .= $out[$a][$b];
        }
        $ret .= "|";
        #echo termcolored("|", WHITE);
        $ret .= "\n";
    }
    $ret .= genchars("-", count($out[0])+2, $bottom, false, STR_PAD_LEFT);
    $ret .= "\n";
    return $ret;
    
}

// *EDIT* change mysql to whatever table you want to test
// this default should work for fun..
$db_list = mysql_list_tables("mysql");
while ($row = mysql_fetch_row($db_list)) {
   $tables[] = trim("{$row[0]}");
}
$testarr_z = array();
$testarr = array();
$qcount = 0;
$start = microtime(true);

while(1){
	$hw = get_term_specs();
	array_pad($testarr_z, ($hw['w'] - 6), 0);

	array_pad($testarr, ($hw['w'] - 6), 0);
	$time_start = microtime(true);
	$tab = $tables[rand(0,count($tables))];
	
	$amt = rand(500, 5000);
	$sql = "SELECT * FROM $tab LIMIT 0,$amt";
	$res = mysql_db_query("oracle", $sql);
	$qcount++;
	
	$time_end = microtime(true);
	$time = $time_end - $time_start;
	$testarr_z[] = $time;
	@mysql_free_result($res);
	
	if(count($testarr_z)> ($hw['w'] - 6)){
		array_shift($testarr_z);
	}
	$testarr = normalize($testarr_z, 1, 100);

	$testarr = remove_flatspots($testarr, false);
	$tottime = $time_end - $start;
	$qps = round($qcount/$tottime);
	echo print_horz_graph($testarr, $hw['h']-3, "-", "local mysql: $qcount queries/sec $qps", $hw['w']-1);

}

?>
    

Comments

Kenneth Mccall replied on Fri, 2007/08/10 - 11:56am

instead of drawing a new screen each time - you could use VT100 commands to update the parts of the screen you want. http://vt100.net/