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
fb75c958
Commit
fb75c958
authored
Jan 19, 2013
by
Qiang Xue
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
refactored logging.
parent
373e6a70
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
218 additions
and
174 deletions
+218
-174
YiiBase.php
framework/YiiBase.php
+10
-8
Application.php
framework/base/Application.php
+4
-2
DbTarget.php
framework/logging/DbTarget.php
+30
-18
FileTarget.php
framework/logging/FileTarget.php
+23
-24
Logger.php
framework/logging/Logger.php
+43
-88
Router.php
framework/logging/Router.php
+15
-11
Target.php
framework/logging/Target.php
+81
-12
todo.md
todo.md
+12
-11
No files found.
framework/YiiBase.php
View file @
fb75c958
...
@@ -8,7 +8,9 @@
...
@@ -8,7 +8,9 @@
*/
*/
use
yii\base\Exception
;
use
yii\base\Exception
;
use
yii\logging\Logger
;
use
yii\base\InvalidCallException
;
use
yii\base\InvalidCallException
;
use
yii\base\InvalidConfigException
;
/**
/**
* Gets the application start timestamp.
* Gets the application start timestamp.
...
@@ -394,7 +396,7 @@ class YiiBase
...
@@ -394,7 +396,7 @@ class YiiBase
public
static
function
trace
(
$message
,
$category
=
'application'
)
public
static
function
trace
(
$message
,
$category
=
'application'
)
{
{
if
(
YII_DEBUG
)
{
if
(
YII_DEBUG
)
{
self
::
getLogger
()
->
trace
(
$message
,
$category
);
self
::
getLogger
()
->
log
(
$message
,
Logger
::
LEVEL_TRACE
,
$category
);
}
}
}
}
...
@@ -407,7 +409,7 @@ class YiiBase
...
@@ -407,7 +409,7 @@ class YiiBase
*/
*/
public
static
function
error
(
$message
,
$category
=
'application'
)
public
static
function
error
(
$message
,
$category
=
'application'
)
{
{
self
::
getLogger
()
->
error
(
$message
,
$category
);
self
::
getLogger
()
->
log
(
$message
,
Logger
::
LEVEL_ERROR
,
$category
);
}
}
/**
/**
...
@@ -419,7 +421,7 @@ class YiiBase
...
@@ -419,7 +421,7 @@ class YiiBase
*/
*/
public
static
function
warning
(
$message
,
$category
=
'application'
)
public
static
function
warning
(
$message
,
$category
=
'application'
)
{
{
self
::
getLogger
()
->
warning
(
$message
,
$category
);
self
::
getLogger
()
->
log
(
$message
,
Logger
::
LEVEL_WARNING
,
$category
);
}
}
/**
/**
...
@@ -431,7 +433,7 @@ class YiiBase
...
@@ -431,7 +433,7 @@ class YiiBase
*/
*/
public
static
function
info
(
$message
,
$category
=
'application'
)
public
static
function
info
(
$message
,
$category
=
'application'
)
{
{
self
::
getLogger
()
->
info
(
$message
,
$category
);
self
::
getLogger
()
->
log
(
$message
,
Logger
::
LEVEL_INFO
,
$category
);
}
}
/**
/**
...
@@ -453,7 +455,7 @@ class YiiBase
...
@@ -453,7 +455,7 @@ class YiiBase
*/
*/
public
static
function
beginProfile
(
$token
,
$category
=
'application'
)
public
static
function
beginProfile
(
$token
,
$category
=
'application'
)
{
{
self
::
getLogger
()
->
beginProfile
(
$token
,
$category
);
self
::
getLogger
()
->
log
(
$token
,
Logger
::
LEVEL_PROFILE_BEGIN
,
$category
);
}
}
/**
/**
...
@@ -465,7 +467,7 @@ class YiiBase
...
@@ -465,7 +467,7 @@ class YiiBase
*/
*/
public
static
function
endProfile
(
$token
,
$category
=
'application'
)
public
static
function
endProfile
(
$token
,
$category
=
'application'
)
{
{
self
::
getLogger
()
->
endProfile
(
$token
,
$category
);
self
::
getLogger
()
->
log
(
$token
,
Logger
::
LEVEL_PROFILE_END
,
$category
);
}
}
/**
/**
...
@@ -477,13 +479,13 @@ class YiiBase
...
@@ -477,13 +479,13 @@ class YiiBase
if
(
self
::
$_logger
!==
null
)
{
if
(
self
::
$_logger
!==
null
)
{
return
self
::
$_logger
;
return
self
::
$_logger
;
}
else
{
}
else
{
return
self
::
$_logger
=
new
\yii\logging\
Logger
;
return
self
::
$_logger
=
new
Logger
;
}
}
}
}
/**
/**
* Sets the logger object.
* Sets the logger object.
* @param
\yii\logging\
Logger $logger the logger object.
* @param Logger $logger the logger object.
*/
*/
public
static
function
setLogger
(
$logger
)
public
static
function
setLogger
(
$logger
)
{
{
...
...
framework/base/Application.php
View file @
fb75c958
...
@@ -75,6 +75,8 @@ use yii\base\InvalidCallException;
...
@@ -75,6 +75,8 @@ use yii\base\InvalidCallException;
*/
*/
class
Application
extends
Module
class
Application
extends
Module
{
{
const
EVENT_BEFORE_REQUEST
=
'beforeRequest'
;
const
EVENT_AFTER_REQUEST
=
'afterRequest'
;
/**
/**
* @var string the application name. Defaults to 'My Application'.
* @var string the application name. Defaults to 'My Application'.
*/
*/
...
@@ -178,7 +180,7 @@ class Application extends Module
...
@@ -178,7 +180,7 @@ class Application extends Module
*/
*/
public
function
beforeRequest
()
public
function
beforeRequest
()
{
{
$this
->
trigger
(
'beforeRequest'
);
$this
->
trigger
(
self
::
EVENT_BEFORE_REQUEST
);
}
}
/**
/**
...
@@ -186,7 +188,7 @@ class Application extends Module
...
@@ -186,7 +188,7 @@ class Application extends Module
*/
*/
public
function
afterRequest
()
public
function
afterRequest
()
{
{
$this
->
trigger
(
'afterRequest'
);
$this
->
trigger
(
self
::
EVENT_AFTER_REQUEST
);
}
}
/**
/**
...
...
framework/logging/DbTarget.php
View file @
fb75c958
...
@@ -9,6 +9,9 @@
...
@@ -9,6 +9,9 @@
namespace
yii\logging
;
namespace
yii\logging
;
use
yii\db\Connection
;
use
yii\base\InvalidConfigException
;
/**
/**
* DbTarget stores log messages in a database table.
* DbTarget stores log messages in a database table.
*
*
...
@@ -23,23 +26,21 @@ namespace yii\logging;
...
@@ -23,23 +26,21 @@ namespace yii\logging;
class
DbTarget
extends
Target
class
DbTarget
extends
Target
{
{
/**
/**
* @var string the ID of [[
\yii\db\
Connection]] application component.
* @var string the ID of [[Connection]] application component.
* Defaults to 'db'. Please make sure that your database contains a table
* Defaults to 'db'. Please make sure that your database contains a table
* whose name is as specified in [[tableName]] and has the required table structure.
* whose name is as specified in [[tableName]] and has the required table structure.
* @see tableName
* @see tableName
*/
*/
public
$connectionID
=
'db'
;
public
$connectionID
=
'db'
;
/**
/**
* @var string the name of the DB table that stores log messages. Defaults to '{{log}}'.
* @var string the name of the DB table that stores log messages. Defaults to 'tbl_log'.
* If you are using table prefix 'tbl_' (configured via [[\yii\db\Connection::tablePrefix]]),
* it means the DB table would be named as 'tbl_log'.
*
*
* The DB table
must
have the following structure:
* The DB table
should
have the following structure:
*
*
* ~~~
* ~~~
* CREATE TABLE tbl_log (
* CREATE TABLE tbl_log (
* id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY,
* id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY,
* level
VARCHAR(32)
,
* level
INTEGER
,
* category VARCHAR(255),
* category VARCHAR(255),
* log_time INTEGER,
* log_time INTEGER,
* message TEXT,
* message TEXT,
...
@@ -50,42 +51,53 @@ class DbTarget extends Target
...
@@ -50,42 +51,53 @@ class DbTarget extends Target
*
*
* Note that the 'id' column must be created as an auto-incremental column.
* Note that the 'id' column must be created as an auto-incremental column.
* The above SQL shows the syntax of MySQL. If you are using other DBMS, you need
* The above SQL shows the syntax of MySQL. If you are using other DBMS, you need
* to adjust it accordingly. For example, in PosgreSQL, it should be `id SERIAL PRIMARY KEY`.
* to adjust it accordingly. For example, in Pos
t
greSQL, it should be `id SERIAL PRIMARY KEY`.
*
*
* The indexes declared above are not required. They are mainly used to improve the performance
* The indexes declared above are not required. They are mainly used to improve the performance
* of some queries about message levels and categories. Depending on your actual needs, you may
* of some queries about message levels and categories. Depending on your actual needs, you may
* want to create
other indexes
.
* want to create
additional indexes (e.g. index on log_time)
.
*/
*/
public
$tableName
=
'
{{log}}
'
;
public
$tableName
=
'
tbl_log
'
;
private
$_db
;
private
$_db
;
/**
/**
* Returns the DB connection used for saving log messages.
* Returns the DB connection used for saving log messages.
* @return
\yii\db\
Connection the DB connection instance
* @return Connection the DB connection instance
* @throws
\yii\base\Exception if [[connectionID]] does not refer to a valid application component ID
.
* @throws
InvalidConfigException if [[connectionID]] does not point to a valid application component
.
*/
*/
public
function
getDb
()
public
function
getDb
()
{
{
if
(
$this
->
_db
===
null
)
{
if
(
$this
->
_db
===
null
)
{
$this
->
_db
=
\Yii
::
$application
->
getComponent
(
$this
->
connectionID
);
$db
=
\Yii
::
$application
->
getComponent
(
$this
->
connectionID
);
if
(
!
$this
->
_db
instanceof
\yii\db\Connection
)
{
if
(
$db
instanceof
Connection
)
{
throw
new
\yii\base\Exception
(
'DbTarget.connectionID must refer to a valid application component ID'
);
$this
->
_db
=
$db
;
}
else
{
throw
new
InvalidConfigException
(
"DbTarget::connectionID must refer to the ID of a DB application component."
);
}
}
}
}
return
$this
->
_db
;
return
$this
->
_db
;
}
}
/**
/**
* Sets the DB connection used by the cache component.
* @param Connection $value the DB connection instance
*/
public
function
setDb
(
$value
)
{
$this
->
_db
=
$value
;
}
/**
* Stores log [[messages]] to DB.
* Stores log [[messages]] to DB.
* @param boolean $final whether this method is called at the end of the current application
* @param boolean $final whether this method is called at the end of the current application
*/
*/
public
function
exportMessages
(
$final
)
public
function
exportMessages
(
$final
)
{
{
$
sql
=
"INSERT INTO
{
$this
->
tableName
}
$
db
=
$this
->
getDb
();
(level, category, log_time, message) VALUES
$tableName
=
$db
->
quoteTableName
(
$this
->
tableName
);
(:level, :category, :log_time, :message)"
;
$sql
=
"INSERT INTO
$tableName
(level, category, log_time, message) VALUES
(:level, :category, :log_time, :message)"
;
$command
=
$
this
->
getDb
()
->
createCommand
(
$sql
);
$command
=
$
db
->
createCommand
(
$sql
);
foreach
(
$this
->
messages
as
$message
)
{
foreach
(
$this
->
messages
as
$message
)
{
$command
->
bindValues
(
array
(
$command
->
bindValues
(
array
(
':level'
=>
$message
[
1
],
':level'
=>
$message
[
1
],
...
...
framework/logging/FileTarget.php
View file @
fb75c958
...
@@ -8,17 +8,16 @@
...
@@ -8,17 +8,16 @@
*/
*/
namespace
yii\logging
;
namespace
yii\logging
;
use
yii\base\InvalidConfigException
;
/**
/**
* FileTarget records log messages in
files
.
* FileTarget records log messages in
a file
.
*
*
* The log files are stored under [[logPath]] and their name
* The log file is specified via [[logFile]]. If the size of the log file exceeds
* is specified by [[logFile]]. If the size of the log file exceeds
* [[maxFileSize]] (in kilo-bytes), a rotation will be performed, which renames
* [[maxFileSize]] (in kilo-bytes), a rotation will be performed,
* the current log file by suffixing the file name with '.1'. All existing log
* which renames the current log file by suffixing the file name
* files are moved backwards by one place, i.e., '.2' to '.3', '.1' to '.2', and so on.
* with '.1'. All existing log files are moved backwards one place,
* The property [[maxLogFiles]] specifies how many files to keep.
* i.e., '.2' to '.3', '.1' to '.2', and so on. The property
* [[maxLogFiles]] specifies how many files to keep.
*
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
* @since 2.0
...
@@ -26,6 +25,12 @@ namespace yii\logging;
...
@@ -26,6 +25,12 @@ namespace yii\logging;
class
FileTarget
extends
Target
class
FileTarget
extends
Target
{
{
/**
/**
* @var string log file path or path alias. If not set, it means the 'application.log' file under
* the application runtime directory. Please make sure the directory containing
* the log file is writable by the Web server process.
*/
public
$logFile
;
/**
* @var integer maximum log file size, in kilo-bytes. Defaults to 1024, meaning 1MB.
* @var integer maximum log file size, in kilo-bytes. Defaults to 1024, meaning 1MB.
*/
*/
public
$maxFileSize
=
1024
;
// in KB
public
$maxFileSize
=
1024
;
// in KB
...
@@ -33,14 +38,6 @@ class FileTarget extends Target
...
@@ -33,14 +38,6 @@ class FileTarget extends Target
* @var integer number of log files used for rotation. Defaults to 5.
* @var integer number of log files used for rotation. Defaults to 5.
*/
*/
public
$maxLogFiles
=
5
;
public
$maxLogFiles
=
5
;
/**
* @var string directory storing log files. Defaults to the application runtime path.
*/
public
$logPath
;
/**
* @var string log file name. Defaults to 'application.log'.
*/
public
$logFile
=
'application.log'
;
/**
/**
...
@@ -50,11 +47,14 @@ class FileTarget extends Target
...
@@ -50,11 +47,14 @@ class FileTarget extends Target
public
function
init
()
public
function
init
()
{
{
parent
::
init
();
parent
::
init
();
if
(
$this
->
logPath
===
null
)
{
if
(
$this
->
logFile
===
null
)
{
$this
->
logPath
=
\Yii
::
$application
->
getRuntimePath
();
$this
->
logFile
=
\Yii
::
$application
->
getRuntimePath
()
.
DIRECTORY_SEPARATOR
.
'application.log'
;
}
else
{
$this
->
logFile
=
\Yii
::
getAlias
(
$this
->
logFile
);
}
}
if
(
!
is_dir
(
$this
->
logPath
)
||
!
is_writable
(
$this
->
logPath
))
{
$logPath
=
dirname
(
$this
->
logFile
);
throw
new
\yii\base\Exception
(
"Directory '
{
$this
->
logPath
}
' does not exist or is not writable."
);
if
(
!
is_dir
(
$logPath
)
||
!
is_writable
(
$logPath
))
{
throw
new
InvalidConfigException
(
"Directory '
$logPath
' does not exist or is not writable."
);
}
}
if
(
$this
->
maxLogFiles
<
1
)
{
if
(
$this
->
maxLogFiles
<
1
)
{
$this
->
maxLogFiles
=
1
;
$this
->
maxLogFiles
=
1
;
...
@@ -70,15 +70,14 @@ class FileTarget extends Target
...
@@ -70,15 +70,14 @@ class FileTarget extends Target
*/
*/
public
function
exportMessages
(
$final
)
public
function
exportMessages
(
$final
)
{
{
$logFile
=
$this
->
logPath
.
DIRECTORY_SEPARATOR
.
$this
->
logFile
;
if
(
@
filesize
(
$this
->
logFile
)
>
$this
->
maxFileSize
*
1024
)
{
if
(
@
filesize
(
$logFile
)
>
$this
->
maxFileSize
*
1024
)
{
$this
->
rotateFiles
();
$this
->
rotateFiles
();
}
}
$messages
=
array
();
$messages
=
array
();
foreach
(
$this
->
messages
as
$message
)
{
foreach
(
$this
->
messages
as
$message
)
{
$messages
[]
=
$this
->
formatMessage
(
$message
);
$messages
[]
=
$this
->
formatMessage
(
$message
);
}
}
@
file_put_contents
(
$logFile
,
implode
(
''
,
$messages
),
FILE_APPEND
|
LOCK_EX
);
@
file_put_contents
(
$
this
->
logFile
,
implode
(
''
,
$messages
),
FILE_APPEND
|
LOCK_EX
);
}
}
/**
/**
...
@@ -86,7 +85,7 @@ class FileTarget extends Target
...
@@ -86,7 +85,7 @@ class FileTarget extends Target
*/
*/
protected
function
rotateFiles
()
protected
function
rotateFiles
()
{
{
$file
=
$this
->
log
Path
.
DIRECTORY_SEPARATOR
.
$this
->
log
File
;
$file
=
$this
->
logFile
;
for
(
$i
=
$this
->
maxLogFiles
;
$i
>
0
;
--
$i
)
{
for
(
$i
=
$this
->
maxLogFiles
;
$i
>
0
;
--
$i
)
{
$rotateFile
=
$file
.
'.'
.
$i
;
$rotateFile
=
$file
.
'.'
.
$i
;
if
(
is_file
(
$rotateFile
))
{
if
(
is_file
(
$rotateFile
))
{
...
...
framework/logging/Logger.php
View file @
fb75c958
...
@@ -10,6 +10,7 @@
...
@@ -10,6 +10,7 @@
namespace
yii\logging
;
namespace
yii\logging
;
use
yii\base\Event
;
use
yii\base\Event
;
use
yii\base\Exception
;
/**
/**
* Logger records logged messages in memory.
* Logger records logged messages in memory.
...
@@ -18,8 +19,6 @@ use yii\base\Event;
...
@@ -18,8 +19,6 @@ use yii\base\Event;
* call [[flush()]] to send logged messages to different log targets, such as
* call [[flush()]] to send logged messages to different log targets, such as
* file, email, Web.
* file, email, Web.
*
*
* Logger provides a set of events for further customization:
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
* @since 2.0
*/
*/
...
@@ -30,12 +29,40 @@ class Logger extends \yii\base\Component
...
@@ -30,12 +29,40 @@ class Logger extends \yii\base\Component
*/
*/
const
EVENT_FLUSH
=
'flush'
;
const
EVENT_FLUSH
=
'flush'
;
const
LEVEL_ERROR
=
'error'
;
/**
const
LEVEL_WARNING
=
'warning'
;
* Error message level. An error message is one that indicates the abnormal termination of the
const
LEVEL_INFO
=
'info'
;
* application and may require developer's handling.
const
LEVEL_TRACE
=
'trace'
;
*/
const
LEVEL_PROFILE_BEGIN
=
'profile-begin'
;
const
LEVEL_ERROR
=
0x01
;
const
LEVEL_PROFILE_END
=
'profile-end'
;
/**
* Warning message level. A warning message is one that indicates some abnormal happens but
* the application is able to continue to run. Developers should pay attention to this message.
*/
const
LEVEL_WARNING
=
0x02
;
/**
* Informational message level. An informational message is one that includes certain information
* for developers to review.
*/
const
LEVEL_INFO
=
0x04
;
/**
* Tracing message level. An tracing message is one that reveals the code execution flow.
*/
const
LEVEL_TRACE
=
0x08
;
/**
* Profiling message level. This indicates the message is for profiling purpose.
*/
const
LEVEL_PROFILE
=
0x40
;
/**
* Profiling message level. This indicates the message is for profiling purpose. It marks the
* beginning of a profiling block.
*/
const
LEVEL_PROFILE_BEGIN
=
0x50
;
/**
* Profiling message level. This indicates the message is for profiling purpose. It marks the
* end of a profiling block.
*/
const
LEVEL_PROFILE_END
=
0x60
;
/**
/**
* @var integer how many messages should be logged before they are flushed from memory and sent to targets.
* @var integer how many messages should be logged before they are flushed from memory and sent to targets.
...
@@ -52,7 +79,7 @@ class Logger extends \yii\base\Component
...
@@ -52,7 +79,7 @@ class Logger extends \yii\base\Component
* ~~~
* ~~~
* array(
* array(
* [0] => message (mixed)
* [0] => message (mixed)
* [1] => level (
string
)
* [1] => level (
integer
)
* [2] => category (string)
* [2] => category (string)
* [3] => timestamp (float, obtained by microtime(true))
* [3] => timestamp (float, obtained by microtime(true))
* )
* )
...
@@ -61,85 +88,13 @@ class Logger extends \yii\base\Component
...
@@ -61,85 +88,13 @@ class Logger extends \yii\base\Component
public
$messages
=
array
();
public
$messages
=
array
();
/**
/**
* Logs an error message.
* An error message is typically logged when an unrecoverable error occurs
* during the execution of an application.
* @param mixed $message the message to be logged.
* @param string $category the category of the message.
*/
public
function
error
(
$message
,
$category
=
'application'
)
{
$this
->
log
(
$message
,
self
::
LEVEL_ERROR
,
$category
);
}
/**
* Logs a trace message.
* Trace messages are logged mainly for development purpose to see
* the execution work flow of some code.
* @param mixed $message the message to be logged.
* @param string $category the category of the message.
*/
public
function
trace
(
$message
,
$category
=
'application'
)
{
$this
->
log
(
$message
,
self
::
LEVEL_TRACE
,
$category
);
}
/**
* Logs a warning message.
* A warning message is typically logged when an error occurs while the execution
* can still continue.
* @param mixed $message the message to be logged.
* @param string $category the category of the message.
*/
public
function
warning
(
$message
,
$category
=
'application'
)
{
$this
->
log
(
$message
,
self
::
LEVEL_WARNING
,
$category
);
}
/**
* Logs an informative message.
* An informative message is typically logged by an application to keep record of
* something important (e.g. an administrator logs in).
* @param mixed $message the message to be logged.
* @param string $category the category of the message.
*/
public
function
info
(
$message
,
$category
=
'application'
)
{
$this
->
log
(
$message
,
self
::
LEVEL_INFO
,
$category
);
}
/**
* Marks the beginning of a code block for profiling.
* This has to be matched with a call to [[endProfile()]] with the same category name.
* The begin- and end- calls must also be properly nested.
* @param string $token token for the code block
* @param string $category the category of this log message
* @see endProfile
*/
public
function
beginProfile
(
$token
,
$category
=
'application'
)
{
$this
->
log
(
$token
,
self
::
LEVEL_PROFILE_BEGIN
,
$category
);
}
/**
* Marks the end of a code block for profiling.
* This has to be matched with a previous call to [[beginProfile()]] with the same category name.
* @param string $token token for the code block
* @param string $category the category of this log message
* @see beginProfile
*/
public
function
endProfile
(
$token
,
$category
=
'application'
)
{
$this
->
log
(
$token
,
self
::
LEVEL_PROFILE_END
,
$category
);
}
/**
* Logs a message with the given type and category.
* Logs a message with the given type and category.
* If `YII_DEBUG` is true and `YII_TRACE_LEVEL` is greater than 0, then additional
* If `YII_DEBUG` is true and `YII_TRACE_LEVEL` is greater than 0, then additional
* call stack information about application code will be appended to the message.
* call stack information about application code will be appended to the message.
* @param string $message the message to be logged.
* @param string $message the message to be logged.
* @param string $level the level of the message. This must be one of the following:
* @param integer $level the level of the message. This must be one of the following:
* 'trace', 'info', 'warning', 'error', 'profile'.
* `Logger::LEVEL_ERROR`, `Logger::LEVEL_WARNING`, `Logger::LEVEL_INFO`, `Logger::LEVEL_TRACE`,
* `Logger::LEVEL_PROFILE_BEGIN`, `Logger::LEVEL_PROFILE_END`.
* @param string $category the category of the message.
* @param string $category the category of the message.
*/
*/
public
function
log
(
$message
,
$level
,
$category
=
'application'
)
public
function
log
(
$message
,
$level
,
$category
=
'application'
)
...
@@ -242,14 +197,14 @@ class Logger extends \yii\base\Component
...
@@ -242,14 +197,14 @@ class Logger extends \yii\base\Component
$stack
=
array
();
$stack
=
array
();
foreach
(
$this
->
messages
as
$log
)
{
foreach
(
$this
->
messages
as
$log
)
{
if
(
$log
[
1
]
===
self
::
LEVEL_PROFILE_BEGIN
)
{
list
(
$token
,
$level
,
$category
,
$timestamp
)
=
$log
;
if
(
$level
==
self
::
LEVEL_PROFILE_BEGIN
)
{
$stack
[]
=
$log
;
$stack
[]
=
$log
;
}
elseif
(
$log
[
1
]
===
self
::
LEVEL_PROFILE_END
)
{
}
elseif
(
$level
==
self
::
LEVEL_PROFILE_END
)
{
list
(
$token
,
$level
,
$category
,
$timestamp
)
=
$log
;
if
((
$last
=
array_pop
(
$stack
))
!==
null
&&
$last
[
0
]
===
$token
)
{
if
((
$last
=
array_pop
(
$stack
))
!==
null
&&
$last
[
0
]
===
$token
)
{
$timings
[]
=
array
(
$token
,
$category
,
$timestamp
-
$last
[
3
]);
$timings
[]
=
array
(
$token
,
$category
,
$timestamp
-
$last
[
3
]);
}
else
{
}
else
{
throw
new
\yii\base\
Exception
(
"Unmatched profiling block:
$token
"
);
throw
new
Exception
(
"Unmatched profiling block:
$token
"
);
}
}
}
}
}
}
...
...
framework/logging/Router.php
View file @
fb75c958
...
@@ -9,6 +9,10 @@
...
@@ -9,6 +9,10 @@
namespace
yii\logging
;
namespace
yii\logging
;
use
Yii
;
use
yii\base\Component
;
use
yii\base\Application
;
/**
/**
* Router manages [[Target|log targets]] that record log messages in different media.
* Router manages [[Target|log targets]] that record log messages in different media.
*
*
...
@@ -48,17 +52,17 @@ namespace yii\logging;
...
@@ -48,17 +52,17 @@ namespace yii\logging;
* as follows:
* as follows:
*
*
* ~~~
* ~~~
*
\
Yii::$application->log->targets['file']->enabled = false;
* Yii::$application->log->targets['file']->enabled = false;
* ~~~
* ~~~
*
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
* @since 2.0
*/
*/
class
Router
extends
\yii\base\Application
Component
class
Router
extends
Component
{
{
/**
/**
* @var Target[] list of log target objects or configurations. If the latter, target objects will
* @var Target[] list of log target objects or configurations. If the latter, target objects will
* be created in [[init()]] by calling [[
\
Yii::createObject()]] with the corresponding object configuration.
* be created in [[init()]] by calling [[Yii::createObject()]] with the corresponding object configuration.
*/
*/
public
$targets
=
array
();
public
$targets
=
array
();
...
@@ -74,28 +78,28 @@ class Router extends \yii\base\ApplicationComponent
...
@@ -74,28 +78,28 @@ class Router extends \yii\base\ApplicationComponent
foreach
(
$this
->
targets
as
$name
=>
$target
)
{
foreach
(
$this
->
targets
as
$name
=>
$target
)
{
if
(
!
$target
instanceof
Target
)
{
if
(
!
$target
instanceof
Target
)
{
$this
->
targets
[
$name
]
=
\
Yii
::
createObject
(
$target
);
$this
->
targets
[
$name
]
=
Yii
::
createObject
(
$target
);
}
}
}
}
\Yii
::
getLogger
()
->
on
(
'flush'
,
array
(
$this
,
'processMessages'
));
Yii
::
getLogger
()
->
on
(
Logger
::
EVENT_FLUSH
,
array
(
$this
,
'processMessages'
));
if
(
\
Yii
::
$application
!==
null
)
{
if
(
Yii
::
$application
!==
null
)
{
\Yii
::
$application
->
on
(
'afterRequest'
,
array
(
$this
,
'processMessages'
));
Yii
::
$application
->
on
(
Application
::
EVENT_AFTER_REQUEST
,
array
(
$this
,
'processMessages'
));
}
}
}
}
/**
/**
* Retrieves and processes log messages from the system logger.
* Retrieves and processes log messages from the system logger.
* This method mainly serves the event handler to [[Logger::onFlush]]
* This method mainly serves the event handler to [[Logger::onFlush]]
* and [[
\yii\base\
Application::onEndRequest]] events.
* and [[Application::onEndRequest]] events.
* It will retrieve the available log messages from the [[
\
Yii::getLogger|system logger]]
* It will retrieve the available log messages from the [[Yii::getLogger|system logger]]
* and invoke the registered [[targets|log targets]] to do the actual processing.
* and invoke the registered [[targets|log targets]] to do the actual processing.
* @param \yii\base\Event $event event parameter
* @param \yii\base\Event $event event parameter
*/
*/
public
function
processMessages
(
$event
)
public
function
processMessages
(
$event
)
{
{
$messages
=
\
Yii
::
getLogger
()
->
messages
;
$messages
=
Yii
::
getLogger
()
->
messages
;
$final
=
$event
->
name
!==
'flush'
;
$final
=
$event
->
name
===
Application
::
EVENT_AFTER_REQUEST
;
foreach
(
$this
->
targets
as
$target
)
{
foreach
(
$this
->
targets
as
$target
)
{
if
(
$target
->
enabled
)
{
if
(
$target
->
enabled
)
{
$target
->
processMessages
(
$messages
,
$final
);
$target
->
processMessages
(
$messages
,
$final
);
...
...
framework/logging/Target.php
View file @
fb75c958
...
@@ -9,6 +9,8 @@
...
@@ -9,6 +9,8 @@
namespace
yii\logging
;
namespace
yii\logging
;
use
yii\base\InvalidConfigException
;
/**
/**
* Target is the base class for all log target classes.
* Target is the base class for all log target classes.
*
*
...
@@ -20,6 +22,8 @@ namespace yii\logging;
...
@@ -20,6 +22,8 @@ namespace yii\logging;
* satisfying both filter conditions will be handled. Additionally, you
* satisfying both filter conditions will be handled. Additionally, you
* may specify [[except]] to exclude messages of certain categories.
* may specify [[except]] to exclude messages of certain categories.
*
*
* @property integer $levels the message levels that this target is interested in.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
* @since 2.0
*/
*/
...
@@ -30,10 +34,6 @@ abstract class Target extends \yii\base\Component
...
@@ -30,10 +34,6 @@ abstract class Target extends \yii\base\Component
*/
*/
public
$enabled
=
true
;
public
$enabled
=
true
;
/**
/**
* @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.
* @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
* 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
* match those categories sharing the same common prefix. For example, 'yii\db\*' will match
...
@@ -70,17 +70,19 @@ abstract class Target extends \yii\base\Component
...
@@ -70,17 +70,19 @@ abstract class Target extends \yii\base\Component
*/
*/
public
$logVars
=
array
(
'_GET'
,
'_POST'
,
'_FILES'
,
'_COOKIE'
,
'_SESSION'
,
'_SERVER'
);
public
$logVars
=
array
(
'_GET'
,
'_POST'
,
'_FILES'
,
'_COOKIE'
,
'_SESSION'
,
'_SERVER'
);
/**
/**
* @var
boolean whether this target should export the collected messages to persistent storage
* @var
integer how many messages should be accumulated before they are exported.
*
(e.g. DB, email) whenever [[processMessages()]] is called. Defaults to true. If false,
*
Defaults to 1000. Note that messages will always be exported when the application terminates.
*
the collected messages will be stored in [[messages]] without any further processing
.
*
Set this property to be 0 if you don't want to export messages until the application terminates
.
*/
*/
public
$
autoExport
=
true
;
public
$
exportInterval
=
1000
;
/**
/**
* @var array the messages that are retrieved from the logger so far by this log target.
* @var array the messages that are retrieved from the logger so far by this log target.
* @see autoExport
* @see autoExport
*/
*/
public
$messages
=
array
();
public
$messages
=
array
();
private
$_levels
=
0
;
/**
/**
* Exports log messages to a specific destination.
* Exports log messages to a specific destination.
* Child classes must implement this method. Note that you may need
* Child classes must implement this method. Note that you may need
...
@@ -102,7 +104,8 @@ abstract class Target extends \yii\base\Component
...
@@ -102,7 +104,8 @@ abstract class Target extends \yii\base\Component
$messages
=
$this
->
filterMessages
(
$messages
);
$messages
=
$this
->
filterMessages
(
$messages
);
$this
->
messages
=
array_merge
(
$this
->
messages
,
$messages
);
$this
->
messages
=
array_merge
(
$this
->
messages
,
$messages
);
if
(
!
empty
(
$this
->
messages
)
&&
(
$this
->
autoExport
||
$final
))
{
$count
=
count
(
$this
->
messages
);
if
(
$count
>
0
&&
(
$final
||
$this
->
exportInterval
>
0
&&
$count
>=
$this
->
exportInterval
))
{
$this
->
prepareExport
(
$final
);
$this
->
prepareExport
(
$final
);
$this
->
exportMessages
(
$final
);
$this
->
exportMessages
(
$final
);
$this
->
messages
=
array
();
$this
->
messages
=
array
();
...
@@ -160,6 +163,58 @@ abstract class Target extends \yii\base\Component
...
@@ -160,6 +163,58 @@ abstract class Target extends \yii\base\Component
}
}
/**
/**
* @return integer the message levels that this target is interested in. This is a bitmap of
* level values. Defaults to 0, meaning all available levels.
*/
public
function
getLevels
()
{
return
$this
->
_levels
;
}
/**
* Sets the message levels that this target is interested in.
*
* The parameter can be either an array of interested level names or an integer representing
* the bitmap of the interested level values. Valid level names include: 'error',
* 'warning', 'info', 'trace' and 'profile'; valid level values include:
* [[Logger::LEVEL_ERROR]], [[Logger::LEVEL_WARNING]], [[Logger::LEVEL_INFO]],
* [[Logger::LEVEL_TRACE]] and [[Logger::LEVEL_PROFILE]].
*
* For example,
*
* ~~~
* array('error', 'warning')
* // which is equivalent to:
* Logger::LEVEL_ERROR | Logger::LEVEL_WARNING
* ~~~
*
* @param array|integer $levels message levels that this target is interested in.
* @throws InvalidConfigException if an unknown level name is given
*/
public
function
setLevels
(
$levels
)
{
static
$levelMap
=
array
(
'error'
=>
Logger
::
LEVEL_ERROR
,
'warning'
=>
Logger
::
LEVEL_WARNING
,
'info'
=>
Logger
::
LEVEL_INFO
,
'trace'
=>
Logger
::
LEVEL_TRACE
,
'profile'
=>
Logger
::
LEVEL_PROFILE
,
);
if
(
is_array
(
$levels
))
{
$this
->
_levels
=
0
;
foreach
(
$levels
as
$level
)
{
if
(
isset
(
$levelMap
[
$level
]))
{
$this
->
_levels
|=
$levelMap
[
$level
];
}
else
{
throw
new
InvalidConfigException
(
"Unrecognized level:
$level
"
);
}
}
}
else
{
$this
->
_levels
=
$levels
;
}
}
/**
* Filters the given messages according to their categories and levels.
* Filters the given messages according to their categories and levels.
* @param array $messages messages to be filtered
* @param array $messages messages to be filtered
* @return array the filtered messages.
* @return array the filtered messages.
...
@@ -168,8 +223,10 @@ abstract class Target extends \yii\base\Component
...
@@ -168,8 +223,10 @@ abstract class Target extends \yii\base\Component
*/
*/
protected
function
filterMessages
(
$messages
)
protected
function
filterMessages
(
$messages
)
{
{
$levels
=
$this
->
getLevels
();
foreach
(
$messages
as
$i
=>
$message
)
{
foreach
(
$messages
as
$i
=>
$message
)
{
if
(
!
empty
(
$this
->
levels
)
&&
!
in_array
(
$message
[
1
],
$this
->
levels
))
{
if
(
$levels
&&
!
(
$levels
&
$message
[
1
]
))
{
unset
(
$messages
[
$i
]);
unset
(
$messages
[
$i
]);
continue
;
continue
;
}
}
...
@@ -210,7 +267,19 @@ abstract class Target extends \yii\base\Component
...
@@ -210,7 +267,19 @@ abstract class Target extends \yii\base\Component
*/
*/
public
function
formatMessage
(
$message
)
public
function
formatMessage
(
$message
)
{
{
$s
=
is_string
(
$message
[
0
])
?
$message
[
0
]
:
var_export
(
$message
[
0
],
true
);
static
$levels
=
array
(
return
date
(
'Y/m/d H:i:s'
,
$message
[
3
])
.
" [
{
$message
[
1
]
}
] [
{
$message
[
2
]
}
]
$s
\n
"
;
Logger
::
LEVEL_ERROR
=>
'error'
,
Logger
::
LEVEL_WARNING
=>
'warning'
,
Logger
::
LEVEL_INFO
=>
'info'
,
Logger
::
LEVEL_TRACE
=>
'trace'
,
Logger
::
LEVEL_PROFILE_BEGIN
=>
'profile begin'
,
Logger
::
LEVEL_PROFILE_END
=>
'profile end'
,
);
list
(
$text
,
$level
,
$category
,
$timestamp
)
=
$message
;
$level
=
isset
(
$levels
[
$level
])
?
$levels
[
$level
]
:
'unknown'
;
if
(
!
is_string
(
$text
))
{
$text
=
var_export
(
$text
,
true
);
}
return
date
(
'Y/m/d H:i:s'
,
$timestamp
)
.
" [
$level
] [
$category
]
$text
\n
"
;
}
}
}
}
todo.md
View file @
fb75c958
-
db
*
pgsql, sql server, oracle, db2 drivers
*
write a guide on creating own schema definitions
*
document-based (should allow storage-specific methods additionally to generic ones)
*
mongodb (put it under framework/db/mongodb)
*
key-value-based (should allow storage-specific methods additionally to generic ones)
*
redis (put it under framework/db/redis or perhaps framework/caching?)
-
logging
-
logging
*
WebTarget
*
WebTarget
*
ProfileTarget
*
ProfileTarget
-
caching
*
a console command to clear cached data
---
-
base
-
base
*
module
*
module
-
Module should be able to define its own configuration including routes. Application should be able to overwrite it.
-
Module should be able to define its own configuration including routes. Application should be able to overwrite it.
...
@@ -16,17 +28,6 @@
...
@@ -16,17 +28,6 @@
*
support for markdown syntax
*
support for markdown syntax
*
support for
[
[name
]
]
*
support for
[
[name
]
]
*
consider to be released as a separate tool for user app docs
*
consider to be released as a separate tool for user app docs
-
caching
*
a way to invalidate/clear cached data
*
a command to clear cached data
-
db
*
pgsql, sql server, oracle, db2 drivers
*
write a guide on creating own schema definitions
*
document-based (should allow storage-specific methods additionally to generic ones)
*
mongodb
*
key-value-based (should allow storage-specific methods additionally to generic ones)
*
redis
*
memcachedb
-
i18n
-
i18n
*
consider using PHP built-in support and data
*
consider using PHP built-in support and data
*
message translations, choice format
*
message translations, choice format
...
...
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