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
* In the latter case, the root alias will be replaced by the corresponding registered path
* 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.
* @param string $alias alias
* @return mixed path corresponding to the alias, false if the root alias is not previously registered.
...
...
@@ -175,6 +178,9 @@ class YiiBase
if
(
isset
(
self
::
$aliases
[
$rootAlias
]))
{
return
self
::
$aliases
[
$alias
]
=
self
::
$aliases
[
$rootAlias
]
.
substr
(
$alias
,
$pos
);
}
else
if
(
$alias
[
0
]
!==
'@'
)
{
// not an alias
return
$alias
;
}
}
return
false
;
}
...
...
@@ -344,7 +350,6 @@ class YiiBase
}
if
(
$object
instanceof
Initable
)
{
$object
->
preinit
();
foreach
(
$config
as
$name
=>
$value
)
{
$object
->
$name
=
$value
;
}
...
...
framework/base/Component.php
View file @
6d2e0ba6
...
...
@@ -307,9 +307,9 @@ class Component
* Creates a new component instance.
*
* 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
* last parameter to this method;
* - Call [[Initable::init|init]] if the class implements [[Initable]].
...
...
@@ -329,7 +329,6 @@ class Component
* $model = Foo::create(1, 2, array('c' => 3));
* // which is equivalent to the following lines:
* $model = new Foo(1, 2);
* $model->preinit();
* $model->c = 3;
* $model->init();
* ~~~
...
...
framework/base/Initable.php
View file @
6d2e0ba6
...
...
@@ -13,9 +13,9 @@ namespace yii\base;
* Initable is an interface indicating a class needs initialization to work properly.
*
* Initable requires a class to implement the [[init]] method.
* When [[\Yii::createComponent]] is
creating a new component instance, if the component
*
class implements Initable interface, the method will call its [[init]] method
*
after setting the initial values of the
component properties.
* When [[\Yii::createComponent]] is
being used to create a new component which implements
*
Initable, it will call the [[init]] method after setting the initial values of the
* component properties.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
...
...
@@ -23,23 +23,10 @@ namespace yii\base;
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.
* This method is invoked by [[\Yii::createComponent]] after its creates the new
* component instance and initializes the component properties. In other words,
* 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
();
}
framework/base/Model.php
View file @
6d2e0ba6
...
...
@@ -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.
*
* This method is required by the [[Initable]] interface. It is invoked by [[\Yii::createComponent]]
...
...
framework/logging/EmailTarget.php
View file @
6d2e0ba6
<?php
/**
*
CEmailLogRoute
class file.
*
EmailTarget
class file.
*
* @author Qiang Xue <qiang.xue@gmail.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/
*/
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.
* Optionally, you may set the email
{@link setSubject subject}, the
*
{@link setSentFrom sentFrom} address and any additional {@link setHeaders headers}
.
* The target email addresses may be specified via
[[emails]]
property.
* Optionally, you may set the email
[[subject]], [[sentFrom]] address and
*
additional [[headers]]
.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @version $Id: CEmailLogRoute.php 3001 2011-02-24 16:42:44Z alexander.makarow $
* @package system.logging
* @since 1.0
* @since 2.0
*/
class
CEmailLogRoute
extends
CLogRoute
class
EmailTarget
extends
Target
{
/**
* @var array list of destination email addresses.
*/
p
rivate
$_email
=
array
();
p
ublic
$emails
=
array
();
/**
* @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.
*/
p
rivate
$_
headers
=
array
();
p
ublic
$
headers
=
array
();
/**
* Sends log
messages
to specified email addresses.
* @param
array $logs list of log messages
* Sends log
[[messages]]
to specified email addresses.
* @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
=
''
;
foreach
(
$logs
as
$log
)
$message
.=
$this
->
formatLogMessage
(
$log
[
0
],
$log
[
1
],
$log
[
2
],
$log
[
3
]);
$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
=
''
;
foreach
(
$this
->
messages
as
$message
)
{
$body
.=
$this
->
formatMessage
(
$message
);
}
/**
* Sends an email.
* @param string $email single email address
* @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
));
$body
=
wordwrap
(
$body
,
70
);
$subject
=
$this
->
subject
===
null
?
Yii
::
t
(
'yii'
,
'Application Log'
)
:
$this
->
subject
;
foreach
(
$this
->
emails
as
$email
)
{
$this
->
sendEmail
(
$subject
,
$body
,
$email
,
$this
->
sentFrom
,
$this
->
headers
);
}
/**
* @return array list of destination email addresses
*/
public
function
getEmails
()
{
return
$this
->
_email
;
$this
->
messages
=
array
();
}
/**
* @param mixed $value list of destination email addresses. If the value is
* a string, it is assumed to be comma-separated email addresses.
*/
public
function
setEmails
(
$value
)
{
if
(
is_array
(
$value
))
$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
* Sends an email.
* @param string $subject email subject
* @param string $body email body
* @param string $sentTo sent-to email address
* @param string $sentFrom sent-from email address
* @param array $headers additional headers to be used when sending the email
*/
p
ublic
function
getHeaders
(
)
p
rotected
function
sendEmail
(
$subject
,
$body
,
$sentTo
,
$sentFrom
,
$headers
)
{
return
$this
->
_headers
;
if
(
$sentFrom
!==
null
)
{
$headers
[]
=
"From:
{
$sentFrom
}
"
;
}
/**
* @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
);
mail
(
$email
,
$subject
,
$body
,
implode
(
"
\r\n
"
,
$headers
));
}
}
\ 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
public
$flushInterval
=
1000
;
/**
* @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
* messages
are still kept in the memory by each log target. If this is true, they will
*
be exported to the actual storage medium (e.g. DB, email) defined by
each log target.
* called due to the [[flushInterval]] is reached. Defaults to
tru
e, meaning the flushed
* messages
will be exported to the actual storage medium (e.g. DB, email) defined by each
*
log target. If false, the flushed messages will be kept in the memory of
each log target.
* @see flushInterval
*/
public
$autoExport
=
fals
e
;
public
$autoExport
=
tru
e
;
/**
* @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
();
/**
* @var array the profiling results (category, token => time in seconds)
*/
private
$_timings
;
/**
* Logs an error message.
...
...
@@ -155,72 +161,24 @@ class Logger extends \yii\base\Component
}
/**
* Retrieves log messages.
*
* Messages may be filtered by log levels and/or categories.
* A level filter is specified by a list of levels separated by comma or space
* (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.
* 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.
*/
private
function
filterByCategory
(
$value
)
{
foreach
(
$this
->
_categories
as
$category
)
public
function
flush
(
$export
=
false
)
{
$cat
=
strtolower
(
$value
[
2
]);
if
(
$cat
===
$category
||
((
$c
=
rtrim
(
$category
,
'.*'
))
!==
$category
&&
strpos
(
$cat
,
$c
)
===
0
))
return
$value
;
}
return
false
;
$this
->
onFlush
(
new
\yii\base\Event
(
$this
,
array
(
'export'
=>
$export
,
'flush'
=>
true
)));
$this
->
messages
=
array
();
}
/**
* Filter function used by {@link getLogs}
* @param array $value element to be filtered
* @return array valid log, false if not.
* Raises an `onFlush` event.
* @param \yii\base\Event $event the event parameter
*/
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
/**
* 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
* being `array($token, $category, $time)`.
* If a filter is specified, the results would be an array of timings.
* @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 boolean $refresh whether to refresh the internal timing calculations. If false,
* only the first time calling this method will the timings be calculated internally.
* @return array the profiling results.
*
* By default, all profiling results will be returned. You may provide
* `$categories` and `$excludeCategories` as parameters to retrieve the
* results that you are interested in.
*
* @param array $categories list of categories that you are interested in.
* You can use an asterisk at the end of a category to do a prefix match.
* For example, 'yii\db\*' will match categories starting with 'yii\db\',
* 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
)
{
$this
->
calculateTimings
();
$timings
=
$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
)
)
{
$results
[]
=
$timing
[
2
]
;
}
if
(
!
$matched
)
{
unset
(
$timings
[
$i
])
;
}
}
return
$results
;
return
array_values
(
$timings
)
;
}
private
function
calculateTimings
()
{
$t
his
->
_t
imings
=
array
();
$timings
=
array
();
$stack
=
array
();
foreach
(
$this
->
messages
as
$log
)
{
...
...
@@ -274,18 +254,16 @@ class Logger extends \yii\base\Component
continue
;
}
list
(
$message
,
$level
,
$category
,
$timestamp
)
=
$log
;
if
(
!
strncasecmp
(
$message
,
'begin:'
,
6
))
{
$log
[
0
]
=
substr
(
$message
,
6
);
if
(
$message
===
'begin'
)
{
$stack
[]
=
$log
;
}
elseif
(
!
strncasecmp
(
$message
,
'end:'
,
4
))
{
$token
=
substr
(
$message
,
4
);
if
((
$last
=
array_pop
(
$stack
))
!==
null
&&
$last
[
0
]
===
$token
)
{
$delta
=
$log
[
3
]
-
$last
[
3
];
$this
->
_timings
[]
=
array
(
$message
,
$category
,
$delta
);
else
{
// $message === 'end'
if
((
$last
=
array_pop
(
$stack
))
!==
null
&&
$last
[
2
]
===
$category
)
{
$delta
=
$timestamp
-
$last
[
3
];
$timings
[]
=
array
(
$category
,
$delta
);
}
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
$now
=
microtime
(
true
);
while
((
$last
=
array_pop
(
$stack
))
!==
null
)
{
$delta
=
$now
-
$last
[
3
];
$this
->
_timings
[]
=
array
(
$last
[
0
],
$last
[
2
],
$delta
);
}
$timings
[]
=
array
(
$last
[
2
],
$delta
);
}
/**
* 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
();
return
$timings
;
}
/**
* 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
*/
public
function
processMessages
(
$event
)
{
$
logger
=
Yii
::
getLogger
()
;
$
messages
=
\Yii
::
getLogger
()
->
messages
;
$export
=
!
isset
(
$event
->
params
[
'export'
])
||
$event
->
params
[
'export'
];
$final
=
!
isset
(
$event
-
params
[
'flush'
])
||
!
$event
->
params
[
'flush'
];
foreach
(
$this
->
_targets
as
$target
)
{
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;
/**
* Target is the base class for all log target classes.
*
* A log target object retrieves log messages from a logger and sends it
* somewhere, such as files, emails.
* The messages being retrieved may be filtered first before being sent
* 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').
* A log target object will filter the messages logged by [[Logger]] according
* to its [[levels]] and [[categories]] properties. It may also export the filtered
* messages to specific destination defined by the target, such as emails, files.
*
* 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>
* @since 2.0
...
...
@@ -36,42 +33,57 @@ abstract class Target extends \yii\base\Component implements \yii\base\Initable
*/
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.
* The value of this property will be passed to {@link Yii::createComponent} to create
* 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.
* @var boolean whether to log a message containing the current user name and ID. Defaults to true.
* @see \yii\web\User
*/
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.
* This method is required by the [[Initable]] interface. It is invoked by
* [[\Yii::createComponent]] after its creates the new component instance but
* BEFORE the component properties are initialized.
*
* You may override this method to do work such as setting property default values.
* Exports log messages to a specific destination.
* Child classes must implement this method. Note that you may need
* to clean up [[messages]] in this method to avoid re-exporting messages.
* @param boolean $final whether this method is called at the end of the current application
*/
public
function
preinit
()
{
}
abstract
public
function
exportMessages
(
$final
);
/**
* Initializes this component.
...
...
@@ -83,89 +95,126 @@ abstract class Target extends \yii\base\Component implements \yii\base\Initable
}
/**
* Formats a log message given different fields.
* @param string $message message content
* @param integer $level message level
* @param string $category message category
* @param integer $time timestamp
* @return string formatted message
* Processes the given log messages.
* This method will filter the given messages with [[levels]] and [[categories]].
* And if requested, it will also export the filtering result to specific medium (e.g. email).
* @param array $messages log messages to be processed. See [[Logger::messages]] for the structure
* of each 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.
* @param CLogger $logger logger instance
* @param boolean $processLogs whether to process the messages after they are collected from the logger
* Prepares the [[messages]] for exporting.
* This method will modify each message by prependding extra information
* 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
)
{
$messages
=
$logger
->
getLogs
(
$this
->
levels
,
$this
->
categories
);
$this
->
messages
=
empty
(
$this
->
messages
)
?
$messages
:
array_merge
(
$this
->
messages
,
$messages
);
if
(
$processLogs
&&
!
empty
(
$this
->
messages
))
protected
function
prepareExport
(
$final
)
{
if
(
$this
->
filter
!==
null
)
Yii
::
createComponent
(
$this
->
filter
)
->
filter
(
$this
->
messages
);
$this
->
processLogs
(
$this
->
messages
);
$this
->
messages
=
array
();
$prefix
=
array
();
if
(
$this
->
prefixSession
&&
(
$id
=
session_id
())
!==
''
)
{
$prefix
[]
=
"[
$id
]"
;
}
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
=
''
)
{
$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'
))));
}
if
(
$final
&&
(
$context
=
$this
->
getContextMessage
())
!==
''
)
{
$this
->
messages
[]
=
array
(
$context
,
Logger
::
LEVEL_INFO
,
'application'
,
YII_BEGIN_TIME
);
}
}
/**
*
Filter function used by {@link getLogs}
*
@param array $value element to be filtered
* @return
array valid log, false if not
.
*
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
filterByCategory
(
$value
)
{
foreach
(
$this
->
_categories
as
$category
)
protected
function
getContextMessage
()
{
$cat
=
strtolower
(
$value
[
2
]);
if
(
$cat
===
$category
||
((
$c
=
rtrim
(
$category
,
'.*'
))
!==
$category
&&
strpos
(
$cat
,
$c
)
===
0
))
return
$value
;
$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
false
;
}
return
implode
(
"
\n\n
"
,
$context
);
}
/**
* Filter function used by {@link getLogs}
* @param array $value element to be filtered
* @return array valid log, false if not.
* Filters the given messages according to their categories and levels.
* @param array $messages messages to be filtered
* @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.
* Derived child classes must implement this method.
* @param array $messages 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));
*/
abstract
protected
function
processLogs
(
$messages
);
* Formats a log message.
* The message structure follows that in [[Logger::messages]].
* @param array $message the log message to be formatted.
* @return string the formatted message
*/
public
function
formatMessage
(
$message
)
{
return
@
date
(
'Y/m/d H:i:s'
,
$message
[
3
])
.
" [
{
$message
[
1
]
}
] [
{
$message
[
2
]
}
]
{
$message
[
0
]
}
\n
"
;
}
}
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