views:

323

answers:

4

Hello, I m using Zend_Log to create and Log messages. It works well for storing Log messages in to a stream (a new defined file name), well i want to store these messages in to Buffer array.

For this i visit : http://framework.zend.com/wiki/display/ZFPROP/Zend_Log+Rewrite#Zend_LogRewrite-1.Overview but fail to get their points.............

Thanks : Rob Knight

But i want some thing like;

If i write $logger->info('Informational message'); in any line of my .php file, the message which will show, must contain the Message Text along with Line Number.

Let suppose i write $logger->info('Name Already Exists'); at line number 116 of my test.php file. Then the result Log must be like : INFO: "Name Already Exists", Line: 116, File: test.php

A: 

Use Zend_Log_Writer_Mock. The documentation page you linked to above is not the actual manual page for Zend_Log - follow my link and you'll get the full documentation.

Usage:

$logger = new Zend_Log();
$writer = new Zend_Log_Writer_Mock();

$logger->addWriter($writer);

$logger->info('My message');
// access messages via $writer->events

To include filename and line number, do as follows:

function LogMessage($logger, $message, $line, $file) {
    $logger->write("INFO: {$message} at line {$line} of file {$file}");
}

LogMessage($logger, 'Informational message', __LINE__, __FILE__);

Just call the LogMessage function for logging messages, passing in the instance of the logger that we prepared earlier.

Rob Knight
A: 

You're gonna have to write your own writer for this functionality I think. You can use debug_backtrace to see where the $logger->info() for the line and file info.

http://de2.php.net/manual/en/function.debug-backtrace.php

smack0007
A: 

Here's how I solved the same problem, but you need to abstract out the logging call it saves you typing anyway

in your bootstrap.php

class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{

    protected function _initLogging() {
        $log = new Zend_Log();

        $writer_log = new Zend_Log_Writer_Stream(APPLICATION_PATH.'/../logs/'.APPLICATION_ENV.'.log');            
        $formatter = new Zend_Log_Formatter_Xml();
        $writer_log->setFormatter($formatter);
        $log->addWriter($writer_log);
        Zend_Registry::set('logger', $log);            
    }

}

and somewhere with global scope

function debug($message, $level = Zend_Log::DEBUG) {
    $backtrace = debug_backtrace();
    Zend_Registry::get('logger')->setEventItem('file', $backtrace[1]['file']);    
    Zend_Registry::get('logger')->setEventItem('class', $backtrace[1]['class']);
    Zend_Registry::get('logger')->setEventItem('function', $backtrace[1]['function']);
    Zend_Registry::get('logger')->setEventItem('line', $backtrace[1]['line']);
    Zend_Registry::get('logger')->log($message, $level);
}

the offset in the $backtrace array is to use the function above the one the called, take a look at the output of debug_backtrace if you need to look somewhere else

it's used like this

class SomeClass {
    function func {
        debug("Message");
    }
}

and comes out like this (formatting added)

<logEntry>
    <timestamp>2010-01-01T00::00+00:00</timestamp>
    <message>Message</message>
    <priority>7</priority>
    <priorityName>DEBUG</priorityName>
    <class>SomeClass</class>
    <function>func</function>
    <line>2</line>
</logEntry>
oliyoung
+1  A: 

Here's a shot at it. With this method, you don't need to write any global utility functions. You can use the Zend_Log interface for all your method calls.

In your bootstrap, initialize your logger. Make sure to include the file and line event types in your formatter. Then, create the Logger with a custom writer, which will set the values of the file and line event types at runtime.

$format = '%file% %line% %message%' . PHP_EOL;
$formatter = new Zend_Log_Formatter_Simple($format);
$writer = new My_Log_Writer_Stream('file://' . $traceLogPath);
$writer->setFormatter($formatter);
$log = new Zend_Log($writer);

In the custom writer, go through the backtrace and find the first class that isn't related to your logging libraries. There is probably a more elegant way to write this piece, but it seems to work in my environment (I'll vote you up for any good suggestions). When you have found the desired item in the backtrace, add it to the event array and then call the parent's write method. If you have initialized the formatter correctly, it will write the event values to the log string.

class My_Log_Writer_Stream extends Zend_Log_Writer_Stream {

    protected function _write($event) {

        $backtrace = debug_backtrace();

        foreach($backtrace as $traceItem) {
            $class = $traceItem['class'];
            if(!is_subclass_of($class, 'Zend_Log') &&
                      !is_subclass_of($class, 'Zend_Log_Writer_Abstract') &&
                      $class !== 'Zend_Log' &&
                      $class !== 'Zend_Log_Writer_Abstract') {
                break;
            }
        }

        $event['file'] = $traceItem['file'];
        $event['line'] = $traceItem['line'];

        parent::_write($event);
    }
Chris