Overview

Packages

  • application
    • commands
    • components
      • actions
      • filters
      • leftWidget
      • permissions
      • sortableWidget
      • util
      • webupdater
      • x2flow
        • actions
        • triggers
      • X2GridView
      • X2Settings
    • controllers
    • models
      • embedded
    • modules
      • accounts
        • controllers
        • models
      • actions
        • controllers
        • models
      • calendar
        • controllers
        • models
      • charts
        • models
      • contacts
        • controllers
        • models
      • docs
        • components
        • controllers
        • models
      • groups
        • controllers
        • models
      • marketing
        • components
        • controllers
        • models
      • media
        • controllers
        • models
      • mobile
        • components
      • opportunities
        • controllers
        • models
      • products
        • controllers
        • models
      • quotes
        • controllers
        • models
      • services
        • controllers
        • models
      • template
        • models
      • users
        • controllers
        • models
      • workflow
        • controllers
        • models
      • x2Leads
        • controllers
        • models
  • Net
  • None
  • PHP
  • system
    • base
    • caching
      • dependencies
    • collections
    • console
    • db
      • ar
      • schema
        • cubrid
        • mssql
        • mysql
        • oci
        • pgsql
        • sqlite
    • i18n
      • gettext
    • logging
    • test
    • utils
    • validators
    • web
      • actions
      • auth
      • filters
      • form
      • helpers
      • renderers
      • services
      • widgets
        • captcha
        • pagers
  • Text
    • Highlighter
  • zii
    • behaviors
    • widgets
      • grid
      • jui

Classes

  • CChainedLogFilter
  • CDbLogRoute
  • CEmailLogRoute
  • CFileLogRoute
  • CLogFilter
  • CLogger
  • CLogRoute
  • CLogRouter
  • CProfileLogRoute
  • CSysLogRoute
  • CWebLogRoute

Interfaces

  • ILogFilter
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * CLogger 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: /**
 12:  * CLogger records log messages in memory.
 13:  *
 14:  * CLogger implements the methods to retrieve the messages with
 15:  * various filter conditions, including log levels and log categories.
 16:  *
 17:  * @property array $logs List of messages. Each array element represents one message
 18:  * with the following structure:
 19:  * array(
 20:  *   [0] => message (string)
 21:  *   [1] => level (string)
 22:  *   [2] => category (string)
 23:  *   [3] => timestamp (float, obtained by microtime(true));.
 24:  * @property float $executionTime The total time for serving the current request.
 25:  * @property integer $memoryUsage Memory usage of the application (in bytes).
 26:  * @property array $profilingResults The profiling results.
 27:  *
 28:  * @author Qiang Xue <qiang.xue@gmail.com>
 29:  * @package system.logging
 30:  * @since 1.0
 31:  */
 32: class CLogger extends CComponent
 33: {
 34:     const LEVEL_TRACE='trace';
 35:     const LEVEL_WARNING='warning';
 36:     const LEVEL_ERROR='error';
 37:     const LEVEL_INFO='info';
 38:     const LEVEL_PROFILE='profile';
 39: 
 40:     /**
 41:      * @var integer how many messages should be logged before they are flushed to destinations.
 42:      * Defaults to 10,000, meaning for every 10,000 messages, the {@link flush} method will be
 43:      * automatically invoked once. If this is 0, it means messages will never be flushed automatically.
 44:      * @since 1.1.0
 45:      */
 46:     public $autoFlush=10000;
 47:     /**
 48:      * @var boolean this property will be passed as the parameter to {@link flush()} when it is
 49:      * called in {@link log()} due to the limit of {@link autoFlush} being reached.
 50:      * By default, this property is false, meaning the filtered messages are still kept in the memory
 51:      * by each log route after calling {@link flush()}. If this is true, the filtered messages
 52:      * will be written to the actual medium each time {@link flush()} is called within {@link log()}.
 53:      * @since 1.1.8
 54:      */
 55:     public $autoDump=false;
 56:     /**
 57:      * @var array log messages
 58:      */
 59:     private $_logs=array();
 60:     /**
 61:      * @var integer number of log messages
 62:      */
 63:     private $_logCount=0;
 64:     /**
 65:      * @var array log levels for filtering (used when filtering)
 66:      */
 67:     private $_levels;
 68:     /**
 69:      * @var array log categories for filtering (used when filtering)
 70:      */
 71:     private $_categories;
 72:     /**
 73:      * @var array log categories for excluding from filtering (used when filtering)
 74:      */
 75:     private $_except=array();
 76:     /**
 77:      * @var array the profiling results (category, token => time in seconds)
 78:      */
 79:     private $_timings;
 80:     /**
 81:     * @var boolean if we are processing the log or still accepting new log messages
 82:     * @since 1.1.9
 83:     */
 84:     private $_processing=false;
 85: 
 86:     /**
 87:      * Logs a message.
 88:      * Messages logged by this method may be retrieved back via {@link getLogs}.
 89:      * @param string $message message to be logged
 90:      * @param string $level level of the message (e.g. 'Trace', 'Warning', 'Error'). It is case-insensitive.
 91:      * @param string $category category of the message (e.g. 'system.web'). It is case-insensitive.
 92:      * @see getLogs
 93:      */
 94:     public function log($message,$level='info',$category='application')
 95:     {
 96:         $this->_logs[]=array($message,$level,$category,microtime(true));
 97:         $this->_logCount++;
 98:         if($this->autoFlush>0 && $this->_logCount>=$this->autoFlush && !$this->_processing)
 99:         {
100:             $this->_processing=true;
101:             $this->flush($this->autoDump);
102:             $this->_processing=false;
103:         }
104:     }
105: 
106:     /**
107:      * Retrieves log messages.
108:      *
109:      * Messages may be filtered by log levels and/or categories.
110:      * A level filter is specified by a list of levels separated by comma or space
111:      * (e.g. 'trace, error'). A category filter is similar to level filter
112:      * (e.g. 'system, system.web'). A difference is that in category filter
113:      * you can use pattern like 'system.*' to indicate all categories starting
114:      * with 'system'.
115:      *
116:      * If you do not specify level filter, it will bring back logs at all levels.
117:      * The same applies to category filter.
118:      *
119:      * Level filter and category filter are combinational, i.e., only messages
120:      * satisfying both filter conditions will be returned.
121:      *
122:      * @param string $levels level filter
123:      * @param array|string $categories category filter
124:      * @param array|string $except list of log categories to ignore
125:      * @return array list of messages. Each array element represents one message
126:      * with the following structure:
127:      * array(
128:      *   [0] => message (string)
129:      *   [1] => level (string)
130:      *   [2] => category (string)
131:      *   [3] => timestamp (float, obtained by microtime(true));
132:      */
133:     public function getLogs($levels='',$categories=array(), $except=array())
134:     {
135:         $this->_levels=preg_split('/[\s,]+/',strtolower($levels),-1,PREG_SPLIT_NO_EMPTY);
136: 
137:         if (is_string($categories))
138:             $this->_categories=preg_split('/[\s,]+/',strtolower($categories),-1,PREG_SPLIT_NO_EMPTY);
139:         else
140:             $this->_categories=array_filter(array_map('strtolower',$categories));
141: 
142:         if (is_string($except))
143:             $this->_except=preg_split('/[\s,]+/',strtolower($except),-1,PREG_SPLIT_NO_EMPTY);
144:         else
145:             $this->_except=array_filter(array_map('strtolower',$except));
146: 
147:         $ret=$this->_logs;
148: 
149:         if(!empty($levels))
150:             $ret=array_values(array_filter($ret,array($this,'filterByLevel')));
151: 
152:         if(!empty($this->_categories) || !empty($this->_except))
153:             $ret=array_values(array_filter($ret,array($this,'filterByCategory')));
154: 
155:         return $ret;
156:     }
157: 
158:     /**
159:      * Filter function used by {@link getLogs}
160:      * @param array $value element to be filtered
161:      * @return boolean true if valid log, false if not.
162:      */
163:     private function filterByCategory($value)
164:     {
165:         return $this->filterAllCategories($value, 2);
166:     }
167: 
168:     /**
169:      * Filter function used by {@link getProfilingResults}
170:      * @param array $value element to be filtered
171:      * @return boolean true if valid timing entry, false if not.
172:      */
173:     private function filterTimingByCategory($value)
174:     {
175:         return $this->filterAllCategories($value, 1);
176:     }
177: 
178:     /**
179:      * Filter function used to filter included and excluded categories
180:      * @param array $value element to be filtered
181:      * @param integer $index index of the values array to be used for check
182:      * @return boolean true if valid timing entry, false if not.
183:      */
184:     private function filterAllCategories($value, $index)
185:     {
186:         $cat=strtolower($value[$index]);
187:         $ret=empty($this->_categories);
188:         foreach($this->_categories as $category)
189:         {
190:             if($cat===$category || (($c=rtrim($category,'.*'))!==$category && strpos($cat,$c)===0))
191:                 $ret=true;
192:         }
193:         if($ret)
194:         {
195:             foreach($this->_except as $category)
196:             {
197:                 if($cat===$category || (($c=rtrim($category,'.*'))!==$category && strpos($cat,$c)===0))
198:                     $ret=false;
199:             }
200:         }
201:         return $ret;
202:     }
203: 
204:     /**
205:      * Filter function used by {@link getLogs}
206:      * @param array $value element to be filtered
207:      * @return boolean true if valid log, false if not.
208:      */
209:     private function filterByLevel($value)
210:     {
211:         return in_array(strtolower($value[1]),$this->_levels);
212:     }
213: 
214:     /**
215:      * Returns the total time for serving the current request.
216:      * This method calculates the difference between now and the timestamp
217:      * defined by constant YII_BEGIN_TIME.
218:      * To estimate the execution time more accurately, the constant should
219:      * be defined as early as possible (best at the beginning of the entry script.)
220:      * @return float the total time for serving the current request.
221:      */
222:     public function getExecutionTime()
223:     {
224:         return microtime(true)-YII_BEGIN_TIME;
225:     }
226: 
227:     /**
228:      * Returns the memory usage of the current application.
229:      * This method relies on the PHP function memory_get_usage().
230:      * If it is not available, the method will attempt to use OS programs
231:      * to determine the memory usage. A value 0 will be returned if the
232:      * memory usage can still not be determined.
233:      * @return integer memory usage of the application (in bytes).
234:      */
235:     public function getMemoryUsage()
236:     {
237:         if(function_exists('memory_get_usage'))
238:             return memory_get_usage();
239:         else
240:         {
241:             $output=array();
242:             if(strncmp(PHP_OS,'WIN',3)===0)
243:             {
244:                 exec('tasklist /FI "PID eq ' . getmypid() . '" /FO LIST',$output);
245:                 return isset($output[5])?preg_replace('/[\D]/','',$output[5])*1024 : 0;
246:             }
247:             else
248:             {
249:                 $pid=getmypid();
250:                 exec("ps -eo%mem,rss,pid | grep $pid", $output);
251:                 $output=explode("  ",$output[0]);
252:                 return isset($output[1]) ? $output[1]*1024 : 0;
253:             }
254:         }
255:     }
256: 
257:     /**
258:      * Returns the profiling results.
259:      * The results may be filtered by token and/or category.
260:      * If no filter is specified, the returned results would be an array with each element
261:      * being array($token,$category,$time).
262:      * If a filter is specified, the results would be an array of timings.
263:      *
264:      * Since 1.1.11, filtering results by category supports the same format used for filtering logs in
265:      * {@link getLogs}, and similarly supports filtering by multiple categories and wildcard.
266:      * @param string $token token filter. Defaults to null, meaning not filtered by token.
267:      * @param string $categories category filter. Defaults to null, meaning not filtered by category.
268:      * @param boolean $refresh whether to refresh the internal timing calculations. If false,
269:      * only the first time calling this method will the timings be calculated internally.
270:      * @return array the profiling results.
271:      */
272:     public function getProfilingResults($token=null,$categories=null,$refresh=false)
273:     {
274:         if($this->_timings===null || $refresh)
275:             $this->calculateTimings();
276:         if($token===null && $categories===null)
277:             return $this->_timings;
278: 
279:         $timings = $this->_timings;
280:         if($categories!==null) {
281:             $this->_categories=preg_split('/[\s,]+/',strtolower($categories),-1,PREG_SPLIT_NO_EMPTY);
282:             $timings=array_filter($timings,array($this,'filterTimingByCategory'));
283:         }
284: 
285:         $results=array();
286:         foreach($timings as $timing)
287:         {
288:             if($token===null || $timing[0]===$token)
289:                 $results[]=$timing[2];
290:         }
291:         return $results;
292:     }
293: 
294:     private function calculateTimings()
295:     {
296:         $this->_timings=array();
297: 
298:         $stack=array();
299:         foreach($this->_logs as $log)
300:         {
301:             if($log[1]!==CLogger::LEVEL_PROFILE)
302:                 continue;
303:             list($message,$level,$category,$timestamp)=$log;
304:             if(!strncasecmp($message,'begin:',6))
305:             {
306:                 $log[0]=substr($message,6);
307:                 $stack[]=$log;
308:             }
309:             elseif(!strncasecmp($message,'end:',4))
310:             {
311:                 $token=substr($message,4);
312:                 if(($last=array_pop($stack))!==null && $last[0]===$token)
313:                 {
314:                     $delta=$log[3]-$last[3];
315:                     $this->_timings[]=array($message,$category,$delta);
316:                 }
317:                 else
318:                     throw new CException(Yii::t('yii','CProfileLogRoute found a mismatching code block "{token}". Make sure the calls to Yii::beginProfile() and Yii::endProfile() be properly nested.',
319:                         array('{token}'=>$token)));
320:             }
321:         }
322: 
323:         $now=microtime(true);
324:         while(($last=array_pop($stack))!==null)
325:         {
326:             $delta=$now-$last[3];
327:             $this->_timings[]=array($last[0],$last[2],$delta);
328:         }
329:     }
330: 
331:     /**
332:      * Removes all recorded messages from the memory.
333:      * This method will raise an {@link onFlush} event.
334:      * The attached event handlers can process the log messages before they are removed.
335:      * @param boolean $dumpLogs whether to process the logs immediately as they are passed to log route
336:      * @since 1.1.0
337:      */
338:     public function flush($dumpLogs=false)
339:     {
340:         $this->onFlush(new CEvent($this, array('dumpLogs'=>$dumpLogs)));
341:         $this->_logs=array();
342:         $this->_logCount=0;
343:     }
344: 
345:     /**
346:      * Raises an <code>onFlush</code> event.
347:      * @param CEvent $event the event parameter
348:      * @since 1.1.0
349:      */
350:     public function onFlush($event)
351:     {
352:         $this->raiseEvent('onFlush', $event);
353:     }
354: }
355: 
API documentation generated by ApiGen 2.8.0