Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
Y
yii2
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
PSDI Army
yii2
Commits
6d2e0ba6
Commit
6d2e0ba6
authored
Aug 04, 2011
by
Qiang Xue
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
w
parent
43777054
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
270 additions
and
458 deletions
+270
-458
YiiBase.php
framework/YiiBase.php
+6
-1
Component.php
framework/base/Component.php
+2
-3
Initable.php
framework/base/Initable.php
+3
-16
Model.php
framework/base/Model.php
+0
-12
EmailTarget.php
framework/logging/EmailTarget.php
+37
-106
Filter.php
framework/logging/Filter.php
+0
-108
Logger.php
framework/logging/Logger.php
+75
-115
Router.php
framework/logging/Router.php
+3
-2
Target.php
framework/logging/Target.php
+144
-95
No files found.
framework/YiiBase.php
View file @
6d2e0ba6
...
@@ -160,6 +160,9 @@ class YiiBase
...
@@ -160,6 +160,9 @@ class YiiBase
* In the latter case, the root alias will be replaced by the corresponding registered path
* In the latter case, the root alias will be replaced by the corresponding registered path
* and the remaining part will be appended to it.
* and the remaining part will be appended to it.
*
*
* In case the given alias is not an alias (i.e., not starting with '@'),
* it will be returned back as is.
*
* Note, this method does not ensure the existence of the resulting path.
* Note, this method does not ensure the existence of the resulting path.
* @param string $alias alias
* @param string $alias alias
* @return mixed path corresponding to the alias, false if the root alias is not previously registered.
* @return mixed path corresponding to the alias, false if the root alias is not previously registered.
...
@@ -175,6 +178,9 @@ class YiiBase
...
@@ -175,6 +178,9 @@ class YiiBase
if
(
isset
(
self
::
$aliases
[
$rootAlias
]))
{
if
(
isset
(
self
::
$aliases
[
$rootAlias
]))
{
return
self
::
$aliases
[
$alias
]
=
self
::
$aliases
[
$rootAlias
]
.
substr
(
$alias
,
$pos
);
return
self
::
$aliases
[
$alias
]
=
self
::
$aliases
[
$rootAlias
]
.
substr
(
$alias
,
$pos
);
}
}
else
if
(
$alias
[
0
]
!==
'@'
)
{
// not an alias
return
$alias
;
}
}
}
return
false
;
return
false
;
}
}
...
@@ -344,7 +350,6 @@ class YiiBase
...
@@ -344,7 +350,6 @@ class YiiBase
}
}
if
(
$object
instanceof
Initable
)
{
if
(
$object
instanceof
Initable
)
{
$object
->
preinit
();
foreach
(
$config
as
$name
=>
$value
)
{
foreach
(
$config
as
$name
=>
$value
)
{
$object
->
$name
=
$value
;
$object
->
$name
=
$value
;
}
}
...
...
framework/base/Component.php
View file @
6d2e0ba6
...
@@ -307,9 +307,9 @@ class Component
...
@@ -307,9 +307,9 @@ class Component
* Creates a new component instance.
* Creates a new component instance.
*
*
* This method differs from the PHP `new` operator in that it does the following
* This method differs from the PHP `new` operator in that it does the following
*
additional work after the component is created
:
*
steps to create a new component instance
:
*
*
* - Call
[[Initable::preinit|preinit]] if the class implements [[Initable]]
;
* - Call
class constructor (same the `new` operator)
;
* - Initialize the component properties using the name-value pairs given as the
* - Initialize the component properties using the name-value pairs given as the
* last parameter to this method;
* last parameter to this method;
* - Call [[Initable::init|init]] if the class implements [[Initable]].
* - Call [[Initable::init|init]] if the class implements [[Initable]].
...
@@ -329,7 +329,6 @@ class Component
...
@@ -329,7 +329,6 @@ class Component
* $model = Foo::create(1, 2, array('c' => 3));
* $model = Foo::create(1, 2, array('c' => 3));
* // which is equivalent to the following lines:
* // which is equivalent to the following lines:
* $model = new Foo(1, 2);
* $model = new Foo(1, 2);
* $model->preinit();
* $model->c = 3;
* $model->c = 3;
* $model->init();
* $model->init();
* ~~~
* ~~~
...
...
framework/base/Initable.php
View file @
6d2e0ba6
...
@@ -13,9 +13,9 @@ namespace yii\base;
...
@@ -13,9 +13,9 @@ namespace yii\base;
* Initable is an interface indicating a class needs initialization to work properly.
* Initable is an interface indicating a class needs initialization to work properly.
*
*
* Initable requires a class to implement the [[init]] method.
* Initable requires a class to implement the [[init]] method.
* When [[\Yii::createComponent]] is
creating a new component instance, if the component
* When [[\Yii::createComponent]] is
being used to create a new component which implements
*
class implements Initable interface, the method will call its [[init]] method
*
Initable, it will call the [[init]] method after setting the initial values of the
*
after setting the initial values of the
component properties.
* component properties.
*
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
* @since 2.0
...
@@ -23,23 +23,10 @@ namespace yii\base;
...
@@ -23,23 +23,10 @@ namespace yii\base;
interface
Initable
interface
Initable
{
{
/**
/**
* Pre-initializes this component.
* This method is invoked by [[\Yii::createComponent]] after its creates the new
* component instance, but BEFORE the component properties are initialized.
*
* You may implement this method to do work such as setting property default values.
*/
public
function
preinit
();
/**
* Initializes this component.
* Initializes this component.
* This method is invoked by [[\Yii::createComponent]] after its creates the new
* This method is invoked by [[\Yii::createComponent]] after its creates the new
* component instance and initializes the component properties. In other words,
* component instance and initializes the component properties. In other words,
* at this stage, the component has been fully configured.
* at this stage, the component has been fully configured.
*
* The default implementation calls [[behaviors]] and registers any available behaviors.
* You may override this method with additional initialization logic (e.g. establish DB connection).
* Make sure you call the parent implementation.
*/
*/
public
function
init
();
public
function
init
();
}
}
framework/base/Model.php
View file @
6d2e0ba6
...
@@ -50,18 +50,6 @@ class Model extends Component implements Initable, \IteratorAggregate, \ArrayAcc
...
@@ -50,18 +50,6 @@ class Model extends Component implements Initable, \IteratorAggregate, \ArrayAcc
}
}
/**
/**
* Pre-initializes this model.
* This method is required by the [[Initable]] interface. It is invoked by
* [[\Yii::createComponent]] after its creates the new model instance but
* BEFORE the model properties are initialized.
*
* You may override this method to do work such as setting property default values.
*/
public
function
preinit
()
{
}
/**
* Initializes this model.
* Initializes this model.
*
*
* This method is required by the [[Initable]] interface. It is invoked by [[\Yii::createComponent]]
* This method is required by the [[Initable]] interface. It is invoked by [[\Yii::createComponent]]
...
...
framework/logging/EmailTarget.php
View file @
6d2e0ba6
<?php
<?php
/**
/**
*
CEmailLogRoute
class file.
*
EmailTarget
class file.
*
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/
* @link http://www.yiiframework.com/
* @copyright Copyright © 2008-201
1
Yii Software LLC
* @copyright Copyright © 2008-201
2
Yii Software LLC
* @license http://www.yiiframework.com/license/
* @license http://www.yiiframework.com/license/
*/
*/
namespace
yii\logging
;
/**
/**
*
CEmailLogRoute sends selected log messages to
email addresses.
*
EmailTarget sends selected log messages to the specified
email addresses.
*
*
* The target email addresses may be specified via
{@link setEmails emails}
property.
* The target email addresses may be specified via
[[emails]]
property.
* Optionally, you may set the email
{@link setSubject subject}, the
* Optionally, you may set the email
[[subject]], [[sentFrom]] address and
*
{@link setSentFrom sentFrom} address and any additional {@link setHeaders headers}
.
*
additional [[headers]]
.
*
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @author Qiang Xue <qiang.xue@gmail.com>
* @version $Id: CEmailLogRoute.php 3001 2011-02-24 16:42:44Z alexander.makarow $
* @since 2.0
* @package system.logging
* @since 1.0
*/
*/
class
CEmailLogRoute
extends
CLogRoute
class
EmailTarget
extends
Target
{
{
/**
/**
* @var array list of destination email addresses.
* @var array list of destination email addresses.
*/
*/
p
rivate
$_email
=
array
();
p
ublic
$emails
=
array
();
/**
/**
* @var string email subject
* @var string email subject
*/
*/
p
rivate
$_
subject
;
p
ublic
$
subject
;
/**
/**
* @var string email sent
from address
* @var string email sent
-
from address
*/
*/
p
rivate
$_f
rom
;
p
ublic
$sentF
rom
;
/**
/**
* @var array list of additional headers to use when sending an email.
* @var array list of additional headers to use when sending an email.
*/
*/
p
rivate
$_
headers
=
array
();
p
ublic
$
headers
=
array
();
/**
/**
* Sends log
messages
to specified email addresses.
* Sends log
[[messages]]
to specified email addresses.
* @param
array $logs list of log messages
* @param
boolean $final whether this method is called at the end of the current application
*/
*/
p
rotected
function
processLogs
(
$logs
)
p
ublic
function
exportMessages
(
$final
)
{
{
$message
=
''
;
$body
=
''
;
foreach
(
$logs
as
$log
)
foreach
(
$this
->
messages
as
$message
)
{
$message
.=
$this
->
formatLogMessage
(
$log
[
0
],
$log
[
1
],
$log
[
2
],
$log
[
3
]);
$body
.=
$this
->
formatMessage
(
$message
);
$message
=
wordwrap
(
$message
,
70
);
$subject
=
$this
->
getSubject
();
if
(
$subject
===
null
)
$subject
=
Yii
::
t
(
'yii'
,
'Application Log'
);
foreach
(
$this
->
getEmails
()
as
$email
)
$this
->
sendEmail
(
$email
,
$subject
,
$message
);
}
}
$body
=
wordwrap
(
$body
,
70
);
/**
$subject
=
$this
->
subject
===
null
?
Yii
::
t
(
'yii'
,
'Application Log'
)
:
$this
->
subject
;
* Sends an email.
foreach
(
$this
->
emails
as
$email
)
{
* @param string $email single email address
$this
->
sendEmail
(
$subject
,
$body
,
$email
,
$this
->
sentFrom
,
$this
->
headers
);
* @param string $subject email subject
* @param string $message email content
*/
protected
function
sendEmail
(
$email
,
$subject
,
$message
)
{
$headers
=
$this
->
getHeaders
();
if
((
$from
=
$this
->
getSentFrom
())
!==
null
)
$headers
[]
=
"From:
{
$from
}
"
;
mail
(
$email
,
$subject
,
$message
,
implode
(
"
\r\n
"
,
$headers
));
}
}
/**
$this
->
messages
=
array
();
* @return array list of destination email addresses
*/
public
function
getEmails
()
{
return
$this
->
_email
;
}
}
/**
/**
* @param mixed $value list of destination email addresses. If the value is
* Sends an email.
* a string, it is assumed to be comma-separated email addresses.
* @param string $subject email subject
*/
* @param string $body email body
public
function
setEmails
(
$value
)
* @param string $sentTo sent-to email address
{
* @param string $sentFrom sent-from email address
if
(
is_array
(
$value
))
* @param array $headers additional headers to be used when sending the email
$this
->
_email
=
$value
;
else
$this
->
_email
=
preg_split
(
'/[\s,]+/'
,
$value
,
-
1
,
PREG_SPLIT_NO_EMPTY
);
}
/**
* @return string email subject. Defaults to CEmailLogRoute::DEFAULT_SUBJECT
*/
public
function
getSubject
()
{
return
$this
->
_subject
;
}
/**
* @param string $value email subject.
*/
public
function
setSubject
(
$value
)
{
$this
->
_subject
=
$value
;
}
/**
* @return string send from address of the email
*/
public
function
getSentFrom
()
{
return
$this
->
_from
;
}
/**
* @param string $value send from address of the email
*/
public
function
setSentFrom
(
$value
)
{
$this
->
_from
=
$value
;
}
/**
* @return array additional headers to use when sending an email.
* @since 1.1.4
*/
*/
p
ublic
function
getHeaders
(
)
p
rotected
function
sendEmail
(
$subject
,
$body
,
$sentTo
,
$sentFrom
,
$headers
)
{
{
return
$this
->
_headers
;
if
(
$sentFrom
!==
null
)
{
$headers
[]
=
"From:
{
$sentFrom
}
"
;
}
}
mail
(
$email
,
$subject
,
$body
,
implode
(
"
\r\n
"
,
$headers
));
/**
* @param mixed $value list of additional headers to use when sending an email.
* If the value is a string, it is assumed to be line break separated headers.
* @since 1.1.4
*/
public
function
setHeaders
(
$value
)
{
if
(
is_array
(
$value
))
$this
->
_headers
=
$value
;
else
$this
->
_headers
=
preg_split
(
'/\r\n|\n/'
,
$value
,
-
1
,
PREG_SPLIT_NO_EMPTY
);
}
}
}
}
\ No newline at end of file
framework/logging/Filter.php
deleted
100644 → 0
View file @
43777054
<?php
/**
* CLogFilter class file
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/
* @copyright Copyright © 2008-2011 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
/**
* CLogFilter preprocesses the logged messages before they are handled by a log route.
*
* CLogFilter is meant to be used by a log route to preprocess the logged messages
* before they are handled by the route. The default implementation of CLogFilter
* prepends additional context information to the logged messages. In particular,
* by setting {@link logVars}, predefined PHP variables such as
* $_SERVER, $_POST, etc. can be saved as a log message, which may help identify/debug
* issues encountered.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @version $Id: CLogFilter.php 3204 2011-05-05 21:36:32Z alexander.makarow $
* @package system.logging
* @since 1.0.6
*/
class
CLogFilter
extends
CComponent
{
/**
* @var boolean whether to prefix each log message with the current user session ID.
* Defaults to false.
*/
public
$prefixSession
=
false
;
/**
* @var boolean whether to prefix each log message with the current user
* {@link CWebUser::name name} and {@link CWebUser::id ID}. Defaults to false.
*/
public
$prefixUser
=
false
;
/**
* @var boolean whether to log the current user name and ID. Defaults to true.
*/
public
$logUser
=
true
;
/**
* @var array list of the PHP predefined variables that should be logged.
* Note that a variable must be accessible via $GLOBALS. Otherwise it won't be logged.
*/
public
$logVars
=
array
(
'_GET'
,
'_POST'
,
'_FILES'
,
'_COOKIE'
,
'_SESSION'
,
'_SERVER'
);
/**
* Filters the given log messages.
* This is the main method of CLogFilter. It processes the log messages
* by adding context information, etc.
* @param array $logs the log messages
* @return array
*/
public
function
filter
(
&
$logs
)
{
if
(
!
empty
(
$logs
))
{
if
((
$message
=
$this
->
getContext
())
!==
''
)
array_unshift
(
$logs
,
array
(
$message
,
CLogger
::
LEVEL_INFO
,
'application'
,
YII_BEGIN_TIME
));
$this
->
format
(
$logs
);
}
return
$logs
;
}
/**
* Formats the log messages.
* The default implementation will prefix each message with session ID
* if {@link prefixSession} is set true. It may also prefix each message
* with the current user's name and ID if {@link prefixUser} is true.
* @param array $logs the log messages
*/
protected
function
format
(
&
$logs
)
{
$prefix
=
''
;
if
(
$this
->
prefixSession
&&
(
$id
=
session_id
())
!==
''
)
$prefix
.=
"[
$id
]"
;
if
(
$this
->
prefixUser
&&
(
$user
=
Yii
::
app
()
->
getComponent
(
'user'
,
false
))
!==
null
)
$prefix
.=
'['
.
$user
->
getName
()
.
']['
.
$user
->
getId
()
.
']'
;
if
(
$prefix
!==
''
)
{
foreach
(
$logs
as
&
$log
)
$log
[
0
]
=
$prefix
.
' '
.
$log
[
0
];
}
}
/**
* Generates the context information to be logged.
* The default implementation will dump user information, system variables, etc.
* @return string the context information. If an empty string, it means no context information.
*/
protected
function
getContext
()
{
$context
=
array
();
if
(
$this
->
logUser
&&
(
$user
=
Yii
::
app
()
->
getComponent
(
'user'
,
false
))
!==
null
)
$context
[]
=
'User: '
.
$user
->
getName
()
.
' (ID: '
.
$user
->
getId
()
.
')'
;
foreach
(
$this
->
logVars
as
$name
)
{
if
(
!
empty
(
$GLOBALS
[
$name
]))
$context
[]
=
"
\$
{
$name
}
="
.
var_export
(
$GLOBALS
[
$name
],
true
);
}
return
implode
(
"
\n\n
"
,
$context
);
}
}
\ No newline at end of file
framework/logging/Logger.php
View file @
6d2e0ba6
...
@@ -38,20 +38,26 @@ class Logger extends \yii\base\Component
...
@@ -38,20 +38,26 @@ class Logger extends \yii\base\Component
public
$flushInterval
=
1000
;
public
$flushInterval
=
1000
;
/**
/**
* @var boolean this property will be passed as the parameter to [[flush]] when it is
* @var boolean this property will be passed as the parameter to [[flush]] when it is
* called due to the [[flushInterval]] is reached. Defaults to
fals
e, meaning the flushed
* called due to the [[flushInterval]] is reached. Defaults to
tru
e, meaning the flushed
* messages
are still kept in the memory by each log target. If this is true, they will
* messages
will be exported to the actual storage medium (e.g. DB, email) defined by each
*
be exported to the actual storage medium (e.g. DB, email) defined by
each log target.
*
log target. If false, the flushed messages will be kept in the memory of
each log target.
* @see flushInterval
* @see flushInterval
*/
*/
public
$autoExport
=
fals
e
;
public
$autoExport
=
tru
e
;
/**
/**
* @var array logged messages. This property is mainly managed by [[log]] and [[flush]].
* @var array logged messages. This property is mainly managed by [[log]] and [[flush]].
* Each log message is of the following structure:
*
* ~~~
* array(
* [0] => message (string)
* [1] => level (string)
* [2] => category (string)
* [3] => timestamp (float, obtained by microtime(true))
* )
* ~~~
*/
*/
public
$messages
=
array
();
public
$messages
=
array
();
/**
* @var array the profiling results (category, token => time in seconds)
*/
private
$_timings
;
/**
/**
* Logs an error message.
* Logs an error message.
...
@@ -155,72 +161,24 @@ class Logger extends \yii\base\Component
...
@@ -155,72 +161,24 @@ class Logger extends \yii\base\Component
}
}
/**
/**
* Retrieves log messages.
* Removes all recorded messages from the memory.
*
* This method will raise an {@link onFlush} event.
* Messages may be filtered by log levels and/or categories.
* The attached event handlers can process the log messages before they are removed.
* A level filter is specified by a list of levels separated by comma or space
* @param boolean $export whether to notify log targets to export the filtered messages they have received.
* (e.g. 'trace, error'). A category filter is similar to level filter
* (e.g. 'system, system.web'). A difference is that in category filter
* you can use pattern like 'system.*' to indicate all categories starting
* with 'system'.
*
* If you do not specify level filter, it will bring back logs at all levels.
* The same applies to category filter.
*
* Level filter and category filter are combinational, i.e., only messages
* satisfying both filter conditions will be returned.
*
* @param string $levels level filter
* @param string $categories category filter
* @return array list of messages. Each array elements represents one message
* with the following structure:
* array(
* [0] => message (string)
* [1] => level (string)
* [2] => category (string)
* [3] => timestamp (float, obtained by microtime(true));
*/
public
function
getLogs
(
$levels
=
''
,
$categories
=
''
)
{
$this
->
_levels
=
preg_split
(
'/[\s,]+/'
,
strtolower
(
$levels
),
-
1
,
PREG_SPLIT_NO_EMPTY
);
$this
->
_categories
=
preg_split
(
'/[\s,]+/'
,
strtolower
(
$categories
),
-
1
,
PREG_SPLIT_NO_EMPTY
);
if
(
empty
(
$levels
)
&&
empty
(
$categories
))
return
$this
->
_logs
;
elseif
(
empty
(
$levels
))
return
array_values
(
array_filter
(
array_filter
(
$this
->
_logs
,
array
(
$this
,
'filterByCategory'
))));
elseif
(
empty
(
$categories
))
return
array_values
(
array_filter
(
array_filter
(
$this
->
_logs
,
array
(
$this
,
'filterByLevel'
))));
else
{
$ret
=
array_values
(
array_filter
(
array_filter
(
$this
->
_logs
,
array
(
$this
,
'filterByLevel'
))));
return
array_values
(
array_filter
(
array_filter
(
$ret
,
array
(
$this
,
'filterByCategory'
))));
}
}
/**
* Filter function used by {@link getLogs}
* @param array $value element to be filtered
* @return array valid log, false if not.
*/
*/
private
function
filterByCategory
(
$value
)
public
function
flush
(
$export
=
false
)
{
foreach
(
$this
->
_categories
as
$category
)
{
{
$cat
=
strtolower
(
$value
[
2
]);
$this
->
onFlush
(
new
\yii\base\Event
(
$this
,
array
(
'export'
=>
$export
,
'flush'
=>
true
)));
if
(
$cat
===
$category
||
((
$c
=
rtrim
(
$category
,
'.*'
))
!==
$category
&&
strpos
(
$cat
,
$c
)
===
0
))
$this
->
messages
=
array
();
return
$value
;
}
return
false
;
}
}
/**
/**
* Filter function used by {@link getLogs}
* Raises an `onFlush` event.
* @param array $value element to be filtered
* @param \yii\base\Event $event the event parameter
* @return array valid log, false if not.
*/
*/
p
rivate
function
filterByLevel
(
$value
)
p
ublic
function
onFlush
(
$event
)
{
{
return
in_array
(
strtolower
(
$value
[
1
]),
$this
->
_levels
)
?
$value
:
false
;
$this
->
raiseEvent
(
'onFlush'
,
$event
)
;
}
}
/**
/**
...
@@ -237,36 +195,58 @@ class Logger extends \yii\base\Component
...
@@ -237,36 +195,58 @@ class Logger extends \yii\base\Component
/**
/**
* Returns the profiling results.
* Returns the profiling results.
* The results may be filtered by token and/or category.
*
* If no filter is specified, the returned results would be an array with each element
* By default, all profiling results will be returned. You may provide
* being `array($token, $category, $time)`.
* `$categories` and `$excludeCategories` as parameters to retrieve the
* If a filter is specified, the results would be an array of timings.
* results that you are interested in.
* @param string $token token filter. Defaults to null, meaning not filtered by token.
*
* @param string $category category filter. Defaults to null, meaning not filtered by category.
* @param array $categories list of categories that you are interested in.
* @param boolean $refresh whether to refresh the internal timing calculations. If false,
* You can use an asterisk at the end of a category to do a prefix match.
* only the first time calling this method will the timings be calculated internally.
* For example, 'yii\db\*' will match categories starting with 'yii\db\',
* @return array the profiling results.
* such as 'yii\db\dao\Connection'.
* @param array $excludeCategories list of categories that you are interested in.
* @return array the profiling results. Each array element has the following structure:
* `array($category, $time)`.
*/
*/
public
function
getProfiling
Results
(
$token
=
null
,
$category
=
null
,
$refresh
=
false
)
public
function
getProfiling
(
$categories
=
array
(),
$excludeCategories
=
array
()
)
{
{
if
(
$this
->
_timings
===
null
||
$refresh
)
{
$timings
=
$this
->
calculateTimings
();
$this
->
calculateTimings
();
if
(
empty
(
$categories
)
&&
empty
(
$excludeCategories
))
{
return
$timings
;
}
foreach
(
$timings
as
$i
=>
$timing
)
{
$matched
=
empty
(
$categories
);
foreach
(
$categories
as
$category
)
{
$prefix
=
rtrim
(
$category
,
'*'
);
if
(
strpos
(
$timing
[
0
],
$prefix
)
===
0
&&
(
$timing
[
0
]
===
$category
||
$prefix
!==
$category
))
{
$matched
=
true
;
break
;
}
}
if
(
$matched
)
{
foreach
(
$excludeCategories
as
$category
)
{
$prefix
=
rtrim
(
$category
,
'*'
);
foreach
(
$timings
as
$i
=>
$timing
)
{
if
(
strpos
(
$timing
[
0
],
$prefix
)
===
0
&&
(
$timing
[
0
]
===
$category
||
$prefix
!==
$category
))
{
$matched
=
false
;
break
;
}
}
}
if
(
$token
===
null
&&
$category
===
null
)
{
return
$this
->
_timings
;
}
}
$results
=
array
();
}
foreach
(
$this
->
_timings
as
$timing
)
{
if
(
(
$category
===
null
||
$timing
[
1
]
===
$category
)
&&
(
$token
===
null
||
$timing
[
0
]
===
$token
)
)
{
if
(
!
$matched
)
{
$results
[]
=
$timing
[
2
]
;
unset
(
$timings
[
$i
])
;
}
}
}
}
return
$results
;
return
array_values
(
$timings
)
;
}
}
private
function
calculateTimings
()
private
function
calculateTimings
()
{
{
$t
his
->
_t
imings
=
array
();
$timings
=
array
();
$stack
=
array
();
$stack
=
array
();
foreach
(
$this
->
messages
as
$log
)
{
foreach
(
$this
->
messages
as
$log
)
{
...
@@ -274,18 +254,16 @@ class Logger extends \yii\base\Component
...
@@ -274,18 +254,16 @@ class Logger extends \yii\base\Component
continue
;
continue
;
}
}
list
(
$message
,
$level
,
$category
,
$timestamp
)
=
$log
;
list
(
$message
,
$level
,
$category
,
$timestamp
)
=
$log
;
if
(
!
strncasecmp
(
$message
,
'begin:'
,
6
))
{
if
(
$message
===
'begin'
)
{
$log
[
0
]
=
substr
(
$message
,
6
);
$stack
[]
=
$log
;
$stack
[]
=
$log
;
}
}
elseif
(
!
strncasecmp
(
$message
,
'end:'
,
4
))
{
else
{
// $message === 'end'
$token
=
substr
(
$message
,
4
);
if
((
$last
=
array_pop
(
$stack
))
!==
null
&&
$last
[
2
]
===
$category
)
{
if
((
$last
=
array_pop
(
$stack
))
!==
null
&&
$last
[
0
]
===
$token
)
{
$delta
=
$timestamp
-
$last
[
3
];
$delta
=
$log
[
3
]
-
$last
[
3
];
$timings
[]
=
array
(
$category
,
$delta
);
$this
->
_timings
[]
=
array
(
$message
,
$category
,
$delta
);
}
}
else
{
else
{
throw
new
\yii\base\Exception
(
'Found a mismatching profiling block: '
.
$
token
);
throw
new
\yii\base\Exception
(
'Found a mismatching profiling block: '
.
$
category
);
}
}
}
}
}
}
...
@@ -293,28 +271,10 @@ class Logger extends \yii\base\Component
...
@@ -293,28 +271,10 @@ class Logger extends \yii\base\Component
$now
=
microtime
(
true
);
$now
=
microtime
(
true
);
while
((
$last
=
array_pop
(
$stack
))
!==
null
)
{
while
((
$last
=
array_pop
(
$stack
))
!==
null
)
{
$delta
=
$now
-
$last
[
3
];
$delta
=
$now
-
$last
[
3
];
$this
->
_timings
[]
=
array
(
$last
[
0
],
$last
[
2
],
$delta
);
$timings
[]
=
array
(
$last
[
2
],
$delta
);
}
}
}
/**
return
$timings
;
* Removes all recorded messages from the memory.
* This method will raise an {@link onFlush} event.
* The attached event handlers can process the log messages before they are removed.
* @param boolean $export whether to notify log targets to export the filtered messages they have received.
*/
public
function
flush
(
$export
=
false
)
{
$this
->
onFlush
(
new
\yii\base\Event
(
$this
,
array
(
'export'
=>
$export
)));
$this
->
messages
=
array
();
}
}
/**
* Raises an `onFlush` event.
* @param \yii\base\Event $event the event parameter
*/
public
function
onFlush
(
$event
)
{
$this
->
raiseEvent
(
'onFlush'
,
$event
);
}
}
}
framework/logging/Router.php
View file @
6d2e0ba6
...
@@ -125,11 +125,12 @@ class Router extends \yii\base\ApplicationComponent
...
@@ -125,11 +125,12 @@ class Router extends \yii\base\ApplicationComponent
*/
*/
public
function
processMessages
(
$event
)
public
function
processMessages
(
$event
)
{
{
$
logger
=
Yii
::
getLogger
()
;
$
messages
=
\Yii
::
getLogger
()
->
messages
;
$export
=
!
isset
(
$event
->
params
[
'export'
])
||
$event
->
params
[
'export'
];
$export
=
!
isset
(
$event
->
params
[
'export'
])
||
$event
->
params
[
'export'
];
$final
=
!
isset
(
$event
-
params
[
'flush'
])
||
!
$event
->
params
[
'flush'
];
foreach
(
$this
->
_targets
as
$target
)
{
foreach
(
$this
->
_targets
as
$target
)
{
if
(
$target
->
enabled
)
{
if
(
$target
->
enabled
)
{
$target
->
processMessages
(
$
logger
,
$export
);
$target
->
processMessages
(
$
messages
,
$export
,
$final
);
}
}
}
}
}
}
...
...
framework/logging/Target.php
View file @
6d2e0ba6
...
@@ -13,18 +13,15 @@ namespace yii\logging;
...
@@ -13,18 +13,15 @@ namespace yii\logging;
/**
/**
* Target is the base class for all log target classes.
* Target is the base class for all log target classes.
*
*
* A log target object retrieves log messages from a logger and sends it
* A log target object will filter the messages logged by [[Logger]] according
* somewhere, such as files, emails.
* to its [[levels]] and [[categories]] properties. It may also export the filtered
* The messages being retrieved may be filtered first before being sent
* messages to specific destination defined by the target, such as emails, files.
* to the destination. The filters include log level filter and log category filter.
*
* To specify level filter, set {@link levels} property,
* which takes a string of comma-separated desired level names (e.g. 'Error, Debug').
* To specify category filter, set {@link categories} property,
* which takes a string of comma-separated desired category names (e.g. 'System.Web, System.IO').
*
*
* Level filter and category filter are combinational, i.e., only messages
* Level filter and category filter are combinational, i.e., only messages
* satisfying both filter conditions will they be returned.
* satisfying both filter conditions will they be returned. Additionally, you
* may specify [[excludeCategories]]. If a message's category falls within the excluded
* categories, it will be filtered out, even if it passes the [[levels]] and
* [[categories]] filters.
*
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
* @since 2.0
...
@@ -36,42 +33,57 @@ abstract class Target extends \yii\base\Component implements \yii\base\Initable
...
@@ -36,42 +33,57 @@ abstract class Target extends \yii\base\Component implements \yii\base\Initable
*/
*/
public
$enabled
=
true
;
public
$enabled
=
true
;
/**
/**
* @var string list of levels separated by comma or space. Defaults to empty, meaning all levels.
* @var array list of message levels that this target is interested in. Defaults to empty, meaning all levels.
*/
public
$levels
=
array
();
/**
* @var array list of message categories that this target is interested in. Defaults to empty, meaning all categories.
* You can use an asterisk at the end of a category so that the category may be used to
* match those categories sharing the same common prefix. For example, 'yii\db\*' will match
* categories starting with 'yii\db\', such as 'yii\db\dao\Connection'.
*/
public
$categories
=
array
();
/**
* @var array list of message categories that this target is NOT interested in. Defaults to empty, meaning no uninteresting messages.
* If this property is not empty, then any category listed here will be excluded from [[categories]].
* You can use an asterisk at the end of a category so that the category can be used to
* match those categories sharing the same common prefix. For example, 'yii\db\*' will match
* categories starting with 'yii\db\', such as 'yii\db\dao\Connection'.
* @see categories
*/
*/
public
$
levels
;
public
$
excludeCategories
=
array
()
;
/**
/**
* @var
string list of categories separated by comma or space. Defaults to empty, meaning all categories
.
* @var
boolean whether to prefix each log message with the current session ID. Defaults to false
.
*/
*/
public
$
categories
;
public
$
prefixSession
=
false
;
/**
/**
* @var string list of categories that should be excluded.
* @var boolean whether to prefix each log message with the current user name and ID. Defaults to false.
* @see \yii\web\User
*/
*/
public
$
excludeCategories
;
public
$
prefixUser
=
false
;
/**
/**
* @var mixed the additional filter (eg {@link CLogFilter}) that can be applied to the log messages.
* @var boolean whether to log a message containing the current user name and ID. Defaults to true.
* The value of this property will be passed to {@link Yii::createComponent} to create
* @see \yii\web\User
* a log filter object. As a result, this can be either a string representing the
* filter class name or an array representing the filter configuration.
* In general, the log filter class should be {@link CLogFilter} or a child class of it.
* Defaults to null, meaning no filter will be used.
*/
*/
public
$
filter
;
public
$
logUser
=
false
;
/**
/**
* @var array the messages that are collected so far by this log target.
* @var array list of the PHP predefined variables that should be logged in a message.
* Note that a variable must be accessible via `$GLOBALS`. Otherwise it won't be logged.
* Defaults to `array('_GET', '_POST', '_FILES', '_COOKIE', '_SESSION', '_SERVER')`.
*/
*/
public
$messages
;
public
$logVars
=
array
(
'_GET'
,
'_POST'
,
'_FILES'
,
'_COOKIE'
,
'_SESSION'
,
'_SERVER'
);
/**
* @var array the messages that are retrieved from the logger so far by this log target.
*/
public
$messages
=
array
();
/**
/**
* Pre-initializes this component.
* Exports log messages to a specific destination.
* This method is required by the [[Initable]] interface. It is invoked by
* Child classes must implement this method. Note that you may need
* [[\Yii::createComponent]] after its creates the new component instance but
* to clean up [[messages]] in this method to avoid re-exporting messages.
* BEFORE the component properties are initialized.
* @param boolean $final whether this method is called at the end of the current application
*
* You may override this method to do work such as setting property default values.
*/
*/
public
function
preinit
()
abstract
public
function
exportMessages
(
$final
);
{
}
/**
/**
* Initializes this component.
* Initializes this component.
...
@@ -83,89 +95,126 @@ abstract class Target extends \yii\base\Component implements \yii\base\Initable
...
@@ -83,89 +95,126 @@ abstract class Target extends \yii\base\Component implements \yii\base\Initable
}
}
/**
/**
* Formats a log message given different fields.
* Processes the given log messages.
* @param string $message message content
* This method will filter the given messages with [[levels]] and [[categories]].
* @param integer $level message level
* And if requested, it will also export the filtering result to specific medium (e.g. email).
* @param string $category message category
* @param array $messages log messages to be processed. See [[Logger::messages]] for the structure
* @param integer $time timestamp
* of each message.
* @return string formatted message
* @param boolean $export whether to export the processing result
* @param boolean $final whether this method is called at the end of the current application
*/
*/
p
rotected
function
formatMessage
(
$message
,
$level
,
$category
,
$time
)
p
ublic
function
processMessages
(
$messages
,
$export
,
$final
)
{
{
return
@
date
(
'Y/m/d H:i:s'
,
$time
)
.
" [
$level
] [
$category
]
$message
\n
"
;
$messages
=
$this
->
filterMessages
(
$messages
);
$this
->
messages
=
array_merge
(
$this
->
messages
,
$messages
);
if
(
$export
&&
!
empty
(
$this
->
messages
))
{
$this
->
prepareExport
(
$final
);
$this
->
exportMessages
(
$final
);
}
}
}
/**
/**
* Retrieves filtered log messages from logger for further processing.
* Prepares the [[messages]] for exporting.
* @param CLogger $logger logger instance
* This method will modify each message by prependding extra information
* @param boolean $processLogs whether to process the messages after they are collected from the logger
* if [[prefixSession]] and/or [[prefixUser]] are set true.
* It will also add an additional message showing context information if
* [[logUser]] and/or [[logVars]] are set.
* @param boolean $final whether this method is called at the end of the current application
*/
*/
public
function
processMessages
(
$logger
,
$export
)
protected
function
prepareExport
(
$final
)
{
$messages
=
$logger
->
getLogs
(
$this
->
levels
,
$this
->
categories
);
$this
->
messages
=
empty
(
$this
->
messages
)
?
$messages
:
array_merge
(
$this
->
messages
,
$messages
);
if
(
$processLogs
&&
!
empty
(
$this
->
messages
))
{
{
if
(
$this
->
filter
!==
null
)
$prefix
=
array
();
Yii
::
createComponent
(
$this
->
filter
)
->
filter
(
$this
->
messages
);
if
(
$this
->
prefixSession
&&
(
$id
=
session_id
())
!==
''
)
{
$this
->
processLogs
(
$this
->
messages
);
$prefix
[]
=
"[
$id
]"
;
$this
->
messages
=
array
();
}
}
if
(
$this
->
prefixUser
&&
(
$user
=
\Yii
::
app
()
->
getComponent
(
'user'
,
false
))
!==
null
)
{
$prefix
[]
=
'['
.
$user
->
getName
()
.
']'
;
$prefix
[]
=
'['
.
$user
->
getId
()
.
']'
;
}
if
(
$prefix
!==
array
())
{
$prefix
=
implode
(
' '
,
$prefix
);
foreach
(
$this
->
messages
as
$i
=>
$message
)
{
$this
->
messages
[
$i
][
0
]
=
$prefix
.
' '
.
$this
->
messages
[
$i
][
0
];
}
}
}
protected
function
filterMessages
(
$levels
=
''
,
$categories
=
''
)
if
(
$final
&&
(
$context
=
$this
->
getContextMessage
())
!==
''
)
{
{
$this
->
messages
[]
=
array
(
$context
,
Logger
::
LEVEL_INFO
,
'application'
,
YII_BEGIN_TIME
);
$this
->
_levels
=
preg_split
(
'/[\s,]+/'
,
strtolower
(
$levels
),
-
1
,
PREG_SPLIT_NO_EMPTY
);
$this
->
_categories
=
preg_split
(
'/[\s,]+/'
,
strtolower
(
$categories
),
-
1
,
PREG_SPLIT_NO_EMPTY
);
if
(
empty
(
$levels
)
&&
empty
(
$categories
))
return
$this
->
_logs
;
elseif
(
empty
(
$levels
))
return
array_values
(
array_filter
(
array_filter
(
$this
->
_logs
,
array
(
$this
,
'filterByCategory'
))));
elseif
(
empty
(
$categories
))
return
array_values
(
array_filter
(
array_filter
(
$this
->
_logs
,
array
(
$this
,
'filterByLevel'
))));
else
{
$ret
=
array_values
(
array_filter
(
array_filter
(
$this
->
_logs
,
array
(
$this
,
'filterByLevel'
))));
return
array_values
(
array_filter
(
array_filter
(
$ret
,
array
(
$this
,
'filterByCategory'
))));
}
}
}
}
/**
/**
*
Filter function used by {@link getLogs}
*
Generates the context information to be logged.
*
@param array $value element to be filtered
*
The default implementation will dump user information, system variables, etc.
* @return
array valid log, false if not
.
* @return
string the context information. If an empty string, it means no context information
.
*/
*/
protected
function
filterByCategory
(
$value
)
protected
function
getContextMessage
()
{
foreach
(
$this
->
_categories
as
$category
)
{
{
$cat
=
strtolower
(
$value
[
2
]);
$context
=
array
();
if
(
$cat
===
$category
||
((
$c
=
rtrim
(
$category
,
'.*'
))
!==
$category
&&
strpos
(
$cat
,
$c
)
===
0
))
if
(
$this
->
logUser
&&
(
$user
=
\Yii
::
app
()
->
getComponent
(
'user'
,
false
))
!==
null
)
{
return
$value
;
$context
[]
=
'User: '
.
$user
->
getName
()
.
' (ID: '
.
$user
->
getId
()
.
')'
;
}
foreach
(
$this
->
logVars
as
$name
)
{
if
(
!
empty
(
$GLOBALS
[
$name
]))
{
$context
[]
=
"
\$
{
$name
}
= "
.
var_export
(
$GLOBALS
[
$name
],
true
);
}
}
return
false
;
}
return
implode
(
"
\n\n
"
,
$context
);
}
}
/**
/**
* Filter function used by {@link getLogs}
* Filters the given messages according to their categories and levels.
* @param array $value element to be filtered
* @param array $messages messages to be filtered
* @return array valid log, false if not.
* @return array the filtered messages.
* @see filterByCategory
* @see filterByLevel
*/
*/
protected
function
filter
ByLevel
(
$value
)
protected
function
filter
Messages
(
$messages
)
{
{
return
in_array
(
strtolower
(
$value
[
1
]),
$this
->
_levels
)
?
$value
:
false
;
foreach
(
$messages
as
$i
=>
$message
)
{
if
(
!
empty
(
$this
->
levels
)
&&
!
in_array
(
$message
[
1
],
$this
->
levels
))
{
unset
(
$messages
[
$i
]);
continue
;
}
$matched
=
empty
(
$this
->
categories
);
foreach
(
$this
->
categories
as
$category
)
{
$prefix
=
rtrim
(
$category
,
'*'
);
if
(
strpos
(
$message
[
2
],
$prefix
)
===
0
&&
(
$message
[
2
]
===
$category
||
$prefix
!==
$category
))
{
$matched
=
true
;
break
;
}
}
if
(
$matched
)
{
foreach
(
$this
->
excludeCategories
as
$category
)
{
$prefix
=
rtrim
(
$category
,
'*'
);
foreach
(
$messages
as
$i
=>
$message
)
{
if
(
strpos
(
$message
[
2
],
$prefix
)
===
0
&&
(
$message
[
2
]
===
$category
||
$prefix
!==
$category
))
{
$matched
=
false
;
break
;
}
}
}
}
if
(
!
$matched
)
{
unset
(
$messages
[
$i
]);
}
}
return
$messages
;
}
}
/**
/**
* Processes log messages and sends them to specific destination.
* Formats a log message.
* Derived child classes must implement this method.
* The message structure follows that in [[Logger::messages]].
* @param array $messages list of messages. Each array elements represents one message
* @param array $message the log message to be formatted.
* with the following structure:
* @return string the formatted message
* array(
*/
* [0] => message (string)
public
function
formatMessage
(
$message
)
* [1] => level (string)
{
* [2] => category (string)
return
@
date
(
'Y/m/d H:i:s'
,
$message
[
3
])
.
" [
{
$message
[
1
]
}
] [
{
$message
[
2
]
}
]
{
$message
[
0
]
}
\n
"
;
* [3] => timestamp (float, obtained by microtime(true));
}
*/
abstract
protected
function
processLogs
(
$messages
);
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment