[ Index ]
 

Code source de PRADO 3.0.6

Accédez au Source d'autres logiciels libresSoutenez Angelica Josefina !

title

Body

[fermer]

/framework/Util/ -> TLogRouter.php (source)

   1  <?php
   2  /**
   3   * TLogRouter, TLogRoute, TFileLogRoute, TEmailLogRoute class file
   4   *
   5   * @author Qiang Xue <qiang.xue@gmail.com>
   6   * @link http://www.pradosoft.com/
   7   * @copyright Copyright &copy; 2005 PradoSoft
   8   * @license http://www.pradosoft.com/license/
   9   * @version $Id: TLogRouter.php 1397 2006-09-07 07:55:53Z wei $
  10   * @package System.Util
  11   */
  12  
  13  /**
  14   * TLogRouter class.
  15   *
  16   * TLogRouter manages routes that record log messages in different media different ways.
  17   * For example, a file log route {@link TFileLogRoute} records log messages
  18   * in log files. An email log route {@link TEmailLogRoute} sends log messages
  19   * to email addresses.
  20   *
  21   * Log routes may be configured in application or page folder configuration files
  22   * or an external configuration file specified by {@link setConfigFile ConfigFile}.
  23   * The format is as follows,
  24   * <code>
  25   *   <route class="TFileLogRoute" Categories="System.Web.UI" Levels="Warning" />
  26   *   <route class="TEmailLogRoute" Categories="Application" Levels="Fatal" Emails="admin@pradosoft.com" />
  27   * </code>
  28   * You can specify multiple routes with different filtering conditions and different
  29   * targets, even if the routes are of the same type.
  30   *
  31   * @author Qiang Xue <qiang.xue@gmail.com>
  32   * @version $Id: TLogRouter.php 1397 2006-09-07 07:55:53Z wei $
  33   * @package System.Util
  34   * @since 3.0
  35   */
  36  class TLogRouter extends TModule
  37  {
  38      /**
  39       * File extension of external configuration file
  40       */
  41      const CONFIG_FILE_EXT='.xml';
  42      /**
  43       * @var array list of routes available
  44       */
  45      private $_routes=array();
  46      /**
  47       * @var string external configuration file
  48       */
  49      private $_configFile=null;
  50  
  51      /**
  52       * Initializes this module.
  53       * This method is required by the IModule interface.
  54       * @param TXmlElement configuration for this module, can be null
  55       * @throws TConfigurationException if {@link getConfigFile ConfigFile} is invalid.
  56       */
  57  	public function init($config)
  58      {
  59          if($this->_configFile!==null)
  60          {
  61               if(is_file($this->_configFile))
  62               {
  63                  $dom=new TXmlDocument;
  64                  $dom->loadFromFile($this->_configFile);
  65                  $this->loadConfig($dom);
  66              }
  67              else
  68                  throw new TConfigurationException('logrouter_configfile_invalid',$this->_configFile);
  69          }
  70          $this->loadConfig($config);
  71          $this->getApplication()->attachEventHandler('OnEndRequest',array($this,'collectLogs'));
  72      }
  73  
  74      /**
  75       * Loads configuration from an XML element
  76       * @param TXmlElement configuration node
  77       * @throws TConfigurationException if log route class or type is not specified
  78       */
  79  	private function loadConfig($xml)
  80      {
  81          foreach($xml->getElementsByTagName('route') as $routeConfig)
  82          {
  83              $properties=$routeConfig->getAttributes();
  84              if(($class=$properties->remove('class'))===null)
  85                  throw new TConfigurationException('logrouter_routeclass_required');
  86              $route=Prado::createComponent($class);
  87              if(!($route instanceof TLogRoute))
  88                  throw new TConfigurationException('logrouter_routetype_invalid');
  89              foreach($properties as $name=>$value)
  90                  $route->setSubproperty($name,$value);
  91              $this->_routes[]=$route;
  92              $route->init($routeConfig);
  93          }
  94      }
  95  
  96      /**
  97       * @return string external configuration file. Defaults to null.
  98       */
  99  	public function getConfigFile()
 100      {
 101          return $this->_configFile;
 102      }
 103  
 104      /**
 105       * @param string external configuration file in namespace format. The file
 106       * must be suffixed with '.xml'.
 107       * @throws TInvalidDataValueException if the file is invalid.
 108       */
 109  	public function setConfigFile($value)
 110      {
 111          if(($this->_configFile=Prado::getPathOfNamespace($value,self::LOG_FILE_EXT))===null)
 112              throw new TConfigurationException('logrouter_configfile_invalid',$value);
 113      }
 114  
 115      /**
 116       * Collects log messages from a logger.
 117       * This method is an event handler to application's EndRequest event.
 118       * @param mixed event parameter
 119       */
 120  	public function collectLogs($param)
 121      {
 122          $logger=Prado::getLogger();
 123          foreach($this->_routes as $route)
 124              $route->collectLogs($logger);
 125      }
 126  }
 127  
 128  /**
 129   * TLogRoute class.
 130   *
 131   * TLogRoute is the base class for all log route classes.
 132   * A log route object retrieves log messages from a logger and sends it
 133   * somewhere, such as files, emails.
 134   * The messages being retrieved may be filtered first before being sent
 135   * to the destination. The filters include log level filter and log category filter.
 136   *
 137   * To specify level filter, set {@link setLevels Levels} property,
 138   * which takes a string of comma-separated desired level names (e.g. 'Error, Debug').
 139   * To specify category filter, set {@link setCategories Categories} property,
 140   * which takes a string of comma-separated desired category names (e.g. 'System.Web, System.IO').
 141   *
 142   * Level filter and category filter are combinational, i.e., only messages
 143   * satisfying both filter conditions will they be returned.
 144   *
 145   * @author Qiang Xue <qiang.xue@gmail.com>
 146   * @version $Id: TLogRouter.php 1397 2006-09-07 07:55:53Z wei $
 147   * @package System.Util
 148   * @since 3.0
 149   */
 150  abstract class TLogRoute extends TApplicationComponent
 151  {
 152      /**
 153       * @var array lookup table for level names
 154       */
 155      protected static $_levelNames=array(
 156          TLogger::DEBUG=>'Debug',
 157          TLogger::INFO=>'Info',
 158          TLogger::NOTICE=>'Notice',
 159          TLogger::WARNING=>'Warning',
 160          TLogger::ERROR=>'Error',
 161          TLogger::ALERT=>'Alert',
 162          TLogger::FATAL=>'Fatal'
 163      );
 164      /**
 165       * @var array lookup table for level values
 166       */
 167      protected static $_levelValues=array(
 168          'debug'=>TLogger::DEBUG,
 169          'info'=>TLogger::INFO,
 170          'notice'=>TLogger::NOTICE,
 171          'warning'=>TLogger::WARNING,
 172          'error'=>TLogger::ERROR,
 173          'alert'=>TLogger::ALERT,
 174          'fatal'=>TLogger::FATAL
 175      );
 176      /**
 177       * @var integer log level filter (bits)
 178       */
 179      private $_levels=null;
 180      /**
 181       * @var array log category filter
 182       */
 183      private $_categories=null;
 184  
 185      /**
 186       * Initializes the route.
 187       * @param TXmlElement configurations specified in {@link TLogRouter}.
 188       */
 189  	public function init($config)
 190      {
 191      }
 192  
 193      /**
 194       * @return integer log level filter
 195       */
 196  	public function getLevels()
 197      {
 198          return $this->_levels;
 199      }
 200  
 201      /**
 202       * @param integer|string integer log level filter (in bits). If the value is
 203       * a string, it is assumed to be comma-separated level names. Valid level names
 204       * include 'Debug', 'Info', 'Notice', 'Warning', 'Error', 'Alert' and 'Fatal'.
 205       */
 206  	public function setLevels($levels)
 207      {
 208          if(is_integer($levels))
 209              $this->_levels=$levels;
 210          else
 211          {
 212              $this->_levels=null;
 213              $levels=strtolower($levels);
 214              foreach(explode(',',$levels) as $level)
 215              {
 216                  $level=trim($level);
 217                  if(isset(self::$_levelValues[$level]))
 218                      $this->_levels|=self::$_levelValues[$level];
 219              }
 220          }
 221      }
 222  
 223      /**
 224       * @return array list of categories to be looked for
 225       */
 226  	public function getCategories()
 227      {
 228          return $this->_categories;
 229      }
 230  
 231      /**
 232       * @param array|string list of categories to be looked for. If the value is a string,
 233       * it is assumed to be comma-separated category names.
 234       */
 235  	public function setCategories($categories)
 236      {
 237          if(is_array($categories))
 238              $this->_categories=$categories;
 239          else
 240          {
 241              $this->_categories=null;
 242              foreach(explode(',',$categories) as $category)
 243              {
 244                  if(($category=trim($category))!=='')
 245                      $this->_categories[]=$category;
 246              }
 247          }
 248      }
 249  
 250      /**
 251       * @param integer level value
 252       * @return string level name
 253       */
 254  	protected function getLevelName($level)
 255      {
 256          return isset(self::$_levelNames[$level])?self::$_levelNames[$level]:'Unknown';
 257      }
 258  
 259      /**
 260       * @param string level name
 261       * @return integer level value
 262       */
 263  	protected function getLevelValue($level)
 264      {
 265          return isset(self::$_levelValues[$level])?self::$_levelValues[$level]:0;
 266      }
 267  
 268      /**
 269       * Formats a log message given different fields.
 270       * @param string message content
 271       * @param integer message level
 272       * @param string message category
 273       * @param integer timestamp
 274       * @return string formatted message
 275       */
 276  	protected function formatLogMessage($message,$level,$category,$time)
 277      {
 278          return @date('M d H:i:s',$time).' ['.$this->getLevelName($level).'] ['.$category.'] '.$message."\n";
 279      }
 280  
 281      /**
 282       * Retrieves log messages from logger to log route specific destination.
 283       * @param TLogger logger instance
 284       */
 285  	public function collectLogs(TLogger $logger)
 286      {
 287          $logs=$logger->getLogs($this->getLevels(),$this->getCategories());
 288          if(!empty($logs))
 289              $this->processLogs($logs);
 290      }
 291  
 292      /**
 293       * Processes log messages and sends them to specific destination.
 294       * Derived child classes must implement this method.
 295       * @param array list of messages.  Each array elements represents one message
 296       * with the following structure:
 297       * array(
 298       *   [0] => message
 299       *   [1] => level
 300       *   [2] => category
 301       *   [3] => timestamp);
 302       */
 303      abstract protected function processLogs($logs);
 304  }
 305  
 306  /**
 307   * TFileLogRoute class.
 308   *
 309   * TFileLogRoute records log messages in files.
 310   * The log files are stored under {@link setLogPath LogPath} and the file name
 311   * is specified by {@link setLogFile LogFile}. If the size of the log file is
 312   * greater than {@link setMaxFileSize MaxFileSize} (in kilo-bytes), a rotation
 313   * is performed, which renames the current log file by suffixing the file name
 314   * with '.1'. All existing log files are moved backwards one place, i.e., '.2'
 315   * to '.3', '.1' to '.2'. The property {@link setMaxLogFiles MaxLogFiles}
 316   * specifies how many files to be kept.
 317   *
 318   * @author Qiang Xue <qiang.xue@gmail.com>
 319   * @version $Id: TLogRouter.php 1397 2006-09-07 07:55:53Z wei $
 320   * @package System.Util
 321   * @since 3.0
 322   */
 323  class TFileLogRoute extends TLogRoute
 324  {
 325      /**
 326       * @var integer maximum log file size
 327       */
 328      private $_maxFileSize=512; // in KB
 329      /**
 330       * @var integer number of log files used for rotation
 331       */
 332      private $_maxLogFiles=2;
 333      /**
 334       * @var string directory storing log files
 335       */
 336      private $_logPath=null;
 337      /**
 338       * @var string log file name
 339       */
 340      private $_logFile='prado.log';
 341  
 342      /**
 343       * @return string directory storing log files. Defaults to application runtime path.
 344       */
 345  	public function getLogPath()
 346      {
 347          if($this->_logPath===null)
 348              $this->_logPath=$this->getApplication()->getRuntimePath();
 349          return $this->_logPath;
 350      }
 351  
 352      /**
 353       * @param string directory (in namespace format) storing log files.
 354       * @throws TConfigurationException if log path is invalid
 355       */
 356  	public function setLogPath($value)
 357      {
 358          if(($this->_logPath=Prado::getPathOfNamespace($value))===null || !is_dir($this->_logPath) || !is_writable($this->_logPath))
 359              throw new TConfigurationException('filelogroute_logpath_invalid',$value);
 360      }
 361  
 362      /**
 363       * @return string log file name. Defaults to 'prado.log'.
 364       */
 365  	public function getLogFile()
 366      {
 367          return $this->_logFile;
 368      }
 369  
 370      /**
 371       * @param string log file name
 372       */
 373  	public function setLogFile($value)
 374      {
 375          $this->_logFile=$value;
 376      }
 377  
 378      /**
 379       * @return integer maximum log file size in kilo-bytes (KB). Defaults to 1024 (1MB).
 380       */
 381  	public function getMaxFileSize()
 382      {
 383          return $this->_maxFileSize;
 384      }
 385  
 386      /**
 387       * @param integer maximum log file size in kilo-bytes (KB).
 388       * @throws TInvalidDataValueException if the value is smaller than 1.
 389       */
 390  	public function setMaxFileSize($value)
 391      {
 392          $this->_maxFileSize=TPropertyValue::ensureInteger($value);
 393          if($this->_maxFileSize<=0)
 394              throw new TInvalidDataValueException('filelogroute_maxfilesize_invalid');
 395      }
 396  
 397      /**
 398       * @return integer number of files used for rotation. Defaults to 2.
 399       */
 400  	public function getMaxLogFiles()
 401      {
 402          return $this->_maxLogFiles;
 403      }
 404  
 405      /**
 406       * @param integer number of files used for rotation.
 407       */
 408  	public function setMaxLogFiles($value)
 409      {
 410          $this->_maxLogFiles=TPropertyValue::ensureInteger($value);
 411          if($this->_maxLogFiles<1)
 412              throw new TInvalidDataValueException('filelogroute_maxlogfiles_invalid');
 413      }
 414  
 415      /**
 416       * Saves log messages in files.
 417       * @param array list of log messages
 418       */
 419  	protected function processLogs($logs)
 420      {
 421          $logFile=$this->getLogPath().'/'.$this->getLogFile();
 422          if(@filesize($logFile)>$this->_maxFileSize*1024)
 423              $this->rotateFiles();
 424          foreach($logs as $log)
 425              error_log($this->formatLogMessage($log[0],$log[1],$log[2],$log[3]),3,$logFile);
 426      }
 427  
 428      /**
 429       * Rotates log files.
 430       */
 431  	protected function rotateFiles()
 432      {
 433          $file=$this->getLogPath().'/'.$this->getLogFile();
 434          for($i=$this->_maxLogFiles;$i>0;--$i)
 435          {
 436              $rotateFile=$file.'.'.$i;
 437              if(is_file($rotateFile))
 438              {
 439                  if($i===$this->_maxLogFiles)
 440                      unlink($rotateFile);
 441                  else
 442                      rename($rotateFile,$file.'.'.($i+1));
 443              }
 444          }
 445          if(is_file($file))
 446              rename($file,$file.'.1');
 447      }
 448  }
 449  
 450  /**
 451   * TEmailLogRoute class.
 452   *
 453   * TEmailLogRoute sends selected log messages to email addresses.
 454   * The target email addresses may be specified via {@link setEmails Emails} property.
 455   * Optionally, you may set the email {@link setSubject Subject} and the
 456   * {@link setSentFrom SentFrom} address.
 457   *
 458   * @author Qiang Xue <qiang.xue@gmail.com>
 459   * @version $Id: TLogRouter.php 1397 2006-09-07 07:55:53Z wei $
 460   * @package System.Util
 461   * @since 3.0
 462   */
 463  class TEmailLogRoute extends TLogRoute
 464  {
 465      /**
 466       * Regex pattern for email address.
 467       */
 468      const EMAIL_PATTERN='/^([0-9a-zA-Z]+[-._+&])*[0-9a-zA-Z]+@([-0-9a-zA-Z]+[.])+[a-zA-Z]{2,6}$/';
 469      /**
 470       * Default email subject.
 471       */
 472      const DEFAULT_SUBJECT='Prado Application Log';
 473      /**
 474       * @var array list of destination email addresses.
 475       */
 476      private $_emails=array();
 477      /**
 478       * @var string email subject
 479       */
 480      private $_subject='';
 481      /**
 482       * @var string email sent from address
 483       */
 484      private $_from='';
 485  
 486      /**
 487       * Initializes the route.
 488       * @param TXmlElement configurations specified in {@link TLogRouter}.
 489       * @throws TConfigurationException if {@link getSentFrom SentFrom} is empty and
 490       * 'sendmail_from' in php.ini is also empty.
 491       */
 492  	public function init($config)
 493      {
 494          if($this->_from==='')
 495              $this->_from=ini_get('sendmail_from');
 496          if($this->_from==='')
 497              throw new TConfigurationException('emaillogroute_sentfrom_required');
 498      }
 499  
 500      /**
 501       * Sends log messages to specified email addresses.
 502       * @param array list of log messages
 503       */
 504  	protected function processLogs($logs)
 505      {
 506          $message='';
 507          foreach($logs as $log)
 508              $message.=$this->formatLogMessage($log[0],$log[1],$log[2],$log[3]);
 509          $message=wordwrap($message,70);
 510          foreach($this->_emails as $email)
 511              mail($email,$this->getSubject(),$message,"From:{$this->_from}\r\n");
 512  
 513      }
 514  
 515      /**
 516       * @return array list of destination email addresses
 517       */
 518  	public function getEmails()
 519      {
 520          return $this->_emails;
 521      }
 522  
 523      /**
 524       * @return array|string list of destination email addresses. If the value is
 525       * a string, it is assumed to be comma-separated email addresses.
 526       */
 527  	public function setEmails($emails)
 528      {
 529          if(is_array($emails))
 530              $this->_emails=$emails;
 531          else
 532          {
 533              $this->_emails=array();
 534              foreach(explode(',',$emails) as $email)
 535              {
 536                  $email=trim($email);
 537                  if(preg_match(self::EMAIL_PATTERN,$email))
 538                      $this->_emails[]=$email;
 539              }
 540          }
 541      }
 542  
 543      /**
 544       * @return string email subject. Defaults to TEmailLogRoute::DEFAULT_SUBJECT
 545       */
 546  	public function getSubject()
 547      {
 548          if($this->_subject===null)
 549              $this->_subject=self::DEFAULT_SUBJECT;
 550          return $this->_subject;
 551      }
 552  
 553      /**
 554       * @param string email subject.
 555       */
 556  	public function setSubject($value)
 557      {
 558          $this->_subject=$value;
 559      }
 560  
 561      /**
 562       * @return string send from address of the email
 563       */
 564  	public function getSentFrom()
 565      {
 566          return $this->_from;
 567      }
 568  
 569      /**
 570       * @param string send from address of the email
 571       */
 572  	public function setSentFrom($value)
 573      {
 574          $this->_from=$value;
 575      }
 576  }
 577  
 578  /**
 579   * TBrowserLogRoute class.
 580   *
 581   * TBrowserLogRoute prints selected log messages in the response.
 582   *
 583   * @author Xiang Wei Zhuo <weizhuo[at]gmail[dot]com>
 584   * @version $Id: TLogRouter.php 1397 2006-09-07 07:55:53Z wei $
 585   * @package System.Util
 586   * @since 3.0
 587   */
 588  class TBrowserLogRoute extends TLogRoute
 589  {
 590  	public function processLogs($logs)
 591      {
 592          if(empty($logs) || $this->getApplication()->getMode()==='Performance') return;
 593          $first = $logs[0][3];
 594          $even = true;
 595          $response = $this->getApplication()->getResponse();
 596          $response->write($this->renderHeader());
 597          for($i=0,$n=count($logs);$i<$n;++$i)
 598          {
 599              if ($i<$n-1)
 600              {
 601                  $timing['delta'] = $logs[$i+1][3] - $logs[$i][3];
 602                  $timing['total'] = $logs[$i+1][3] - $first;
 603              }
 604              else
 605              {
 606                  $timing['delta'] = '?';
 607                  $timing['total'] = $logs[$i][3] - $first;
 608              }
 609              $timing['even'] = !($even = !$even);
 610              $response->write($this->renderMessage($logs[$i],$timing));
 611          }
 612          $response->write($this->renderFooter());
 613      }
 614  
 615  	protected function renderHeader()
 616      {
 617          $string = <<<EOD
 618  <table cellspacing="0" cellpadding="2" border="0" width="100%">
 619      <tr>
 620          <th style="background-color: black; color:white;" colspan="11">
 621              Application Log
 622          </th>
 623      </tr><tr style="background-color: #ccc;">
 624          <th>&nbsp;</th>
 625          <th>Category</th><th>Message</th><th>Time Spent (s)</th><th>Cumulated Time Spent (s)</th>
 626      </tr>
 627  EOD;
 628          return $string;
 629      }
 630  
 631  	protected function renderMessage($log, $info)
 632      {
 633          $bgcolor = $info['even'] ? "#fff" : "#eee";
 634          $total = sprintf('%0.6f', $info['total']);
 635          $delta = sprintf('%0.6f', $info['delta']);
 636          $color = $this->getColorLevel($log[1]);
 637          $msg = preg_replace('/\(line[^\)]+\)$/','',$log[0]); //remove line number info
 638          $msg = THttpUtility::htmlEncode($msg);
 639          $string = <<<EOD
 640      <tr style="background-color: {$bgcolor};">
 641          <td style="border:1px solid silver;background-color: $color;">&nbsp;</td>
 642          <td>{$log[2]}</td>
 643          <td>{$msg}</td>
 644          <td style="text-align:center">{$delta}</td>
 645          <td style="text-align:center">{$total}</td>
 646      </tr>
 647  EOD;
 648          return $string;
 649      }
 650  
 651  	protected function getColorLevel($level)
 652      {
 653          switch($level)
 654          {
 655              case TLogger::DEBUG: return 'green';
 656              case TLogger::INFO: return 'black';
 657              case TLogger::NOTICE: return '#3333FF';
 658              case TLogger::WARNING: return '#33FFFF';
 659              case TLogger::ERROR: return '#ff9933';
 660              case TLogger::ALERT: return '#ff00ff';
 661              case TLogger::FATAL: return 'red';
 662          }
 663          return '';
 664      }
 665  
 666  	protected function renderFooter()
 667      {
 668          $string = "<tr><td colspan=\"11\" style=\"text-align:center; border-top: 1px solid #ccc; padding:0.2em;\">";
 669          foreach(self::$_levelValues as $name => $level)
 670          {
 671              $string .= "<span style=\"color:white;background-color:".$this->getColorLevel($level);
 672              $string .= ";margin: 0.5em;\">".strtoupper($name)."</span>";
 673          }
 674          $string .= "</td></tr></table>";
 675          return $string;
 676      }
 677  }
 678  ?>


Généré le : Sun Feb 25 21:07:04 2007 par Balluche grâce à PHPXref 0.7