stime = null; $this->fullSizeX = null; $this->fullSizeY = null; $this->yaxismin = null; $this->yaxismax = null; $this->m_minY = null; $this->m_maxY = null; $this->data = array(); $this->items = null; $this->min = null; $this->max = null; $this->avg = null; $this->clock = null; $this->count = null; $this->header = null; $this->from_time = null; $this->to_time = null; $this->colors = null; $this->im = null; $this->triggers = array(); $this->period=3600; $this->from=0; $this->sizeX=900; $this->sizeY=200; $this->shiftXleft=10; $this->shiftXright=60; $this->shiftY=17; $this->border=1; $this->num=0; $this->type = $type; $this->yaxistype=GRAPH_YAXIS_TYPE_CALCULATED; $this->yaxisright=0; $this->yaxisleft=0; $this->m_showWorkPeriod = 1; $this->m_showTriggers = 1; /* if($this->period<=3600) { $this->date_format="H:i"; } else { $this->date_format="m.d H:i"; }*/ } function updateShifts() { if( ($this->yaxisleft == 1) && ($this->yaxisright == 1)) { $this->shiftXleft = 60; $this->shiftXright = 60; } else if($this->yaxisleft == 1) { $this->shiftXleft = 60; $this->shiftXright = 20; } else if($this->yaxisright == 1) { $this->shiftXleft = 10; $this->shiftXright = 60; } # $this->sizeX = $this->sizeX - $this->shiftXleft-$this->shiftXright; } function initColors() { $colors = array( /* Red, Green, Blue, Alpha */ "Red" => array(255,0,0,50), "Dark Red" => array(150,0,0,50), "Green" => array(0,255,0,50), "Dark Green" => array(0,150,0,50), "Blue" => array(0,0,255,50), "Dark Blue" => array(0,0,150,50), "Yellow" => array(255,255,0,50), "Dark Yellow" => array(150,150,0,50), "Cyan" => array(0,255,255,50), "Black" => array(0,0,0,50), "Gray" => array(150,150,150,50), "White" => array(255,255,255), "Dark Red No Alpha" => array(150,0,0), "Black No Alpha" => array(0,0,0), "HistoryMinMax" => array(90,150,185,50), "HistoryMax" => array(255,100,100,50), "HistoryMin" => array(50,255,50,50), "HistoryAvg" => array(50,50,50,50), "ValueMinMax" => array(255,255,150,50), "ValueMax" => array(255,180,180,50), "ValueMin" => array(100,255,100,50), "Priority Disaster" => array(255,0,0), "Priority Hight" => array(255,100,100), "Priority Average" => array(221,120,120), "Priority" => array(100,100,100), "Not Work Period" => array(230,230,230), "UncnownData" => array(130,130,130, 50) ); // I should rename No Alpha to Alpha at some point to get rid of some confusion foreach($colors as $name => $RGBA) { if(isset($RGBA[3]) && function_exists("ImageColorExactAlpha") && function_exists("ImageCreateTrueColor") && @ImageCreateTrueColor(1,1) ) { $this->colors[$name] = ImageColorExactAlpha($this->im,$RGBA[0],$RGBA[1],$RGBA[2],$RGBA[3]); } else { $this->colors[$name] = ImageColorAllocate($this->im,$RGBA[0],$RGBA[1],$RGBA[2]); } } } function ShowWorkPeriod($value) { $this->m_showWorkPeriod = $value == 1 ? 1 : 0; } function ShowTriggers($value) { $this->m_showTriggers = $value == 1 ? 1 : 0;; } function AddItem($itemid, $axis=GRAPH_YAXIS_SIDE_RIGHT, $calc_fnc=CALC_FNC_AVG, $color=null, $drawtype=null, $type=null, $periods_cnt=null) { if($this->type == GRAPH_TYPE_STACKED /* stacked graph */) $drawtype = GRAPH_DRAW_TYPE_FILL; $this->items[$this->num] = get_item_by_itemid($itemid); $this->items[$this->num]["description"]=item_description($this->items[$this->num]["description"],$this->items[$this->num]["key_"]); $host=get_host_by_hostid($this->items[$this->num]["hostid"]); $this->items[$this->num]["host"] = $host["host"]; $this->items[$this->num]["color"] = is_null($color) ? "Dark Green" : $color; $this->items[$this->num]["drawtype"] = is_null($drawtype) ? GRAPH_DRAW_TYPE_LINE : $drawtype; $this->items[$this->num]["axisside"] = is_null($axis) ? GRAPH_YAXIS_SIDE_RIGHT : $axis; $this->items[$this->num]["calc_fnc"] = is_null($calc_fnc) ? CALC_FNC_AVG : $calc_fnc; $this->items[$this->num]["calc_type"] = is_null($type) ? GRAPH_ITEM_SIMPLE : $type; $this->items[$this->num]["periods_cnt"] = is_null($periods_cnt) ? 0 : $periods_cnt; if($this->items[$this->num]["axisside"] == GRAPH_YAXIS_SIDE_LEFT) $this->yaxisleft=1; if($this->items[$this->num]["axisside"] == GRAPH_YAXIS_SIDE_RIGHT) $this->yaxisright=1; $this->num++; } function setPeriod($period) { $this->period=$period; } function setYAxisMin($yaxismin) { $this->yaxismin=$yaxismin; } function setYAxisMax($yaxismax) { $this->yaxismax=$yaxismax; } function setYAxisType($yaxistype) { $this->yaxistype=$yaxistype; } function SetSTime($stime) { if($stime>200000000000 && $stime<220000000000) { $this->stime=mktime(substr($stime,8,2),substr($stime,10,2),0,substr($stime,4,2),substr($stime,6,2),substr($stime,0,4)); } } function setFrom($from) { $this->from=$from; } function setWidth($value = NULL) { // Avoid sizeX==0, to prevent division by zero later if($value <= 0) $value = NULL; if(is_null($value)) $value = 900; $this->sizeX = $value; } function setHeight($value = NULL) { if($value <= 0) $value = NULL; if(is_null($value)) $value = 900; $this->sizeY = $value; } function setBorder($border) { $this->border=$border; } function getLastValue($num) { $data = &$this->data[$this->items[$num]["itemid"]][$this->items[$num]["calc_type"]]; if(isset($data)) for($i=$this->sizeX-1;$i>=0;$i--) { if(isset($data->count[$i]) && ($data->count[$i] > 0)) { switch($this->items[$num]["calc_fnc"]) { case CALC_FNC_MIN: return $data->min[$i]; case CALC_FNC_MAX: return $data->max[$i]; case CALC_FNC_ALL: /* use avg */ case CALC_FNC_AVG: default: return $data->avg[$i]; } } } return 0; } function drawSmallRectangle() { DashedRectangle($this->im, $this->shiftXleft-1, $this->shiftY-1, $this->sizeX+$this->shiftXleft-1, $this->sizeY+$this->shiftY+1, $this->GetColor("Black No Alpha") ); } function drawRectangle() { ImageFilledRectangle($this->im,0,0, $this->fullSizeX,$this->fullSizeY, $this->GetColor("White")); if($this->border==1) { ImageRectangle($this->im,0,0,$this->fullSizeX-1,$this->fullSizeY-1,$this->GetColor("Black No Alpha")); } } function period2str($period) { $minute=60; $hour=$minute*60; $day=$hour*24; $str = " ( "; $days=floor($this->period/$day); $hours=floor(($this->period%$day)/$hour); $minutes=floor((($this->period%$day)%$hour)/$minute); $str.=($days>0 ? $days."d" : "").($hours>0 ? $hours."h" : "").($minutes>0 ? $minutes."m" : ""); $str.=" history "; $hour=1; $day=$hour*24; $days=floor($this->from/$day); $hours=floor(($this->from%$day)/$hour); $minutes=floor((($this->from%$day)%$hour)/$minute); $str.=($days>0 ? $days."d" : "").($hours>0 ? $hours."h" : "").($minutes>0 ? $minutes."m" : ""); $str.=($days+$hours+$minutes>0 ? " in past " : ""); $str.=")"; return $str; } function drawHeader() { if(!isset($this->header)) { $str=$this->items[0]["host"].":".$this->items[0]["description"]; } else { $str=$this->header; } $str=$str.$this->period2str($this->period); if($this->sizeX < 500) { $fontnum = 2; } else { $fontnum = 4; } $x=$this->fullSizeX/2-ImageFontWidth($fontnum)*strlen($str)/2; ImageString($this->im, $fontnum,$x,1, $str , $this->GetColor("Dark Red No Alpha")); } function setHeader($header) { $this->header=$header; } function drawGrid() { $this->drawSmallRectangle(); for($i=1;$i<=5;$i++) { DashedLine($this->im,$this->shiftXleft,$i*$this->sizeY/6+$this->shiftY,$this->sizeX+$this->shiftXleft,$i*$this->sizeY/6+$this->shiftY,$this->GetColor("Gray")); } for($i=1;$i<=23;$i++) { DashedLine($this->im,$i*$this->sizeX/24+$this->shiftXleft,$this->shiftY,$i*$this->sizeX/24+$this->shiftXleft,$this->sizeY+$this->shiftY,$this->GetColor("Gray")); } $old_day=-1; for($i=0;$i<=24;$i++) { ImageStringUp($this->im, 1,$i*$this->sizeX/24+$this->shiftXleft-3, $this->sizeY+$this->shiftY+57, date(" H:i",$this->from_time+$i*$this->period/24) , $this->GetColor("Black No Alpha")); $new_day=date("d",$this->from_time+$i*$this->period/24); if( ($old_day != $new_day) ||($i==24)) { $old_day=$new_day; ImageStringUp($this->im, 1,$i*$this->sizeX/24+$this->shiftXleft-3, $this->sizeY+$this->shiftY+57, date("m.d H:i",$this->from_time+$i*$this->period/24) , $this->GetColor("Dark Red No Alpha")); } } } function drawWorkPeriod() { if($this->m_showWorkPeriod != 1) return; if($this->period > 2678400) return; // > 31*24*3600 (month) $db_work_period = DBselect("select work_period from config"); $work_period = DBfetch($db_work_period); if(!$work_period) return; $periods = parse_period($work_period['work_period']); if(!$periods) return; ImageFilledRectangle($this->im, $this->shiftXleft+1, $this->shiftY, $this->sizeX+$this->shiftXleft, $this->sizeY+$this->shiftY, $this->GetColor("Not Work Period")); $now = time(); if(isset($this->stime)) { $this->from_time=$this->stime; $this->to_time=$this->stime+$this->period; } else { $this->to_time=$now-3600*$this->from; $this->from_time=$this->to_time-$this->period; } $from = $this->from_time; $max_time = $this->to_time; $start = find_period_start($periods,$from); $end = -1; while($start < $max_time && $start > 0) { $end = find_period_end($periods,$start,$max_time); $x1 = round((($start-$from)*$this->sizeX)/$this->period) + $this->shiftXleft; $x2 = round((($end-$from)*$this->sizeX)/$this->period) + $this->shiftXleft; //draw rectangle ImageFilledRectangle( $this->im, $x1, $this->shiftY, $x2, $this->sizeY+$this->shiftY, $this->GetColor("White")); $start = find_period_start($periods,$end); } } function calcTriggers() { $this->triggers = array(); if($this->m_showTriggers != 1) return; if($this->num != 1) return; // skip multiple graphs $max = 3; $cnt = 0; $db_triggers = DBselect("select distinct tr.triggerid,tr.expression,tr.priority from triggers tr,functions f,items i". " where tr.triggerid=f.triggerid and f.function in ('last','min','max') and". " tr.status=".TRIGGER_STATUS_ENABLED." and i.itemid=f.itemid and f.itemid=".$this->items[0]["itemid"]." order by tr.priority"); while(($trigger = DBfetch($db_triggers)) && ($cnt < $max)) { $db_fnc_cnt = DBselect('select count(*) as cnt from functions f where f.triggerid='.$trigger['triggerid']); $fnc_cnt = DBfetch($db_fnc_cnt); if($fnc_cnt['cnt'] != 1) continue; if(!eregi('\{([0-9]{1,})\}([\<\>\=]{1})([0-9\.]{1,})([K|M|G]{0,1})',$trigger['expression'],$arr)) continue; $val = $arr[3]; if(strcasecmp($arr[4],'K') == 0) $val *= 1024; else if(strcasecmp($arr[4],'M') == 0) $val *= 1048576; //1024*1024; else if(strcasecmp($arr[4],'G') == 0) $val *= 1073741824; //1024*1024*1024; $minY = $this->m_minY[$this->items[0]["axisside"]]; $maxY = $this->m_maxY[$this->items[0]["axisside"]]; if($val <= $minY || $val >= $maxY) continue; if($trigger['priority'] == 5) $color = "Priority Disaster"; elseif($trigger['priority'] == 4) $color = "Priority Hight"; elseif($trigger['priority'] == 3) $color = "Priority Average"; else $color = "Priority"; array_push($this->triggers,array( 'y' => $this->sizeY - (($val-$minY) / ($maxY-$minY)) * $this->sizeY + $this->shiftY, 'color' => $color, 'description' => 'trigger: '.expand_trigger_description($trigger['triggerid']).' ['.$arr[2].' '.$arr[3].$arr[4].']' )); ++$cnt; } } function drawTriggers() { if($this->m_showTriggers != 1) return; if($this->num != 1) return; // skip multiple graphs foreach($this->triggers as $trigger) { DashedLine( $this->im, $this->shiftXleft, $trigger['y'], $this->sizeX+$this->shiftXleft, $trigger['y'], $this->GetColor($trigger['color'])); } } function drawLogo() { ImageStringUp($this->im,0,$this->fullSizeX-10,$this->fullSizeY-50, "http://www.zabbix.com", $this->GetColor("Gray")); } function GetColor($color,$alfa=50) { if(isset($this->colors[$color])) return $this->colors[$color]; $RGB = array( hexdec('0x'.substr($color, 0,2)), hexdec('0x'.substr($color, 2,2)), hexdec('0x'.substr($color, 4,2)) ); if(isset($alfa) && function_exists("ImageColorExactAlpha") && function_exists("ImageCreateTrueColor") && @ImageCreateTrueColor(1,1) ) { return ImageColorExactAlpha($this->im,$RGB[0],$RGB[1],$RGB[2],$alfa); } return ImageColorAllocate($this->im,$RGB[0],$RGB[1],$RGB[2]); } function drawLegend() { $max_host_len=0; $max_desc_len=0; for($i=0;$i<$this->num;$i++) { if(strlen($this->items[$i]["host"])>$max_host_len) $max_host_len=strlen($this->items[$i]["host"]); if(strlen($this->items[$i]["description"])>$max_desc_len) $max_desc_len=strlen($this->items[$i]["description"]); } for($i=0;$i<$this->num;$i++) { if($this->items[$i]["calc_type"] == GRAPH_ITEM_AGGREGATED) { $fnc_name = "agr(".$this->items[$i]["periods_cnt"].")"; $color = $this->GetColor("HistoryMinMax"); } else { $color = $this->GetColor($this->items[$i]["color"]); switch($this->items[$i]["calc_fnc"]) { case CALC_FNC_MIN: $fnc_name = "min"; break; case CALC_FNC_MAX: $fnc_name = "max"; break; case CALC_FNC_ALL: $fnc_name = "all"; break; case CALC_FNC_AVG: default: $fnc_name = "avg"; } } $data = &$this->data[$this->items[$i]["itemid"]][$this->items[$i]["calc_type"]]; if(isset($data)&&isset($data->min)) { $str=sprintf("%s: %s [%s] [min:%s max:%s last:%s]", str_pad($this->items[$i]["host"],$max_host_len," "), str_pad($this->items[$i]["description"],$max_desc_len," "), $fnc_name, convert_units(min($data->min),$this->items[$i]["units"]), convert_units(max($data->max),$this->items[$i]["units"]), convert_units($this->getLastValue($i),$this->items[$i]["units"])); } else { $str=sprintf("%s: %s [ no data ]", str_pad($this->items[$i]["host"],$max_host_len," "), str_pad($this->items[$i]["description"],$max_desc_len," ")); } ImageFilledRectangle($this->im,$this->shiftXleft,$this->sizeY+$this->shiftY+62+12*$i,$this->shiftXleft+5,$this->sizeY+$this->shiftY+5+62+12*$i,$color); ImageRectangle($this->im,$this->shiftXleft,$this->sizeY+$this->shiftY+62+12*$i,$this->shiftXleft+5,$this->sizeY+$this->shiftY+5+62+12*$i,$this->GetColor("Black No Alpha")); ImageString($this->im, 2, $this->shiftXleft+9, $this->sizeY+$this->shiftY+(62-5)+12*$i, $str, $this->GetColor("Black No Alpha")); } if($this->sizeY < 120) return; foreach($this->triggers as $trigger) { ImageFilledEllipse($this->im, $this->shiftXleft + 2, $this->sizeY+$this->shiftY+2+62+12*$i, 6, 6, $this->GetColor($trigger["color"])); ImageEllipse($this->im, $this->shiftXleft + 2, $this->sizeY+$this->shiftY+2+62+12*$i, 6, 6, $this->GetColor("Black No Alpha")); ImageString( $this->im, 2, $this->shiftXleft+9, $this->sizeY+$this->shiftY+(62-5)+12*$i, $trigger['description'], $this->GetColor("Black No Alpha")); ++$i; } } function drawElement( &$data, $from, $to, $minX, $maxX, $minY, $maxY, $drawtype, $max_color, $avg_color, $min_color, $minmax_color, $calc_fnc ) { $shift_min_from = $shift_min_to = 0; $shift_max_from = $shift_max_to = 0; $shift_avg_from = $shift_avg_to = 0; if(isset($data->shift_min[$from])) $shift_min_from = $data->shift_min[$from]; if(isset($data->shift_min[$to])) $shift_min_to = $data->shift_min[$to]; if(isset($data->shift_max[$from])) $shift_max_from = $data->shift_max[$from]; if(isset($data->shift_max[$to])) $shift_max_to = $data->shift_max[$to]; if(isset($data->shift_avg[$from])) $shift_avg_from = $data->shift_avg[$from]; if(isset($data->shift_avg[$to])) $shift_avg_to = $data->shift_avg[$to]; /**/ $min_from = $data->min[$from] + $shift_min_from; $min_to = $data->min[$to] + $shift_min_to; $max_from = $data->max[$from] + $shift_max_from; $max_to = $data->max[$to] + $shift_max_to; $avg_from = $data->avg[$from] + $shift_avg_from; $avg_to = $data->avg[$to] + $shift_avg_to; $x1 = $from + $this->shiftXleft - 1; $x2 = $to + $this->shiftXleft; $y1min = $this->sizeY - ($this->sizeY*($min_from-$minY)/($maxY-$minY)) + $this->shiftY; $y2min = $this->sizeY - ($this->sizeY*($min_to-$minY)/($maxY-$minY)) + $this->shiftY; $y1max = $this->sizeY - ($this->sizeY*($max_from-$minY)/($maxY-$minY)) + $this->shiftY; $y2max = $this->sizeY - ($this->sizeY*($max_to-$minY)/($maxY-$minY)) + $this->shiftY; $y1avg = $this->sizeY - ($this->sizeY*($avg_from-$minY)/($maxY-$minY)) + $this->shiftY; $y2avg = $this->sizeY - ($this->sizeY*($avg_to-$minY)/($maxY-$minY)) + $this->shiftY; switch($calc_fnc) { case CALC_FNC_MAX: $y1 = $y1max; $y2 = $y2max; $shift_from = $shift_max_from; $shift_to = $shift_max_to; break; case CALC_FNC_MIN: $y1 = $y1min; $y2 = $y2min; $shift_from = $shift_min_from; $shift_to = $shift_min_to; break; case CALC_FNC_ALL: $a[0] = $x1; $a[1] = $y1max; $a[2] = $x1; $a[3] = $y1min; $a[4] = $x2; $a[5] = $y2min; $a[6] = $x2; $a[7] = $y2max; ImageFilledPolygon($this->im,$a,4,$minmax_color); ImageLine($this->im,$x1,$y1max,$x2,$y2max,$max_color); ImageLine($this->im,$x1,$y1min,$x2,$y2min,$min_color); /* don't use break, avg must be drawed in this statement */ // break; case CALC_FNC_AVG: /* don't use break, avg must be drawed in this statement */ // break; default: $y1 = $y1avg; $y2 = $y2avg; $shift_from = $shift_avg_from; $shift_to = $shift_avg_to; } $y1_shift = $this->sizeY - ($this->sizeY*$shift_from/($maxY-$minY)) + $this->shiftY; $y2_shift = $this->sizeY - ($this->sizeY*$shift_to/($maxY-$minY)) + $this->shiftY; /* draw main line */ switch($drawtype) { case GRAPH_DRAW_TYPE_BOLDLINE: ImageLine($this->im,$x1,$y1+1,$x2,$y2+1,$avg_color); // break; /* don't use break, must be drawed line also */ case GRAPH_DRAW_TYPE_LINE: ImageLine($this->im,$x1,$y1,$x2,$y2,$avg_color); break; case GRAPH_DRAW_TYPE_FILL: $a[0] = $x1; $a[1] = $y1; $a[2] = $x1; $a[3] = $y1_shift; $a[4] = $x2; $a[5] = $y2_shift; $a[6] = $x2; $a[7] = $y2; ImageFilledPolygon($this->im,$a,4,$avg_color); break; case GRAPH_DRAW_TYPE_DOT: ImageFilledRectangle($this->im,$x1-1,$y1-1,$x1+1,$y1+1,$avg_color); ImageFilledRectangle($this->im,$x2-1,$y2-1,$x2+1,$y2+1,$avg_color); break; } } // Calculation of maximum Y axis function calculateMinY($side) { // return 0; if($this->yaxistype==GRAPH_YAXIS_TYPE_FIXED) { return $this->yaxismin; } else { unset($minY); for($i=0;$i<$this->num;$i++) { if($this->items[$i]["axisside"] != $side) continue; foreach(array(GRAPH_ITEM_SIMPLE, GRAPH_ITEM_AGGREGATED) as $type) { if(!isset($this->data[$this->items[$i]["itemid"]][$type])) continue; $data = &$this->data[$this->items[$i]["itemid"]][$type]; if(!isset($data)) continue; if($type == GRAPH_ITEM_AGGREGATED) $calc_fnc = CALC_FNC_ALL; else $calc_fnc = $this->items[$i]["calc_fnc"]; switch($calc_fnc) { case CALC_FNC_ALL: /* use min */ case CALC_FNC_MIN: $val = $data->min; $shift_val = $data->shift_min; break; case CALC_FNC_MAX: $val = $data->max; $shift_val = $data->shift_max; break; case CALC_FNC_AVG: default: $val = $data->avg; $shift_val = $data->shift_avg; } if(!isset($val)) continue; if($this->type == GRAPH_TYPE_STACKED) for($ci=0; $ci < min(count($val), count($shift_val)); $ci++) $val[$ci] -= $shift_val[$ci]; if(!isset($minY)) { if(isset($val) && count($val) > 0) { $minY = min($val); } } else { $minY = min($minY, min($val)); } } } if(isset($minY)&&($minY>0)) { $exp = round(log10($minY)); $mant = $minY/pow(10,$exp); } else { $exp=0; $mant=0; } $mant=((round(($mant*11)/6)-1)*6)/10; // $mant=(floor($mant*1.1*10/6)+1)*6/10; /* MAX */ $minY = $mant*pow(10,$exp); // Do not allow <0. However we may allow it, no problem. $minY = max(0,$minY); return $minY; // return 0; } } // Calculation of maximum Y of a side (left/right) function calculateMaxY($side) { if($this->yaxistype==GRAPH_YAXIS_TYPE_FIXED) { return $this->yaxismax; } else { unset($maxY); for($i=0;$i<$this->num;$i++) { if($this->items[$i]["axisside"] != $side) continue; foreach(array(GRAPH_ITEM_SIMPLE, GRAPH_ITEM_AGGREGATED) as $type) { if(!isset($this->data[$this->items[$i]["itemid"]][$type])) continue; $data = &$this->data[$this->items[$i]["itemid"]][$type]; if(!isset($data)) continue; if($type == GRAPH_ITEM_AGGREGATED) $calc_fnc = CALC_FNC_ALL; else $calc_fnc = $this->items[$i]["calc_fnc"]; switch($calc_fnc) { case CALC_FNC_ALL: /* use max */ case CALC_FNC_MAX: $val = $data->max; $shift_val = $data->shift_max; break; case CALC_FNC_MIN: $val = $data->min; $shift_val = $data->shift_min; break; case CALC_FNC_AVG: default: $val = $data->avg; $shift_val = $data->shift_avg; } if(!isset($val)) continue; for($ci=0; $ci < min(count($val),count($shift_val)); $ci++) $val[$ci] += $shift_val[$ci]; if(!isset($maxY)) { if(isset($val) && count($val) > 0) { $maxY = max($val); } } else { $maxY = max($maxY, max($val)); } } } if(isset($maxY)&&($maxY>0)) { $exp = floor(log10($maxY)); $mant = $maxY/pow(10,$exp); } else { $exp=0; $mant=0; } $mant=(floor($mant*1.1*10/6)+1)*6/10; $maxY = $mant*pow(10,$exp); return $maxY; } } function selectData() { global $DB_TYPE; $this->data = array(); $now = time(NULL); if(isset($this->stime)) { $this->from_time = $this->stime; $this->to_time = $this->stime + $this->period; } else { $this->to_time = $now - 3600 * $this->from; $this->from_time = $this->to_time - $this->period; } $p = $this->to_time - $this->from_time; $z = $p - $this->from_time % $p; $x = $this->sizeX - 1; for($i=0; $i < $this->num; $i++) { $type = $this->items[$i]["calc_type"]; if($type == GRAPH_ITEM_AGGREGATED) { /* skip current period */ $from_time = $this->from_time - $this->period * $this->items[$i]["periods_cnt"]; $to_time = $this->from_time; } else { $from_time = $this->from_time; $to_time = $this->to_time; } $calc_field = 'round('.$x.'*(mod(clock+'.$z.','.$p.'))/('.$p.'),0)'; /* required for 'group by' support of Oracle */ $sql_arr = array(); if(($this->period / $this->sizeX) <= (ZBX_MAX_TREND_DIFF / ZBX_GRAPH_MAX_SKIP_CELL)) { array_push($sql_arr, 'select itemid,'.$calc_field.' as i,'. ' count(*) as count,avg(value) as avg,min(value) as min,'. ' max(value) as max,max(clock) as clock'. ' from history where itemid='.$this->items[$i]['itemid'].' and clock>='.$from_time. ' and clock<='.$to_time.' group by itemid,'.$calc_field , 'select itemid,'.$calc_field.' as i,'. ' count(*) as count,avg(value) as avg,min(value) as min,'. ' max(value) as max,max(clock) as clock'. ' from history_uint where itemid='.$this->items[$i]['itemid'].' and clock>='.$from_time. ' and clock<='.$to_time.' group by itemid,'.$calc_field ); } else { array_push($sql_arr, 'select itemid,'.$calc_field.' as i,'. ' sum(num) as count,avg(value_avg) as avg,min(value_min) as min,'. ' max(value_max) as max,max(clock) as clock'. ' from trends where itemid='.$this->items[$i]['itemid'].' and clock>='.$from_time. ' and clock<='.$to_time.' group by itemid,'.$calc_field ); } $curr_data = &$this->data[$this->items[$i]["itemid"]][$type]; $curr_data->count = NULL; $curr_data->min = NULL; $curr_data->max = NULL; $curr_data->avg = NULL; $curr_data->clock = NULL; foreach($sql_arr as $sql) { $result=DBselect($sql); while($row=DBfetch($result)) { $idx=$row["i"]; $curr_data->count[$idx] = $row["count"]; $curr_data->min[$idx] = $row["min"]; $curr_data->max[$idx] = $row["max"]; $curr_data->avg[$idx] = $row["avg"]; $curr_data->clock[$idx] = $row["clock"]; $curr_data->shift_min[$idx] = 0; $curr_data->shift_max[$idx] = 0; $curr_data->shift_avg[$idx] = 0; } } /* calculate missed points */ $first_idx = 0; /* ci - current index cj - count of missed dx - offset to first value */ for($ci = 0, $cj=0; $ci < $this->sizeX; $ci++) { if(!isset($curr_data->count[$ci]) || $curr_data->count[$ci] == 0) { $curr_data->count[$ci] = 0; $curr_data->shift_min[$ci] = 0; $curr_data->shift_max[$ci] = 0; $curr_data->shift_avg[$ci] = 0; $cj++; } else if($cj > 0) { $dx = $cj + 1; $first_idx = $ci - $dx; if($first_idx < 0) $first_idx = $ci; // if no data from start of graph get current data as first data for(;$cj > 0; $cj--) { foreach(array('clock','min','max','avg') as $var_name) { $var = &$curr_data->$var_name; if($first_idx == $ci && $var_name == 'clock') { $var[$ci - ($dx - $cj)] = $var[$first_idx] - ($p / $this->sizeX * ($dx - $cj)); continue; } $dy = $var[$ci] - $var[$first_idx]; $var[$ci - ($dx - $cj)] = $var[$first_idx] + ($cj * $dy) / $dx; } } } } if($cj > 0 && $ci > $cj) { $dx = $cj + 1; $first_idx = $ci - $dx; for(;$cj > 0; $cj--) { foreach(array('clock','min','max','avg') as $var_name) { $var = &$curr_data->$var_name; if($var_name == 'clock') { $var[$first_idx + ($dx - $cj)] = $var[$first_idx] + ($p / $this->sizeX * ($dx - $cj)); continue; } $var[$first_idx + ($dx - $cj)] = $var[$first_idx]; } } } /* end of missed points calculation */ } /* calculte shift for stacked graphs */ if($this->type == GRAPH_TYPE_STACKED) { for($i=1; $i<$this->num; $i++) { $curr_data = &$this->data[$this->items[$i]["itemid"]][$this->items[$i]["calc_type"]]; if(!isset($curr_data)) continue; for($j = $i-1; $j >= 0; $j--) { if($this->items[$j]["axisside"] != $this->items[$i]["axisside"]) continue; $prev_data = &$this->data[$this->items[$j]["itemid"]][$this->items[$j]["calc_type"]]; if(!isset($prev_data)) continue; for($ci = 0; $ci < $this->sizeX; $ci++) { foreach(array('min','max','avg') as $var_name) { $shift_var_name = 'shift_'.$var_name; $curr_shift = &$curr_data->$shift_var_name; $curr_var = &$curr_data->$var_name; $prev_shift = &$prev_data->$shift_var_name; $prev_var = &$prev_data->$var_name; $curr_shift[$ci] = $prev_var[$ci] + $prev_shift[$ci]; } } break; } } } /* end calculation of stacked graphs */ } function DrawLeftSide() { if($this->yaxisleft == 1) { $minY = $this->m_minY[GRAPH_YAXIS_SIDE_LEFT]; $maxY = $this->m_maxY[GRAPH_YAXIS_SIDE_LEFT]; for($item=0;$item<$this->num;$item++) { if($this->items[$item]["axisside"] == GRAPH_YAXIS_SIDE_LEFT) { $units=$this->items[$item]["units"]; break; } } for($i=0;$i<=6;$i++) { $str = str_pad(convert_units($this->sizeY*$i/6*($maxY-$minY)/$this->sizeY+$minY,$units),10," ", STR_PAD_LEFT); ImageString($this->im, 1, 5, $this->sizeY-$this->sizeY*$i/6-4+$this->shiftY, $str, $this->GetColor("Dark Red No Alpha")); } } } function DrawRightSide() { if($this->yaxisright == 1) { $minY = $this->m_minY[GRAPH_YAXIS_SIDE_RIGHT]; $maxY = $this->m_maxY[GRAPH_YAXIS_SIDE_RIGHT]; for($item=0;$item<$this->num;$item++) { if($this->items[$item]["axisside"] == GRAPH_YAXIS_SIDE_RIGHT) { $units=$this->items[$item]["units"]; break; } } for($i=0;$i<=6;$i++) { $str = str_pad(convert_units($this->sizeY*$i/6*($maxY-$minY)/$this->sizeY+$minY,$units),10," "); ImageString($this->im, 1, $this->sizeX+$this->shiftXleft+2, $this->sizeY-$this->sizeY*$i/6-4+$this->shiftY, $str, $this->GetColor("Dark Red No Alpha")); } } } function Draw() { $start_time=getmicrotime(); // $this->im = imagecreate($this->sizeX+$this->shiftX+61,$this->sizeY+2*$this->shiftY+40); set_image_header(); check_authorisation(); $this->selectData(); $this->m_minY[GRAPH_YAXIS_SIDE_LEFT] = $this->calculateMinY(GRAPH_YAXIS_SIDE_LEFT); $this->m_minY[GRAPH_YAXIS_SIDE_RIGHT] = $this->calculateMinY(GRAPH_YAXIS_SIDE_RIGHT); $this->m_maxY[GRAPH_YAXIS_SIDE_LEFT] = $this->calculateMaxY(GRAPH_YAXIS_SIDE_LEFT); $this->m_maxY[GRAPH_YAXIS_SIDE_RIGHT] = $this->calculateMaxY(GRAPH_YAXIS_SIDE_RIGHT); $this->updateShifts(); $this->calcTriggers(); $this->fullSizeX = $this->sizeX+$this->shiftXleft+$this->shiftXright+1; $this->fullSizeY = $this->sizeY+$this->shiftY+62+12*($this->num+ (($this->sizeY < 120) ? 0 : count($this->triggers)))+8; if(function_exists("ImageColorExactAlpha")&&function_exists("ImageCreateTrueColor")&&@imagecreatetruecolor(1,1)) $this->im = ImageCreateTrueColor($this->fullSizeX,$this->fullSizeY); else $this->im = imagecreate($this->fullSizeX,$this->fullSizeY); $this->initColors(); $this->drawRectangle(); $this->drawHeader(); if($this->num==0) { // $this->noDataFound(); } $this->drawWorkPeriod(); $this->drawGrid(); $maxX = $this->sizeX; // For each metric for($item = 0; $item < $this->num; $item++) { $minY = $this->m_minY[$this->items[$item]["axisside"]]; $maxY = $this->m_maxY[$this->items[$item]["axisside"]]; $data = &$this->data[$this->items[$item]["itemid"]][$this->items[$item]["calc_type"]]; if(!isset($data)) continue; if($this->items[$item]["calc_type"] == GRAPH_ITEM_AGGREGATED) { $drawtype = GRAPH_DRAW_TYPE_LINE; $max_color = $this->GetColor("HistoryMax"); $avg_color = $this->GetColor("HistoryAvg"); $min_color = $this->GetColor("HistoryMin"); $minmax_color = $this->GetColor("HistoryMinMax"); $calc_fnc = CALC_FNC_ALL; } else { $drawtype = $this->items[$item]["drawtype"]; $max_color = $this->GetColor("ValueMax"); $avg_color = $this->GetColor($this->items[$item]["color"]); $min_color = $this->GetColor("ValueMin"); $minmax_color = $this->GetColor("ValueMinMax"); $calc_fnc = $this->items[$item]["calc_fnc"]; } // For each X for($i = 1, $j = 0; $i < $maxX; $i++) // new point { if($data->count[$i] == 0) continue; $diff = abs($data->clock[$i] - $data->clock[$j]); $cell = ($this->to_time - $this->from_time)/$this->sizeX; $delay = $this->items[$item]["delay"]; if($cell > $delay) $draw = $diff < ZBX_GRAPH_MAX_SKIP_CELL * $cell; else $draw = $diff < ZBX_GRAPH_MAX_SKIP_DELAY * $delay; if($draw == false && $this->items[$item]["calc_type"] == GRAPH_ITEM_AGGREGATED) $draw = $i - $j < 5; if($this->items[$item]["type"] == ITEM_TYPE_TRAPPER) $draw = true; if($draw) { $this->drawElement( $data, $i, $j, 0, $this->sizeX, $minY, $maxY, $drawtype, $max_color, $avg_color, $min_color, $minmax_color, $calc_fnc ); } $j = $i; } } $this->DrawLeftSide(); $this->DrawRightSide(); $this->drawTriggers(); $this->drawLogo(); $this->drawLegend(); $end_time=getmicrotime(); $str=sprintf("%0.2f",($end_time-$start_time)); ImageString($this->im, 0,$this->fullSizeX-120,$this->fullSizeY-12,"Generated in $str sec", $this->GetColor("Gray")); ImageOut($this->im); ImageDestroy($this->im); } } ?>