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