CFileLogRoute.php 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. <?php
  2. /**
  3. * CFileLogRoute class file.
  4. *
  5. * @author Qiang Xue <qiang.xue@gmail.com>
  6. * @link http://www.yiiframework.com/
  7. * @copyright 2008-2013 Yii Software LLC
  8. * @license http://www.yiiframework.com/license/
  9. */
  10. /**
  11. * CFileLogRoute records log messages in files.
  12. *
  13. * The log files are stored under {@link setLogPath logPath} and the file name
  14. * is specified by {@link setLogFile logFile}. If the size of the log file is
  15. * greater than {@link setMaxFileSize maxFileSize} (in kilo-bytes), a rotation
  16. * is performed, which renames the current log file by suffixing the file name
  17. * with '.1'. All existing log files are moved backwards one place, i.e., '.2'
  18. * to '.3', '.1' to '.2'. The property {@link setMaxLogFiles maxLogFiles}
  19. * specifies how many files to be kept.
  20. * If the property {@link rotateByCopy} is true, the primary log file will be
  21. * rotated by a copy and truncated (to be more compatible with log tailers)
  22. * otherwise it will be rotated by being renamed.
  23. *
  24. * @property string $logPath Directory storing log files. Defaults to application runtime path.
  25. * @property string $logFile Log file name. Defaults to 'application.log'.
  26. * @property integer $maxFileSize Maximum log file size in kilo-bytes (KB). Defaults to 1024 (1MB).
  27. * @property integer $maxLogFiles Number of files used for rotation. Defaults to 5.
  28. *
  29. * @author Qiang Xue <qiang.xue@gmail.com>
  30. * @package system.logging
  31. * @since 1.0
  32. */
  33. class CFileLogRoute extends CLogRoute
  34. {
  35. /**
  36. * @var integer maximum log file size
  37. */
  38. private $_maxFileSize=1024; // in KB
  39. /**
  40. * @var integer number of log files used for rotation
  41. */
  42. private $_maxLogFiles=5;
  43. /**
  44. * @var string directory storing log files
  45. */
  46. private $_logPath;
  47. /**
  48. * @var string log file name
  49. */
  50. private $_logFile='application.log';
  51. /**
  52. * @var boolean Whether to rotate primary log by copy and truncate
  53. * which is more compatible with log tailers. Defaults to false.
  54. * @since 1.1.14
  55. */
  56. public $rotateByCopy=false;
  57. /**
  58. * Initializes the route.
  59. * This method is invoked after the route is created by the route manager.
  60. */
  61. public function init()
  62. {
  63. parent::init();
  64. if($this->getLogPath()===null)
  65. $this->setLogPath(Yii::app()->getRuntimePath());
  66. }
  67. /**
  68. * @return string directory storing log files. Defaults to application runtime path.
  69. */
  70. public function getLogPath()
  71. {
  72. return $this->_logPath;
  73. }
  74. /**
  75. * @param string $value directory for storing log files.
  76. * @throws CException if the path is invalid
  77. */
  78. public function setLogPath($value)
  79. {
  80. $this->_logPath=realpath($value);
  81. if($this->_logPath===false || !is_dir($this->_logPath) || !is_writable($this->_logPath))
  82. throw new CException(Yii::t('yii','CFileLogRoute.logPath "{path}" does not point to a valid directory. Make sure the directory exists and is writable by the Web server process.',
  83. array('{path}'=>$value)));
  84. }
  85. /**
  86. * @return string log file name. Defaults to 'application.log'.
  87. */
  88. public function getLogFile()
  89. {
  90. return $this->_logFile;
  91. }
  92. /**
  93. * @param string $value log file name
  94. */
  95. public function setLogFile($value)
  96. {
  97. $this->_logFile=$value;
  98. }
  99. /**
  100. * @return integer maximum log file size in kilo-bytes (KB). Defaults to 1024 (1MB).
  101. */
  102. public function getMaxFileSize()
  103. {
  104. return $this->_maxFileSize;
  105. }
  106. /**
  107. * @param integer $value maximum log file size in kilo-bytes (KB).
  108. */
  109. public function setMaxFileSize($value)
  110. {
  111. if(($this->_maxFileSize=(int)$value)<1)
  112. $this->_maxFileSize=1;
  113. }
  114. /**
  115. * @return integer number of files used for rotation. Defaults to 5.
  116. */
  117. public function getMaxLogFiles()
  118. {
  119. return $this->_maxLogFiles;
  120. }
  121. /**
  122. * @param integer $value number of files used for rotation.
  123. */
  124. public function setMaxLogFiles($value)
  125. {
  126. if(($this->_maxLogFiles=(int)$value)<1)
  127. $this->_maxLogFiles=1;
  128. }
  129. /**
  130. * Saves log messages in files.
  131. * @param array $logs list of log messages
  132. */
  133. protected function processLogs($logs)
  134. {
  135. $text='';
  136. foreach($logs as $log)
  137. $text.=$this->formatLogMessage($log[0],$log[1],$log[2],$log[3]);
  138. $logFile=$this->getLogPath().DIRECTORY_SEPARATOR.$this->getLogFile();
  139. $fp=@fopen($logFile,'a');
  140. @flock($fp,LOCK_EX);
  141. if(@filesize($logFile)>$this->getMaxFileSize()*1024)
  142. {
  143. $this->rotateFiles();
  144. @flock($fp,LOCK_UN);
  145. @fclose($fp);
  146. @file_put_contents($logFile,$text,FILE_APPEND|LOCK_EX);
  147. }
  148. else
  149. {
  150. @fwrite($fp,$text);
  151. @flock($fp,LOCK_UN);
  152. @fclose($fp);
  153. }
  154. }
  155. /**
  156. * Rotates log files.
  157. */
  158. protected function rotateFiles()
  159. {
  160. $file=$this->getLogPath().DIRECTORY_SEPARATOR.$this->getLogFile();
  161. $max=$this->getMaxLogFiles();
  162. for($i=$max;$i>0;--$i)
  163. {
  164. $rotateFile=$file.'.'.$i;
  165. if(is_file($rotateFile))
  166. {
  167. // suppress errors because it's possible multiple processes enter into this section
  168. if($i===$max)
  169. @unlink($rotateFile);
  170. else
  171. @rename($rotateFile,$file.'.'.($i+1));
  172. }
  173. }
  174. if(is_file($file))
  175. {
  176. // suppress errors because it's possible multiple processes enter into this section
  177. if($this->rotateByCopy)
  178. {
  179. @copy($file,$file.'.1');
  180. if($fp=@fopen($file,'a'))
  181. {
  182. @ftruncate($fp,0);
  183. @fclose($fp);
  184. }
  185. }
  186. else
  187. @rename($file,$file.'.1');
  188. }
  189. }
  190. }