1<?php 2/* 3 +----------------------------------------------------------------------+ 4 | PHP Version 5 | 5 +----------------------------------------------------------------------+ 6 | Copyright (c) 1997-2004 The PHP Group | 7 +----------------------------------------------------------------------+ 8 | This source file is subject to version 3.0 of the PHP license, | 9 | that is bundled with this package in the file LICENSE, and is | 10 | available through the world-wide-web at the following url: | 11 | http://www.php.net/license/3_0.txt. | 12 | If you did not receive a copy of the PHP license and are unable to | 13 | obtain it through the world-wide-web, please send a note to | 14 | license@php.net so we can mail you a copy immediately. | 15 +----------------------------------------------------------------------+ 16 | Author: Harun Yayli <harunyayli at gmail.com> | 17 +----------------------------------------------------------------------+ 18*/ 19 20$VERSION='$Id$'; 21 22define('ADMIN_USERNAME','memcache'); // Admin Username 23define('ADMIN_PASSWORD','password'); // Admin Password 24define('DATE_FORMAT','Y/m/d H:i:s'); 25define('GRAPH_SIZE',200); 26define('MAX_ITEM_DUMP',50); 27 28$MEMCACHE_SERVERS[] = 'mymemcache-server1:11211'; // add more as an array 29$MEMCACHE_SERVERS[] = 'mymemcache-server2:11211'; // add more as an array 30 31 32////////// END OF DEFAULT CONFIG AREA ///////////////////////////////////////////////////////////// 33 34///////////////// Password protect //////////////////////////////////////////////////////////////// 35if (!isset($_SERVER['PHP_AUTH_USER']) || !isset($_SERVER['PHP_AUTH_PW']) || 36 $_SERVER['PHP_AUTH_USER'] != ADMIN_USERNAME ||$_SERVER['PHP_AUTH_PW'] != ADMIN_PASSWORD) { 37 Header("WWW-Authenticate: Basic realm=\"Memcache Login\""); 38 Header("HTTP/1.0 401 Unauthorized"); 39 40 echo <<<EOB 41 <html><body> 42 <h1>Rejected!</h1> 43 <big>Wrong Username or Password!</big> 44 </body></html> 45EOB; 46 exit; 47} 48 49///////////MEMCACHE FUNCTIONS ///////////////////////////////////////////////////////////////////// 50 51function get_host_port_from_server($server){ 52 $values = explode(':', $server); 53 if (($values[0] == 'unix') && (!is_numeric( $values[1]))) { 54 return array($server, 0); 55 } 56 else { 57 return $values; 58 } 59} 60 61function sendMemcacheCommands($command){ 62 global $MEMCACHE_SERVERS; 63 $result = array(); 64 65 foreach($MEMCACHE_SERVERS as $server){ 66 $strs = get_host_port_from_server($server); 67 $host = $strs[0]; 68 $port = $strs[1]; 69 $result[$server] = sendMemcacheCommand($host,$port,$command); 70 } 71 return $result; 72} 73function sendMemcacheCommand($server,$port,$command){ 74 75 $s = @fsockopen($server,$port); 76 if (!$s){ 77 die("Cant connect to:".$server.':'.$port); 78 } 79 80 fwrite($s, $command."\r\n"); 81 82 $buf=''; 83 while ((!feof($s))) { 84 $buf .= fgets($s, 256); 85 if (strpos($buf,"END\r\n")!==false){ // stat says end 86 break; 87 } 88 if (strpos($buf,"DELETED\r\n")!==false || strpos($buf,"NOT_FOUND\r\n")!==false){ // delete says these 89 break; 90 } 91 if (strpos($buf,"OK\r\n")!==false){ // flush_all says ok 92 break; 93 } 94 } 95 fclose($s); 96 return parseMemcacheResults($buf); 97} 98function parseMemcacheResults($str){ 99 100 $res = array(); 101 $lines = explode("\r\n",$str); 102 $cnt = count($lines); 103 for($i=0; $i< $cnt; $i++){ 104 $line = $lines[$i]; 105 $l = explode(' ',$line,3); 106 if (count($l)==3){ 107 $res[$l[0]][$l[1]]=$l[2]; 108 if ($l[0]=='VALUE'){ // next line is the value 109 $res[$l[0]][$l[1]] = array(); 110 list ($flag,$size)=explode(' ',$l[2]); 111 $res[$l[0]][$l[1]]['stat']=array('flag'=>$flag,'size'=>$size); 112 $res[$l[0]][$l[1]]['value']=$lines[++$i]; 113 } 114 }elseif($line=='DELETED' || $line=='NOT_FOUND' || $line=='OK'){ 115 return $line; 116 } 117 } 118 return $res; 119 120} 121 122function dumpCacheSlab($server,$slabId,$limit){ 123 list($host,$port) = get_host_port_from_server($server); 124 $resp = sendMemcacheCommand($host,$port,'stats cachedump '.$slabId.' '.$limit); 125 126 return $resp; 127 128} 129 130function flushServer($server){ 131 list($host,$port) = get_host_port_from_server($server); 132 $resp = sendMemcacheCommand($host,$port,'flush_all'); 133 return $resp; 134} 135function getCacheItems(){ 136 $items = sendMemcacheCommands('stats items'); 137 $serverItems = array(); 138 $totalItems = array(); 139 foreach ($items as $server=>$itemlist){ 140 $serverItems[$server] = array(); 141 $totalItems[$server]=0; 142 if (!isset($itemlist['STAT'])){ 143 continue; 144 } 145 146 $iteminfo = $itemlist['STAT']; 147 148 foreach($iteminfo as $keyinfo=>$value){ 149 if (preg_match('/items\:(\d+?)\:(.+?)$/',$keyinfo,$matches)){ 150 $serverItems[$server][$matches[1]][$matches[2]] = $value; 151 if ($matches[2]=='number'){ 152 $totalItems[$server] +=$value; 153 } 154 } 155 } 156 } 157 return array('items'=>$serverItems,'counts'=>$totalItems); 158} 159function getMemcacheStats($total=true){ 160 $resp = sendMemcacheCommands('stats'); 161 if ($total){ 162 $res = array(); 163 foreach($resp as $server=>$r){ 164 foreach($r['STAT'] as $key=>$row){ 165 if (!isset($res[$key])){ 166 $res[$key]=null; 167 } 168 switch ($key){ 169 case 'pid': 170 $res['pid'][$server]=$row; 171 break; 172 case 'uptime': 173 $res['uptime'][$server]=$row; 174 break; 175 case 'time': 176 $res['time'][$server]=$row; 177 break; 178 case 'version': 179 $res['version'][$server]=$row; 180 break; 181 case 'pointer_size': 182 $res['pointer_size'][$server]=$row; 183 break; 184 case 'rusage_user': 185 $res['rusage_user'][$server]=$row; 186 break; 187 case 'rusage_system': 188 $res['rusage_system'][$server]=$row; 189 break; 190 case 'curr_items': 191 $res['curr_items']+=$row; 192 break; 193 case 'total_items': 194 $res['total_items']+=$row; 195 break; 196 case 'bytes': 197 $res['bytes']+=$row; 198 break; 199 case 'curr_connections': 200 $res['curr_connections']+=$row; 201 break; 202 case 'total_connections': 203 $res['total_connections']+=$row; 204 break; 205 case 'connection_structures': 206 $res['connection_structures']+=$row; 207 break; 208 case 'cmd_get': 209 $res['cmd_get']+=$row; 210 break; 211 case 'cmd_set': 212 $res['cmd_set']+=$row; 213 break; 214 case 'get_hits': 215 $res['get_hits']+=$row; 216 break; 217 case 'get_misses': 218 $res['get_misses']+=$row; 219 break; 220 case 'evictions': 221 $res['evictions']+=$row; 222 break; 223 case 'bytes_read': 224 $res['bytes_read']+=$row; 225 break; 226 case 'bytes_written': 227 $res['bytes_written']+=$row; 228 break; 229 case 'limit_maxbytes': 230 $res['limit_maxbytes']+=$row; 231 break; 232 case 'threads': 233 $res['rusage_system'][$server]=$row; 234 break; 235 } 236 } 237 } 238 return $res; 239 } 240 return $resp; 241} 242 243////////////////////////////////////////////////////// 244 245// 246// don't cache this page 247// 248header("Cache-Control: no-store, no-cache, must-revalidate"); // HTTP/1.1 249header("Cache-Control: post-check=0, pre-check=0", false); 250header("Pragma: no-cache"); // HTTP/1.0 251 252function duration($ts) { 253 global $time; 254 $years = (int)((($time - $ts)/(7*86400))/52.177457); 255 $rem = (int)(($time-$ts)-($years * 52.177457 * 7 * 86400)); 256 $weeks = (int)(($rem)/(7*86400)); 257 $days = (int)(($rem)/86400) - $weeks*7; 258 $hours = (int)(($rem)/3600) - $days*24 - $weeks*7*24; 259 $mins = (int)(($rem)/60) - $hours*60 - $days*24*60 - $weeks*7*24*60; 260 $str = ''; 261 if($years==1) $str .= "$years year, "; 262 if($years>1) $str .= "$years years, "; 263 if($weeks==1) $str .= "$weeks week, "; 264 if($weeks>1) $str .= "$weeks weeks, "; 265 if($days==1) $str .= "$days day,"; 266 if($days>1) $str .= "$days days,"; 267 if($hours == 1) $str .= " $hours hour and"; 268 if($hours>1) $str .= " $hours hours and"; 269 if($mins == 1) $str .= " 1 minute"; 270 else $str .= " $mins minutes"; 271 return $str; 272} 273 274// create graphics 275// 276function graphics_avail() { 277 return extension_loaded('gd'); 278} 279 280function bsize($s) { 281 foreach (array('','K','M','G') as $i => $k) { 282 if ($s < 1024) break; 283 $s/=1024; 284 } 285 return sprintf("%5.1f %sBytes",$s,$k); 286} 287 288// create menu entry 289function menu_entry($ob,$title) { 290 global $PHP_SELF; 291 if ($ob==$_GET['op']){ 292 return "<li><a class=\"child_active\" href=\"$PHP_SELF&op=$ob\">$title</a></li>"; 293 } 294 return "<li><a class=\"active\" href=\"$PHP_SELF&op=$ob\">$title</a></li>"; 295} 296 297function getHeader(){ 298 $header = <<<EOB 299<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 300<html> 301<head><title>MEMCACHE INFO</title> 302<style type="text/css"><!-- 303body { background:white; font-size:100.01%; margin:0; padding:0; } 304body,p,td,th,input,submit { font-size:0.8em;font-family:arial,helvetica,sans-serif; } 305* html body {font-size:0.8em} 306* html p {font-size:0.8em} 307* html td {font-size:0.8em} 308* html th {font-size:0.8em} 309* html input {font-size:0.8em} 310* html submit {font-size:0.8em} 311td { vertical-align:top } 312a { color:black; font-weight:none; text-decoration:none; } 313a:hover { text-decoration:underline; } 314div.content { padding:1em 1em 1em 1em; position:absolute; width:97%; z-index:100; } 315 316h1.memcache { background:rgb(153,153,204); margin:0; padding:0.5em 1em 0.5em 1em; } 317* html h1.memcache { margin-bottom:-7px; } 318h1.memcache a:hover { text-decoration:none; color:rgb(90,90,90); } 319h1.memcache span.logo { 320 background:rgb(119,123,180); 321 color:black; 322 border-right: solid black 1px; 323 border-bottom: solid black 1px; 324 font-style:italic; 325 font-size:1em; 326 padding-left:1.2em; 327 padding-right:1.2em; 328 text-align:right; 329 display:block; 330 width:130px; 331 } 332h1.memcache span.logo span.name { color:white; font-size:0.7em; padding:0 0.8em 0 2em; } 333h1.memcache span.nameinfo { color:white; display:inline; font-size:0.4em; margin-left: 3em; } 334h1.memcache div.copy { color:black; font-size:0.4em; position:absolute; right:1em; } 335hr.memcache { 336 background:white; 337 border-bottom:solid rgb(102,102,153) 1px; 338 border-style:none; 339 border-top:solid rgb(102,102,153) 10px; 340 height:12px; 341 margin:0; 342 margin-top:1px; 343 padding:0; 344} 345 346ol,menu { margin:1em 0 0 0; padding:0.2em; margin-left:1em;} 347ol.menu li { display:inline; margin-right:0.7em; list-style:none; font-size:85%} 348ol.menu a { 349 background:rgb(153,153,204); 350 border:solid rgb(102,102,153) 2px; 351 color:white; 352 font-weight:bold; 353 margin-right:0em; 354 padding:0.1em 0.5em 0.1em 0.5em; 355 text-decoration:none; 356 margin-left: 5px; 357 } 358ol.menu a.child_active { 359 background:rgb(153,153,204); 360 border:solid rgb(102,102,153) 2px; 361 color:white; 362 font-weight:bold; 363 margin-right:0em; 364 padding:0.1em 0.5em 0.1em 0.5em; 365 text-decoration:none; 366 border-left: solid black 5px; 367 margin-left: 0px; 368 } 369ol.menu span.active { 370 background:rgb(153,153,204); 371 border:solid rgb(102,102,153) 2px; 372 color:black; 373 font-weight:bold; 374 margin-right:0em; 375 padding:0.1em 0.5em 0.1em 0.5em; 376 text-decoration:none; 377 border-left: solid black 5px; 378 } 379ol.menu span.inactive { 380 background:rgb(193,193,244); 381 border:solid rgb(182,182,233) 2px; 382 color:white; 383 font-weight:bold; 384 margin-right:0em; 385 padding:0.1em 0.5em 0.1em 0.5em; 386 text-decoration:none; 387 margin-left: 5px; 388 } 389ol.menu a:hover { 390 background:rgb(193,193,244); 391 text-decoration:none; 392 } 393 394 395div.info { 396 background:rgb(204,204,204); 397 border:solid rgb(204,204,204) 1px; 398 margin-bottom:1em; 399 } 400div.info h2 { 401 background:rgb(204,204,204); 402 color:black; 403 font-size:1em; 404 margin:0; 405 padding:0.1em 1em 0.1em 1em; 406 } 407div.info table { 408 border:solid rgb(204,204,204) 1px; 409 border-spacing:0; 410 width:100%; 411 } 412div.info table th { 413 background:rgb(204,204,204); 414 color:white; 415 margin:0; 416 padding:0.1em 1em 0.1em 1em; 417 } 418div.info table th a.sortable { color:black; } 419div.info table tr.tr-0 { background:rgb(238,238,238); } 420div.info table tr.tr-1 { background:rgb(221,221,221); } 421div.info table td { padding:0.3em 1em 0.3em 1em; } 422div.info table td.td-0 { border-right:solid rgb(102,102,153) 1px; white-space:nowrap; } 423div.info table td.td-n { border-right:solid rgb(102,102,153) 1px; } 424div.info table td h3 { 425 color:black; 426 font-size:1.1em; 427 margin-left:-0.3em; 428 } 429.td-0 a , .td-n a, .tr-0 a , tr-1 a { 430 text-decoration:underline; 431} 432div.graph { margin-bottom:1em } 433div.graph h2 { background:rgb(204,204,204);; color:black; font-size:1em; margin:0; padding:0.1em 1em 0.1em 1em; } 434div.graph table { border:solid rgb(204,204,204) 1px; color:black; font-weight:normal; width:100%; } 435div.graph table td.td-0 { background:rgb(238,238,238); } 436div.graph table td.td-1 { background:rgb(221,221,221); } 437div.graph table td { padding:0.2em 1em 0.4em 1em; } 438 439div.div1,div.div2 { margin-bottom:1em; width:35em; } 440div.div3 { position:absolute; left:40em; top:1em; width:580px; } 441//div.div3 { position:absolute; left:37em; top:1em; right:1em; } 442 443div.sorting { margin:1.5em 0em 1.5em 2em } 444.center { text-align:center } 445.aright { position:absolute;right:1em } 446.right { text-align:right } 447.ok { color:rgb(0,200,0); font-weight:bold} 448.failed { color:rgb(200,0,0); font-weight:bold} 449 450span.box { 451 border: black solid 1px; 452 border-right:solid black 2px; 453 border-bottom:solid black 2px; 454 padding:0 0.5em 0 0.5em; 455 margin-right:1em; 456} 457span.green { background:#60F060; padding:0 0.5em 0 0.5em} 458span.red { background:#D06030; padding:0 0.5em 0 0.5em } 459 460div.authneeded { 461 background:rgb(238,238,238); 462 border:solid rgb(204,204,204) 1px; 463 color:rgb(200,0,0); 464 font-size:1.2em; 465 font-weight:bold; 466 padding:2em; 467 text-align:center; 468 } 469 470input { 471 background:rgb(153,153,204); 472 border:solid rgb(102,102,153) 2px; 473 color:white; 474 font-weight:bold; 475 margin-right:1em; 476 padding:0.1em 0.5em 0.1em 0.5em; 477 } 478//--> 479</style> 480</head> 481<body> 482<div class="head"> 483 <h1 class="memcache"> 484 <span class="logo"><a href="http://pecl.php.net/package/memcache">memcache</a></span> 485 <span class="nameinfo">memcache.php by <a href="http://livebookmark.net">Harun Yayli</a></span> 486 </h1> 487 <hr class="memcache"> 488</div> 489<div class=content> 490EOB; 491 492 return $header; 493} 494function getFooter(){ 495 global $VERSION; 496 $footer = '</div><!-- Based on apc.php '.$VERSION.'--></body> 497</html> 498'; 499 500 return $footer; 501 502} 503function getMenu(){ 504 global $PHP_SELF; 505echo "<ol class=menu>"; 506if ($_GET['op']!=4){ 507echo <<<EOB 508 <li><a href="$PHP_SELF&op={$_GET['op']}">Refresh Data</a></li> 509EOB; 510} 511else { 512echo <<<EOB 513 <li><a href="$PHP_SELF&op=2}">Back</a></li> 514EOB; 515} 516echo 517 menu_entry(1,'View Host Stats'), 518 menu_entry(2,'Variables'); 519 520echo <<<EOB 521 </ol> 522 <br/> 523EOB; 524} 525 526// TODO, AUTH 527 528$_GET['op'] = !isset($_GET['op'])? '1':$_GET['op']; 529$PHP_SELF= isset($_SERVER['PHP_SELF']) ? htmlentities(strip_tags($_SERVER['PHP_SELF'],'')) : ''; 530 531$PHP_SELF=$PHP_SELF.'?'; 532$time = time(); 533// sanitize _GET 534 535foreach($_GET as $key=>$g){ 536 $_GET[$key]=htmlentities($g); 537} 538 539 540// singleout 541// when singleout is set, it only gives details for that server. 542if (isset($_GET['singleout']) && $_GET['singleout']>=0 && $_GET['singleout'] <count($MEMCACHE_SERVERS)){ 543 $MEMCACHE_SERVERS = array($MEMCACHE_SERVERS[$_GET['singleout']]); 544} 545 546// display images 547if (isset($_GET['IMG'])){ 548 $memcacheStats = getMemcacheStats(); 549 $memcacheStatsSingle = getMemcacheStats(false); 550 551 if (!graphics_avail()) { 552 exit(0); 553 } 554 555 function fill_box($im, $x, $y, $w, $h, $color1, $color2,$text='',$placeindex='') { 556 global $col_black; 557 $x1=$x+$w-1; 558 $y1=$y+$h-1; 559 560 imagerectangle($im, $x, $y1, $x1+1, $y+1, $col_black); 561 if($y1>$y) imagefilledrectangle($im, $x, $y, $x1, $y1, $color2); 562 else imagefilledrectangle($im, $x, $y1, $x1, $y, $color2); 563 imagerectangle($im, $x, $y1, $x1, $y, $color1); 564 if ($text) { 565 if ($placeindex>0) { 566 567 if ($placeindex<16) 568 { 569 $px=5; 570 $py=$placeindex*12+6; 571 imagefilledrectangle($im, $px+90, $py+3, $px+90-4, $py-3, $color2); 572 imageline($im,$x,$y+$h/2,$px+90,$py,$color2); 573 imagestring($im,2,$px,$py-6,$text,$color1); 574 575 } else { 576 if ($placeindex<31) { 577 $px=$x+40*2; 578 $py=($placeindex-15)*12+6; 579 } else { 580 $px=$x+40*2+100*intval(($placeindex-15)/15); 581 $py=($placeindex%15)*12+6; 582 } 583 imagefilledrectangle($im, $px, $py+3, $px-4, $py-3, $color2); 584 imageline($im,$x+$w,$y+$h/2,$px,$py,$color2); 585 imagestring($im,2,$px+2,$py-6,$text,$color1); 586 } 587 } else { 588 imagestring($im,4,$x+5,$y1-16,$text,$color1); 589 } 590 } 591 } 592 593 594 function fill_arc($im, $centerX, $centerY, $diameter, $start, $end, $color1,$color2,$text='',$placeindex=0) { 595 $r=$diameter/2; 596 $w=deg2rad((360+$start+($end-$start)/2)%360); 597 598 599 if (function_exists("imagefilledarc")) { 600 // exists only if GD 2.0.1 is avaliable 601 imagefilledarc($im, $centerX+1, $centerY+1, $diameter, $diameter, $start, $end, $color1, IMG_ARC_PIE); 602 imagefilledarc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color2, IMG_ARC_PIE); 603 imagefilledarc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color1, IMG_ARC_NOFILL|IMG_ARC_EDGED); 604 } else { 605 imagearc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color2); 606 imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($start)) * $r, $centerY + sin(deg2rad($start)) * $r, $color2); 607 imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($start+1)) * $r, $centerY + sin(deg2rad($start)) * $r, $color2); 608 imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($end-1)) * $r, $centerY + sin(deg2rad($end)) * $r, $color2); 609 imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($end)) * $r, $centerY + sin(deg2rad($end)) * $r, $color2); 610 imagefill($im,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2, $color2); 611 } 612 if ($text) { 613 if ($placeindex>0) { 614 imageline($im,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$diameter, $placeindex*12,$color1); 615 imagestring($im,4,$diameter, $placeindex*12,$text,$color1); 616 617 } else { 618 imagestring($im,4,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$text,$color1); 619 } 620 } 621 } 622 $size = GRAPH_SIZE; // image size 623 $image = imagecreate($size+50, $size+10); 624 625 $col_white = imagecolorallocate($image, 0xFF, 0xFF, 0xFF); 626 $col_red = imagecolorallocate($image, 0xD0, 0x60, 0x30); 627 $col_green = imagecolorallocate($image, 0x60, 0xF0, 0x60); 628 $col_black = imagecolorallocate($image, 0, 0, 0); 629 630 imagecolortransparent($image,$col_white); 631 632 switch ($_GET['IMG']){ 633 case 1: // pie chart 634 $tsize=$memcacheStats['limit_maxbytes']; 635 $avail=$tsize-$memcacheStats['bytes']; 636 $x=$y=$size/2; 637 $angle_from = 0; 638 $fuzz = 0.000001; 639 640 foreach($memcacheStatsSingle as $serv=>$mcs) { 641 $free = $mcs['STAT']['limit_maxbytes']-$mcs['STAT']['bytes']; 642 $used = $mcs['STAT']['bytes']; 643 644 645 if ($free>0){ 646 // draw free 647 $angle_to = ($free*360)/$tsize; 648 $perc =sprintf("%.2f%%", ($free *100) / $tsize) ; 649 650 fill_arc($image,$x,$y,$size,$angle_from,$angle_from + $angle_to ,$col_black,$col_green,$perc); 651 $angle_from = $angle_from + $angle_to ; 652 } 653 if ($used>0){ 654 // draw used 655 $angle_to = ($used*360)/$tsize; 656 $perc =sprintf("%.2f%%", ($used *100) / $tsize) ; 657 fill_arc($image,$x,$y,$size,$angle_from,$angle_from + $angle_to ,$col_black,$col_red, '('.$perc.')' ); 658 $angle_from = $angle_from+ $angle_to ; 659 } 660 } 661 662 break; 663 664 case 2: // hit miss 665 666 $hits = ($memcacheStats['get_hits']==0) ? 1:$memcacheStats['get_hits']; 667 $misses = ($memcacheStats['get_misses']==0) ? 1:$memcacheStats['get_misses']; 668 $total = $hits + $misses ; 669 670 fill_box($image, 30,$size,50,-$hits*($size-21)/$total,$col_black,$col_green,sprintf("%.1f%%",$hits*100/$total)); 671 fill_box($image,130,$size,50,-max(4,($total-$hits)*($size-21)/$total),$col_black,$col_red,sprintf("%.1f%%",$misses*100/$total)); 672 break; 673 674 } 675 header("Content-type: image/png"); 676 imagepng($image); 677 exit; 678} 679 680echo getHeader(); 681echo getMenu(); 682 683switch ($_GET['op']) { 684 685 case 1: // host stats 686 $phpversion = phpversion(); 687 $memcacheStats = getMemcacheStats(); 688 $memcacheStatsSingle = getMemcacheStats(false); 689 690 $mem_size = $memcacheStats['limit_maxbytes']; 691 $mem_used = $memcacheStats['bytes']; 692 $mem_avail= $mem_size-$mem_used; 693 $startTime = time()-array_sum($memcacheStats['uptime']); 694 695 $curr_items = $memcacheStats['curr_items']; 696 $total_items = $memcacheStats['total_items']; 697 $hits = ($memcacheStats['get_hits']==0) ? 1:$memcacheStats['get_hits']; 698 $misses = ($memcacheStats['get_misses']==0) ? 1:$memcacheStats['get_misses']; 699 $sets = $memcacheStats['cmd_set']; 700 701 $req_rate = sprintf("%.2f",($hits+$misses)/($time-$startTime)); 702 $hit_rate = sprintf("%.2f",($hits)/($time-$startTime)); 703 $miss_rate = sprintf("%.2f",($misses)/($time-$startTime)); 704 $set_rate = sprintf("%.2f",($sets)/($time-$startTime)); 705 706 echo <<< EOB 707 <div class="info div1"><h2>General Cache Information</h2> 708 <table cellspacing=0><tbody> 709 <tr class=tr-1><td class=td-0>PHP Version</td><td>$phpversion</td></tr> 710EOB; 711 echo "<tr class=tr-0><td class=td-0>Memcached Host". ((count($MEMCACHE_SERVERS)>1) ? 's':'')."</td><td>"; 712 $i=0; 713 if (!isset($_GET['singleout']) && count($MEMCACHE_SERVERS)>1){ 714 foreach($MEMCACHE_SERVERS as $server){ 715 echo ($i+1).'. <a href="'.$PHP_SELF.'&singleout='.$i++.'">'.$server.'</a><br/>'; 716 } 717 } 718 else{ 719 echo '1.'.$MEMCACHE_SERVERS[0]; 720 } 721 if (isset($_GET['singleout'])){ 722 echo '<a href="'.$PHP_SELF.'">(all servers)</a><br/>'; 723 } 724 echo "</td></tr>\n"; 725 echo "<tr class=tr-1><td class=td-0>Total Memcache Cache</td><td>".bsize($memcacheStats['limit_maxbytes'])."</td></tr>\n"; 726 727 echo <<<EOB 728 </tbody></table> 729 </div> 730 731 <div class="info div1"><h2>Memcache Server Information</h2> 732EOB; 733 foreach($MEMCACHE_SERVERS as $server){ 734 echo '<table cellspacing=0><tbody>'; 735 echo '<tr class=tr-1><td class=td-1>'.$server.'</td><td><a href="'.$PHP_SELF.'&server='.array_search($server,$MEMCACHE_SERVERS).'&op=6">[<b>Flush this server</b>]</a></td></tr>'; 736 echo '<tr class=tr-0><td class=td-0>Start Time</td><td>',date(DATE_FORMAT,$memcacheStatsSingle[$server]['STAT']['time']-$memcacheStatsSingle[$server]['STAT']['uptime']),'</td></tr>'; 737 echo '<tr class=tr-1><td class=td-0>Uptime</td><td>',duration($memcacheStatsSingle[$server]['STAT']['time']-$memcacheStatsSingle[$server]['STAT']['uptime']),'</td></tr>'; 738 echo '<tr class=tr-0><td class=td-0>Memcached Server Version</td><td>'.$memcacheStatsSingle[$server]['STAT']['version'].'</td></tr>'; 739 echo '<tr class=tr-1><td class=td-0>Used Cache Size</td><td>',bsize($memcacheStatsSingle[$server]['STAT']['bytes']),'</td></tr>'; 740 echo '<tr class=tr-0><td class=td-0>Total Cache Size</td><td>',bsize($memcacheStatsSingle[$server]['STAT']['limit_maxbytes']),'</td></tr>'; 741 echo '</tbody></table>'; 742 } 743 echo <<<EOB 744 745 </div> 746 <div class="graph div3"><h2>Host Status Diagrams</h2> 747 <table cellspacing=0><tbody> 748EOB; 749 750 $size='width='.(GRAPH_SIZE+50).' height='.(GRAPH_SIZE+10); 751 echo <<<EOB 752 <tr> 753 <td class=td-0>Cache Usage</td> 754 <td class=td-1>Hits & Misses</td> 755 </tr> 756EOB; 757 758 echo 759 graphics_avail() ? 760 '<tr>'. 761 "<td class=td-0><img alt=\"\" $size src=\"$PHP_SELF&IMG=1&".(isset($_GET['singleout'])? 'singleout='.$_GET['singleout'].'&':'')."$time\"></td>". 762 "<td class=td-1><img alt=\"\" $size src=\"$PHP_SELF&IMG=2&".(isset($_GET['singleout'])? 'singleout='.$_GET['singleout'].'&':'')."$time\"></td></tr>\n" 763 : "", 764 '<tr>', 765 '<td class=td-0><span class="green box"> </span>Free: ',bsize($mem_avail).sprintf(" (%.1f%%)",$mem_avail*100/$mem_size),"</td>\n", 766 '<td class=td-1><span class="green box"> </span>Hits: ',$hits.sprintf(" (%.1f%%)",$hits*100/($hits+$misses)),"</td>\n", 767 '</tr>', 768 '<tr>', 769 '<td class=td-0><span class="red box"> </span>Used: ',bsize($mem_used ).sprintf(" (%.1f%%)",$mem_used *100/$mem_size),"</td>\n", 770 '<td class=td-1><span class="red box"> </span>Misses: ',$misses.sprintf(" (%.1f%%)",$misses*100/($hits+$misses)),"</td>\n"; 771 echo <<< EOB 772 </tr> 773 </tbody></table> 774<br/> 775 <div class="info"><h2>Cache Information</h2> 776 <table cellspacing=0><tbody> 777 <tr class=tr-0><td class=td-0>Current Items(total)</td><td>$curr_items ($total_items)</td></tr> 778 <tr class=tr-1><td class=td-0>Hits</td><td>{$hits}</td></tr> 779 <tr class=tr-0><td class=td-0>Misses</td><td>{$misses}</td></tr> 780 <tr class=tr-1><td class=td-0>Request Rate (hits, misses)</td><td>$req_rate cache requests/second</td></tr> 781 <tr class=tr-0><td class=td-0>Hit Rate</td><td>$hit_rate cache requests/second</td></tr> 782 <tr class=tr-1><td class=td-0>Miss Rate</td><td>$miss_rate cache requests/second</td></tr> 783 <tr class=tr-0><td class=td-0>Set Rate</td><td>$set_rate cache requests/second</td></tr> 784 </tbody></table> 785 </div> 786 787EOB; 788 789 break; 790 791 case 2: // variables 792 793 $m=0; 794 $cacheItems= getCacheItems(); 795 $items = $cacheItems['items']; 796 $totals = $cacheItems['counts']; 797 $maxDump = MAX_ITEM_DUMP; 798 foreach($items as $server => $entries) { 799 800 echo <<< EOB 801 802 <div class="info"><table cellspacing=0><tbody> 803 <tr><th colspan="2">$server</th></tr> 804 <tr><th>Slab Id</th><th>Info</th></tr> 805EOB; 806 807 foreach($entries as $slabId => $slab) { 808 $dumpUrl = $PHP_SELF.'&op=2&server='.(array_search($server,$MEMCACHE_SERVERS)).'&dumpslab='.$slabId; 809 echo 810 "<tr class=tr-$m>", 811 "<td class=td-0><center>",'<a href="',$dumpUrl,'">',$slabId,'</a>',"</center></td>", 812 "<td class=td-last><b>Item count:</b> ",$slab['number'],'<br/><b>Age:</b>',duration($time-$slab['age']),'<br/> <b>Evicted:</b>',((isset($slab['evicted']) && $slab['evicted']==1)? 'Yes':'No'); 813 if ((isset($_GET['dumpslab']) && $_GET['dumpslab']==$slabId) && (isset($_GET['server']) && $_GET['server']==array_search($server,$MEMCACHE_SERVERS))){ 814 echo "<br/><b>Items: item</b><br/>"; 815 $items = dumpCacheSlab($server,$slabId,$slab['number']); 816 // maybe someone likes to do a pagination here :) 817 $i=1; 818 foreach($items['ITEM'] as $itemKey=>$itemInfo){ 819 $itemInfo = trim($itemInfo,'[ ]'); 820 821 822 echo '<a href="',$PHP_SELF,'&op=4&server=',(array_search($server,$MEMCACHE_SERVERS)),'&key=',base64_encode($itemKey).'">',$itemKey,'</a>'; 823 if ($i++ % 10 == 0) { 824 echo '<br/>'; 825 } 826 elseif ($i!=$slab['number']+1){ 827 echo ','; 828 } 829 } 830 } 831 832 echo "</td></tr>"; 833 $m=1-$m; 834 } 835 echo <<<EOB 836 </tbody></table> 837 </div><hr/> 838EOB; 839} 840 break; 841 842 break; 843 844 case 4: //item dump 845 if (!isset($_GET['key']) || !isset($_GET['server'])){ 846 echo "No key set!"; 847 break; 848 } 849 // I'm not doing anything to check the validity of the key string. 850 // probably an exploit can be written to delete all the files in key=base64_encode("\n\r delete all"). 851 // somebody has to do a fix to this. 852 $theKey = htmlentities(base64_decode($_GET['key'])); 853 854 $theserver = $MEMCACHE_SERVERS[(int)$_GET['server']]; 855 list($h,$p) = get_host_port_from_server($theserver); 856 $r = sendMemcacheCommand($h,$p,'get '.$theKey); 857 echo <<<EOB 858 <div class="info"><table cellspacing=0><tbody> 859 <tr><th>Server<th>Key</th><th>Value</th><th>Delete</th></tr> 860EOB; 861 if (!isset($r['VALUE'])) { 862 echo "<tr><td class=td-0>",$theserver,"</td><td class=td-0>",$theKey, 863 "</td><td>[The requested item was not found or has expired]</td>", 864 "<td></td>","</tr>"; 865 } 866 else { 867 868 echo "<tr><td class=td-0>",$theserver,"</td><td class=td-0>",$theKey, 869 " <br/>flag:",$r['VALUE'][$theKey]['stat']['flag'], 870 " <br/>Size:",bsize($r['VALUE'][$theKey]['stat']['size']), 871 "</td><td>",chunk_split($r['VALUE'][$theKey]['value'],40),"</td>", 872 '<td><a href="',$PHP_SELF,'&op=5&server=',(int)$_GET['server'],'&key=',base64_encode($theKey),"\">Delete</a></td>","</tr>"; 873 } 874 echo <<<EOB 875 </tbody></table> 876 </div><hr/> 877EOB; 878 break; 879 case 5: // item delete 880 if (!isset($_GET['key']) || !isset($_GET['server'])){ 881 echo "No key set!"; 882 break; 883 } 884 $theKey = htmlentities(base64_decode($_GET['key'])); 885 $theserver = $MEMCACHE_SERVERS[(int)$_GET['server']]; 886 list($h,$p) = get_host_port_from_server($theserver); 887 $r = sendMemcacheCommand($h,$p,'delete '.$theKey); 888 echo 'Deleting '.$theKey.':'.$r; 889 break; 890 891 case 6: // flush server 892 $theserver = $MEMCACHE_SERVERS[(int)$_GET['server']]; 893 $r = flushServer($theserver); 894 echo 'Flush '.$theserver.":".$r; 895 break; 896} 897echo getFooter(); 898 899?> 900