Zend Framework: Zend_Log Component Proposal
| Proposed Component Name | Zend_Log |
|---|---|
| Developer Notes | http://framework.zend.com/wiki/display/ZFDEV/Zend_Log |
| Proposers | Mike Naberezny, with direction from Bill Karwin and Andi Gutmans |
| Revision | 1.1 - 17 Jan 2007: Use "writer" instead of "handler" (Christopher Thompson) (wiki revision: 23) |
Table of Contents
1. Overview
This proposal covers a complete rewrite of Zend_Log. It addresses concerns
raised in another proposal, "Zend_Log Dynamic", and also proposes new
features requested both by the Zend team and community members.
2. References
- Existing Zend_Log Component
- Zend_Log Dynamic - Art Hundiak
- Apache Log4j Project
- PEAR Log
- IETF RFC-3164: The BSD syslog Protocol
3. Component Requirements, Constraints, and Acceptance Criteria
- Usage must remain simple, on the same level as the current implementation.
While the log4x loggers are a popular and powerful standard, Zend has
decided to use their influence but not make a logger that is based on
them. Instead, the logger will be closer in usage to PEAR's Log package.
- The new logger will make little or no use of static functions.
It must be easy to store logger instances for use with other components.
- It should be possible and relatively simple to add new log writers. These
should include additional ones from the community to be included with the
package and also any specialized writers that end users might need to
write for their own needs.
- The tasks of managing data to be logged (loggers), the log backend
(writers), and filtering log messages (filters) should be cleanly
separated into different objects. It should be simple for users to register
their own objects to perform these functions. However, the logger should
have a simple default configuration and users should not need to be aware
of these features until they are needed.
4. Dependencies on Other Framework Components
The dependencies will be determined primarily by which log writers are
developed. Possibly these will include:
- Zend_Db
- Zend_Cache
- Zend_Mail
- Zend_Http
- Zend_Exception
5. Theory of Operation
Logger
The base logging class where writers and filters can be registered.
Users will able to add new levels with a method such as
$log->addLevel($name, $level) provided the name or level does not conflict
with an existing one. The default levels will always be present and can
never be overridden (without subclassing Zend_Log).
Message can be logged with a method such as $log->log($message, $level).
It will also provide convenience methods for each level, such as
$log->warn('message');
Log Levels
Each log level will have a name and a value. The default log levels
will mimic those from syslog:
0 Emergency: system is unusable
1 Alert: action must be taken immediately
2 Critical: critical conditions
3 Error: error conditions
4 Warning: warning conditions
5 Notice: normal but significant condition
6 Informational: informational messages
7 Debug: debug-level messages
User error levels may be any number above DEBUG (7).
Filter
Loggers will have the ability to filter by level. For more sophisticated
filtering, filter objects built by users can be registered and chained.
Writer
Initially, the following log writers will be developed:
- Stream Writer (STDOUT/STDERR)
- RDBMS Writer (Zend_Db)
- File Writer
- XML File Writer
- Test Writer (mock for testing)
In the future, additional writers could be developed by the
community. Suggestions for these are:
- Rotating File Writer (Rotate Logs)
- Socket Writer (Log to TCP/IP)
- Syslog Writer (UNIX/Linux Syslog)
- NT Event Writer (Windows NT-based systems)
- Email Writer (Zend_Mail)
- HTTP Writer (Zend_Http_Client)
6. Milestones / Tasks
- Iteration 1 - Base Logger implementation
- Iteration 2 - Writer and Filter implementation
- Iteration 3 - Log writer implementation (Test, Stream, File)
- Iteration 4 - Additional writers (RDBMS, XML)
- Iteration 5 - Documentation (DocBook)
Unit tests will be written as an integral and ongoing part of the
development process so no separate iteration is needed for them.
7. Class Index
- Logger (Zend_Log)
- Writer (Zend_Log_Writer_*)
- Filter (Zend_Log_Filter_*)
- Error (Zend_Log_*Exception)
8. Use Cases
| UC-01 | Simple Usage |
|---|
| UC-02 | Using Multiple Log Writers |
|---|
| UC-03 | Custom Log Levels |
|---|
| UC-04 | Filtering for All Writers |
|---|
A filter can be added to either Zend_Log, where it will be applied
to all writers. Either a simple level or a filter object may be passed.
| UC-05 | Filtering for a Specific Writer |
|---|
| UC-06 | Use with the Registry |
|---|
The current Zend_Log implementation uses all static functions. This new
implementation has no static functions. However, for users that prefer the
old usage, similar usage can be achieved by storing a logger object in the
registry.
9. Class Skeletons
Class skeletons will not be proposed at this stage. When development begins,
behavioral requirements of the objects will be expressed as tests and the
classes will then be developed based on these requirements using TDD.
I'd like to see two additional things: (1) The constructor should take a single argument, a log adapter; this would be more convenient, and ensure no logging happens prior to logging a message. (2) I like the logLevel(), but want to make sure that the convenience methods would not change the global log level (I assume they wouldn't, but feel this should be explicit criteria).
| Official Zend comment We have reviewed this proposal and we approve it for inclusion in the Zend Framework. This represents a redesign of the existing Zend_Log class, and it is the intention to remove the old implementation in favor of this new design. We have a few specific comments that we would like to see addressed in the design:
|
Hi. I have a feature request. I have actually stumbled upon it while replying to Gavin's comment concerning my own proposal:
http://framework.zend.com/wiki/display/ZFPROP/Zend_Controller_Router_RegexRoute+-+Michael+Minicki
In RewriteRouter I need to log a couple of messages or a pack of data at once:
It gave me an idea to pass the message as an array:
Which can then be rendered differently by different writers.
For example, XML writer can render it as:
While file writer could use multiline entry:
And DB of course can keep it on one line separated with semicolon.
Hope you will like it too ![]()
How about setting log format?
for example:
$log->setFormat("%datetime [%pid] %level %message");
by doing:
$log->warning("Live support not ready");
should produce:
2007-03-12 14:11:38 [8439] WARNING Live support not ready
There should be predefined keyword for formatting,
the most important IMHO:
datetime, current locale date time
date,
time,
pid, current process ID
level, current log level
message, log message
Thanks
Is there an existing proposal to contribute a rotating log file writer?
If yes, could someone kindly point me to it?
We have had two feature requests logged in our issue tracker regarding log rotation solutions.
http://framework.zend.com/issues/browse/ZF-263
http://framework.zend.com/issues/browse/ZF-563
I continue to believe that this is not appropriate to solve in a PHP class. Linux has the 'logrotate' command for this purpose.
http://www.linuxcommand.org/man_pages/logrotate8.html
Windows does not have a standard tool to do this. It needs to be done as part of restarting the HTTP server, so it cannot be a PHP solution.
Thanks for the prompt response, Bill.
First time I heard of logrotate. I definitely prefer that option since I'm on Linux. I agree too that it's best not to duplicate functionality if there's already a good tool that provides it.
P.S. I enjoyed your recent ZF Overview webinar. Even as I'm quite familiar with the content you delivered, I was all the same enwrapped by your delivery. Nice work with ZF, all-round.
ZF Home Page
Code Browser
Wiki Dashboard
I noticed from the use cases that the names of convenience methods appear to be indeterministic. For example, a log message of Zend_Log::CRITICAL would correspond to an invocation of Zend_Log::crit(). Does this matter? User-defined log levels, however, appear to result in method names matching the level name (e.g., "foo").
I'm not sure I fully understand the first sentence of UC-04; perhaps a slight rephrasing would help?
How would I create a logger that writes messages only of a user-defined log level? For instance, let's assume that I want to write only "specialError" level messages both to a log file and to an e-mail address. Would this use case be considered in the scope of the proposal?
It might be reasonable to use Zend_Log for application security auditing. For example, it is often valuable to collect information about certain security violations, such as logging when users attempt to perform unauthorized operations. I could imagine providing via the Zend_Auth and Zend_Acl APIs methods to plug in Zend_Log objects for providing for an audit trail.
The proposal is shaping up nicely, and the approach of using use cases and test-driven development seems very appropriate to me.