<?php
/*
Plugin Name: Load Monitor
Description: Add error log entry when page memory usage or run time is too high
Version: 1.01
Requires at least: 2.65
*/

// UPDATE THESE VALUES
$GLOBALS['LOADMONITOR_MAX_SECS'] = 2;     // pages that take longer than this to load will be logged 
$GLOBALS['LOADMONITOR_MAX_MEGS'] = 10;    // pages that use more memory than this will be logged 

// NOTE: Add this code to the top of any specific pages where higher memory/runtime is expected (eg: cron.php)
// ... Make sure you add it after viewer_functions.php or init.php is called.
/*
// Load Monitor Plugin: Override/set logging limits
$GLOBALS['LOADMONITOR_MAX_SECS'] = 5;    // pages that take longer than this to load will be logged 
$GLOBALS['LOADMONITOR_MAX_MEGS'] = 10;   // pages that use more memory than this will be logged 
*/


// DON'T UPDATE ANYTHING BELOW THIS LINE

register_shutdown_function('lm_logHighLoadRequests');
pluginAction_addHandlerAndLink(t('Debug Menu'), 'lm_debug_menu', 'admins');


//
function lm_logHighLoadRequests() {
  $errors = array();

  // check memory usage
  $peakMemoryActualBytes = memory_get_peak_usage(true);
  if (defined('IS_CMS_ADMIN') && array_key_exists('submitUploads', $_POST)) { $GLOBALS['LOADMONITOR_MAX_MEGS'] = 60; } // increase memory limit for uploads
  if ($peakMemoryActualBytes > ($GLOBALS['LOADMONITOR_MAX_MEGS']*1024*1024)) { 
    $errors[] = "high memory usage: " . formatBytes($peakMemoryActualBytes);     
  }
  
  // check page load time
  $runtimeSeconds = sprintf("%0.2f", microtime(true) - $_SERVER['REQUEST_TIME_FLOAT']);
  if ($runtimeSeconds > $GLOBALS['LOADMONITOR_MAX_SECS']) {
    $errors[] = "slow loading page: {$runtimeSeconds}s";
  }

  // add note about uploads
  if ($errors && defined('IS_CMS_ADMIN') && array_key_exists('submitUploads', $_POST)) {
    $errors[] = "FILE UPLOAD";
    $GLOBALS['LOADMONITOR_MAX_MEGS'] = 60;
  }

  // future? check system load average
  //$sys_getloadavg_last1m_5m_15m = "Not supported on this platform"; 
  //if (function_exists('sys_getloadavg')) { $sys_getloadavg_last1m_5m_15m = sys_getloadavg(); }
    
  if ($errors) { 
    @trigger_error("Load Monitor - " . implode(', ', $errors), E_USER_NOTICE);
  }
}

//
function lm_debug_menu() {
  echo plugin_header("Load Monitor - Debug Menu");
  
  // ... listRow listRowOdd
  ?>
  
  <p>For developer reference only, you can safely ignore all of the following.  Load Monitor alerts will be automatically added to your error log.</p>
  
  <table border='0' cellspacing='2' cellpadding='2' class="data"> 
    <tr>
    <td>Current Memory Usage:</td>
    <td>Allocated: <?php echo formatBytes(memory_get_usage()) ?>, Actual: <?php echo formatBytes(memory_get_usage(true)); ?></td>
    </tr>
    <tr>
    <td>Peak Memory Usage:</td>
    <td>Allocated: <?php echo formatBytes(memory_get_peak_usage()); ?> , Actual: <?php echo formatBytes(memory_get_peak_usage(true)); ?></td>
    </tr>
  </table>

  <div class='content-box content-box-divider'>
    <div class='content-box-header'><h3>script runtime</h3></div>
  </div>
  <?php
    print "\$_SERVER['REQUEST_TIME_FLOAT'] = {$_SERVER['REQUEST_TIME_FLOAT']}<br/>\n"; 
    print "\$_SERVER['REQUEST_TIME']       = {$_SERVER['REQUEST_TIME']}<br/>\n"; 
    print "<br/>\n";

    $result = microtime(true) - coalesce($_SERVER['REQUEST_TIME_FLOAT'], $_SERVER['REQUEST_TIME']);
    print " microtime - REQUEST_TIME* = " .sprintf("%0.5f", $result). "<br/>\n";
    
    print " getrusage: ";
    if (!function_exists('sys_getloadavg')) { print "not supported on this platform<br/>\n"; }
    else {
      $ru = getrusage();
      $usertime = sprintf("%0.2f", $ru['ru_utime.tv_sec'] + ($ru['ru_utime.tv_usec']/1000000));
      $systime  = sprintf("%0.2f", $ru['ru_stime.tv_sec'] + ($ru['ru_stime.tv_usec']/1000000));
      echo "This process used $usertime for its computations\n";
      echo "It spent $systime in system calls\n";
    }
  ?>
  
  <div class='content-box content-box-divider'>
    <div class='content-box-header'><h3>sys_getloadavg()</h3></div>
  </div>
  <?php 
    if (function_exists('sys_getloadavg')) {
      print "Average system load (the number of processes in the system run queue)<br/>\n"; 
      list($avgLoadLast_1m, $avgLoadLast_5m, $avgLoadLast_15m) = sys_getloadavg();
      print "Last 1 minutes: $avgLoadLast_1m<br/>\n"; 
      print "Last 5 minutes: $avgLoadLast_5m<br/>\n"; 
      print "Last 15 minutes: $avgLoadLast_15m<br/>\n"; 
      
    }
    else { print "not supported on this platform\n"; }
  ?>

  <div class='content-box content-box-divider'>
    <div class='content-box-header'><h3>getrusage(), getrusage(true)</h3></div>
  </div>
  <?php 
    if (function_exists('getrusage'))        { showme(getrusage()); showme(getrusage(true));  }
    else                                     { print "not supported on this platform\n"; }
    
  //
  echo plugin_footer();
  exit;

}