Location: PHPKode > projects > Monyet > classes/bigplotter.php
<?php
include ("plotter/jpgraph/src/jpgraph.php");
include ("plotter/jpgraph/src/jpgraph_log.php");
include ("plotter/jpgraph/src/jpgraph_line.php");
include ("plotter/jpgraph/src/jpgraph_pie.php");
include ("plotter/jpgraph/src/jpgraph_bar.php");
include ("plotter/jpgraph/src/jpgraph_pie3d.php");

//this class use posttime from data base
//not really a plotter.. i picked wrong classname

//instead of interval that must be in 5 minutes granularity
//i revisit the sql query for selecting data from database

//if thereis no warning threshold and critical threshold it should be shown as green pie chart 

Class BigPlotter{

	//tons of data dictionary
	private $starttime;
	private $finishtime;
	
	//determine active window monitoring
	private $startwindow;
	private $finishwindow;
	
	private $table;
	private $dba;
	
	//the line graph to plot the actual data
	private $graph;
	//the pie graph to plot availability
	private $pieGraph;

	private $data;
	private $availdata;
	private $legend;
	//interval determine what the granularity should be presented
	//12*5 = 1 hour
	private $interval;
	private $redvalue;
	private $greenvalue;
	private $map;
	//average (graphtype==avg) or full rough data (graphtype==full)
	//or undefined/null if you want button average or detail disabled
	private $graphtype; 	
	private $caller; //actual class that invoke plotter, to determine href for image maps
	private $post; //caller post
	private $title;

	private $graphAvail;

	//statistic
	private $maxstat;
	private $minstat;
	private $averagestat;
	private $lateststat;


	//return the downtime/totalcheckpoint
	private $availability;

	public function __construct(){
		// Setup the graph
		$this->dba = DBAccess::getInstance();
		// default for interval
		$this->interval = 10;
		//defaul is line graph
		$this->graphAvail = false;
	}
	public function setGraph($table,$st,$ft){
	   $this->starttime = $st;
		$this->finishtime = $ft;
		$stts = strtotime($this->starttime);
		$ftts = strtotime($this->finishtime);
		//calculate how much we will be iterate
		$diff = ($ftts - $stts)/(60*5*$this->interval);
		
		//table determine the monitoring id
		//plotter self aware
		$this->table = $table;
		$obj = '';
		if($table[0]=='p'){
			$obj = new Ping();
			$obj->selectByID($table);
			$this->setLegend('Ping');
		}
		else
		if($table[0]=='s'){
			$obj = new ServiceMon();
			$obj->selectByID($table);
			$objservdef = new ServicesDef();
			$objservdef->selectByID($obj->getService());
			$this->setLegend('Service '.$objservdef->getName());
		}
		else{
			die('currently not support for monitoring with priority id '.$table);
		}

		$this->redvalue = $obj->getRedLine();
		$this->greenvalue = $obj->getGreenLine();
		$this->startwindow = $obj->getStartTime();
		$this->finishwindow = $obj->getFinishTime();
		$peak = 0;
		//magic number here make sure it's big enough
		$valley = 10000;

		$gap = 5*60*$this->interval;
		$downcount = 0;
		$criticalcount = 0;
		$warningcount = 0;
		$okcount = 0;
		
		$result = array();
		$inactive = array();
		$datay = array();
		$posttime = array();
		$redline = array();
		$greenline = array();
		$lastcaption = '';
		
		$offset = $stts;
		$bigtotal = 0;
		for($i=0;$i<$diff;$i++){
			//building time query
			$q_start_time = " AND posttime >= \"".date('Y-m-d G:i:s',($offset+($i*$gap)))."\"";
			$q_finish_time = " AND posttime <= \"".date('Y-m-d G:i:s',($offset+(($i+1)*$gap)))."\"";
			$sql = "SELECT value FROM ".$this->table." WHERE value>=0 ".$q_start_time." ".$q_finish_time;
			$tempresult = $this->dba->query($sql);
			//calculate data within 
			$total = 0;
			$tmpobj = new StdClass();
			$count = 0;
			$downcounttemp = 0;
			$criticalcounttemp = 0;
			$warningcounttemp = 0;
			$okcounttemp = 0;
			for($j=0;$j<sizeof($tempresult);$j++){
				$total+=$tempresult[$j]->value;
				$count++;
				if($tempresult[$j]->value==0){
					$downcounttemp++;
				}
				else
				if($tempresult[$j]->value < $this->greenvalue){
					$okcounttemp++;		  
				}
				else
				if($tempresult[$j]->value>=$this->redvalue){
					$criticalcounttemp++;
				}
				else
				if(($tempresult[$j]->value <= $this->redvalue)&&($tempresult[$j]->value > $this->greenvalue)){
					$warningcounttemp++;
				}
			}
			if(($this->redvalue==0)&&($this->greenvalue==0)){
				$okcounttemp += $criticalcounttemp;
				$criticalcounttemp = 0;
			}
			$downcount += $downcounttemp;
			$criticalcount += $criticalcounttemp;
			$warningcount += $warningcounttemp;
			$okcount += $okcounttemp;
			$bigtotal += $total;
			//take the data to the container
			if($this->interval<288){
				if($lastcaption==date('Y-m-d',$offset+($i*$gap))){
					$posttime[$i] = date('G:i',$offset+($i*$gap));
				}else{
					$lastcaption = date('Y-m-d',$offset+($i*($gap)));
					$posttime[$i] = '   '.date('G:i',$offset+($i*($gap)))."\n".date('Y-m-d',$offset+($i*$gap));
				}
				$tmpobj->itemid = date('Y-m-d G:i',$offset+($i*$gap));
			}
			else
			if($this->interval>=288){
				if($lastcaption==date('Y-m',$offset+($i*$gap))){
					$posttime[$i] = date('d',$offset+($i*$gap));
				}else{
					$lastcaption = date('Y-m',$offset+($i*($gap)));
					$posttime[$i] = '   '.date('d',$offset+($i*($gap)))."\n".date('Y-m',$offset+($i*$gap));
				}
				$tmpobj->itemid = date('Y-m-d',$offset+($i*$gap));
			}
			$tmpobj->posttime = $tmpobj->itemid;
			$tmpdate = date('G:i:s',strtotime($tmpobj->posttime));
			//if graphavail = false then datay is average value
			if($this->graphAvail){
				$avail=0;
				if($count!=0){
					$avail = round(($okcounttemp+$warningcounttemp)/$count*10000)/100;
				}
				if((strtotime($tmpdate)<strtotime($this->startwindow))||(strtotime($tmpdate)>strtotime($this->finishwindow))){
					$inactive[] = $avail;
				}else{
					$datay[] = $avail;
				}
				$tmpobj->value = $avail;
			}
			else{
				$average = null;
				if($count>0){
					$average=round($total/$count*100)/100;
				}
				$datay[] = $average;
				$redline[] = $this->redvalue; 
				$greenline[] = $this->greenvalue;
				if($peak < $average){
					$peak = $average;
				}
				if($valley > $average){
					$valley = $average;
				}
				if($this->startwindow!=$this->finishwindow){
					if((strtotime($tmpdate)<strtotime($this->startwindow))||(strtotime($tmpdate)>strtotime($this->finishwindow))){
						$inactive[] = $average;
					}else{
						$inactive[] = null;
					}
				}else{
					$inactive[] = null;
				}
				$tmpobj->value = $average;
			}
			$result[] = $tmpobj;
		}
		$this->data = $result;
		//calculate the peak and valley to give better presentation
		$this->maxstat = $peak;
		if($valley==10000){
			$this->minstat = 0;
		}
		else{
			$this->minstat = $valley;
		}
		if($downcount>0){
			$valley = 0;
		}
		else
		if($valley>$this->greenvalue){
			$valley = $this->greenvalue;
		}
		if($peak<$this->redvalue){
			$peak = $this->redvalue;
		}
	
		$peak += ($peak-$valley)*0.15;
		$valley -= ($peak-$valley)*0.05;
		//if negatif pick zero as valley
		if($valley<0){
			$valley=0;
		}
		// Setup the graph
		$this->graph = new Graph(510,305);
		$this->graph->SetMarginColor('white');
		$this->graph->SetFrame(false);
		$this->graph->SetMargin(30,50,30,35);


		//set up pie graph
		$this->pieGraph = new PieGraph(500,200,"auto");
		$this->pieGraph->SetMarginColor('white');
		$this->pieGraph->SetFrame(false);
		$this->pieGraph->SetMargin(30,50,30,30);

		//if greenvalue and redvalue == 0, its mean that threshold unset
		//treat it as green pie chart
		$totalcheckpoint = $downcount+$criticalcount+$warningcount+$okcount;
		if($totalcheckpoint<2){
			die('Data not big enought to be plotted. Please wait while system is collecting the data');
		}
		$this->availability = round(($okcount+$warningcount)/$totalcheckpoint*10000)/100;
		$this->averagestat = (round($bigtotal/$totalcheckpoint*100)/100);

		//calculate the availability in percentage
		//NOTE: critical is excluded for availability definition

		$datapie = array();	
		$legendpie = array();
		$slicecolor = array();
		//for good presentation only show non-null value
		if($downcount!=0){
			$datapie[] = $downcount;
			$legendpie[] = 'down';
			$slicecolor[] = '#f2f2fc';
		}
		if($criticalcount!=0){
			$datapie[] = $criticalcount;
			$legendpie[] = 'critical';
			$slicecolor[] = '#ff8c8f';
		}
		
		if($warningcount!=0){
			$datapie[] = $warningcount;
			$legendpie[] = 'warning';
			$slicecolor[] = '#ffff8f';
		}
		if($okcount!=0){
			$datapie[] = $okcount;
			$legendpie[] = 'ok';
			$slicecolor[] = '#befff5';
		}
		$pie = new PiePlot3D($datapie);
		$pie->setLegends($legendpie);
		$pie->SetSliceColors($slicecolor);
		//always explode the first pie chunk ;)
		//to give clear presentation what is critical
		$pie->explodeSlice(0);
		$this->pieGraph->add($pie);

		if($this->graphAvail==false){	
			// Create the first line
			$p1 = new LinePlot($datay);
			$p1->SetColor("navy");
			$p1->SetLegend($this->legend);
			$this->graph->Add($p1);
			if(isset($this->redvalue)){
				// Create red line
				$p3 = new LinePlot($redline);
				$p3->SetColor("red");
				$this->graph->Add($p3);
			}
			if(isset($this->greenvalue)){
				$p2 = new LinePlot($greenline);
				$p2->SetColor("yellow");
				$this->graph->Add($p2);
			}
			//build gray line to show active window size
			$p5 = new LinePlot($inactive);
			$p5->SetColor("gray");
			$this->graph->Add($p5);
			$this->graph->SetScale("textlin",$valley,$peak);
		}
		else{
			$datay = array();	  
			for($i=0;$i<sizeof($this->data);$i++){
				$datay[] = $this->data[$i]->value;
			}
			$p1 = new BarPlot($datay);
			$p1->SetColor("navy");
			$p1->SetFillGradient("#99ccff","white",GRAD_HOR);
			$p1->SetLegend('availability (%)');
			$this->graph->Add($p1);
			$this->graph->SetScale("textlin",0,105);
		}

	
		//average and detail button panel embeded in graph
		$txt=new Text("[A]");
		$txt->SetPos(492,85);
		$txt->SetFont(FF_FONT1,FS_NORMAL);

		//average button is enabled if graphtype = full
		if($this->graphtype=='full'){
			//image maps for detail control button
			$url = 'javascript:sndReqPOST(\''.$this->caller.'\',\''.$this->post.'&graphtype=avg\')';
			$this->map .= '<AREA SHAPE="rect" COORDS="492,85,510,97" HREF="'.$url.'">';
			$txt->SetColor("black");
		}
		else{
			$txt->SetColor("gray");
		}
		$this->graph->AddText($txt);
	
		$txt=new Text("[D]");
		$txt->SetPos(492,105);
		$txt->SetFont(FF_FONT1,FS_NORMAL);
		//detail button is enabled if graphtype = avg
		if($this->graphtype=='avg'){
			//image maps for detail control button
			$url = 'javascript:sndReqPOST(\''.$this->caller.'\',\''.$this->post.'&graphtype=full\')';
			$this->map .= '<AREA SHAPE="rect" COORDS="492,105,510,117" HREF="'.$url.'">';
			$txt->SetColor("black");
		}
		else{
			$txt->SetColor("gray");
		}
		$this->graph->AddText($txt);
	
		$txt=new Text("[F]");
		$txt->SetPos(492,135);
		$txt->SetFont(FF_FONT1,FS_NORMAL);
		//full screen
		$url = 'javascript:sndReqPOST(\''.$this->caller.'\',\''.$this->post.'&graphtype=full\')';
		$this->map .= '<AREA SHAPE="rect" title="show full screen" COORDS="492,135,510,147" HREF="javascript:popup(\'gen_picts/mainframe.gif\',\'big\',\'notes\')">';
		$txt->SetColor("black");
		$this->graph->AddText($txt);
		
		$this->graph->xaxis->SetTickLabels($posttime);
		$this->graph->xaxis->SetTextTickInterval(1);
		$this->graph->title->Set($this->title);
	}

	//similar with getrecent
	public function getLatestStat(){
		return $this->lateststat;
	}

	public function getMaxStat(){
		return $this->maxstat;
	}

	public function getMinStat(){
		return $this->minstat;
	}
	public function getAverageStat(){
		return $this->averagestat;
	}

	public function getImageMaps(){
		return '<MAP NAME="MyMap">'.$this->map.'</MAP>';
	}

	public function attachLine(){
		//set graph
		$file = rand(2,20000).'plotline.png';
		$this->graph->Stroke('/www/htdocs/ajaxmonyet/tmp/'.$file);
		return $file;
	}
	public function attachPie(){
		//set graph
		$file = rand(2,20000).'plotpie.png';
		$this->pieGraph->Stroke('/www/htdocs/ajaxmonyet/tmp/'.$file);
		return $file;
	}

	public function setTitle($title){
		$this->title = $title;
	}
	public function getData(){
	  	return $this->data;
	}
	public function setLegend($legend){
		$this->legend = $legend;
	}
	//boolean value. determine wether graph should be displayed as bar availability or line detail line
	public function setGraphAvail($graphavail){
		$this->graphAvail = $graphavail;
	}
	public function setCaller($caller,$post){
	   $this->caller = $caller;
	   $this->post = $post;
	}
	public function setRedLine($red){
		$this->redvalue = $red;
	}
	public function setGreenLine($green){
		$this->greenvalue = $green;
	}

	//set the graph graphtype. avg for average and full for full rough data
	//null or undefined if you want average and detail button disabled
	public function setGraphType($graphtype){
		$this->graphtype = $graphtype;
	}
	public function setInterval($interval){
		$this->interval = $interval;
	}

	//please invoke after setGraph
	public function getAvailability(){
		return $this->availability;
	}


}

?>
Return current item: Monyet