jump to navigation

Logging with source object name and function (updated) June 14, 2006

Posted by rossoft in CakePHP.
trackback

When you log some info, get the caller filename:filenumber object_name->function_name like:

class TestsController{
function myaction()
{
$this->log('Some info here')
}
}

at error.log file :
06-06-07 10:12:09 [ /app/controllers/tests_controller.php:4 TestsController::myaction()] Error: Some info here

The code is from OT (MIT license)

You need to load this class before the original cake class. Copy to vendors/logs/logs.php. Then put in your bootstrap.php file: require_once ROOT. DS .’vendors’ . DS . ‘logs’ . DS . ‘logs.php’;

Now everywhere you can use some other functions like caller_path that returns the complete stack trace or $this->log('xxxx') that will show the caller filename:linenumber object_name->function_name()
<?php
 /**  * Extends log class. The log now shows the caller [Filename:linenumber ClassName->function()]
 *
 * @author RosSoft
 * @version 0.3
 * @license MIT 
 *
 * @link http://sputnik.pl/dev/labs/fase/ Fase Framework
 */
 
/**
 * Set to true if you want filename::linenumber at logs
 */
define('LOG_FILENAME',true);
 
/**
 * Set to true if you want objectname->function() at logs
 */
define('LOG_OBJECTNAME',true);
 
/**
 * Date format of the logs
 * 
 * Spain Locale:   'd-m-y H:i:s'
 * US Locale:      'y-m-y H:i:s'
 */
define('LOG_DATEFORMAT','d-m-y H:i:s');
 
/**
 * Logs messages to text files.
 *
 * @package        cake
 * @subpackage    cake.cake.libs
 */ 
class CakeLog
{
    /**
     * Writes given message to a log file in the logs directory.
     * Puts the calling function name
     *
     * @param string $type Type of log, becomes part of the log's filename
     * @param string $msg  Message to log
     * @param integer $skip Number of calls to skip for reaching the calling function. The default skips to the caller of Object->log
     * @return boolean Success
     */
    function write($type, $msg,$skip=3)
    {
        if (!class_exists('File'))
        {   
             uses('file');
        }
        $filename=LOGS . $type . '.log';
        $output=date(LOG_DATEFORMAT);
        if (LOG_FILENAME || LOG_OBJECTNAME)
        {
            $output.=' [  ';
            if (LOG_FILENAME)
            {
                $output.=caller_place($skip) . '  ';
            }
            if (LOG_OBJECTNAME)
            {
                $output.=caller_name($skip) . '  ';
            }
            $output.=']';             
        }
        $output.=' ' . ucfirst($type) . ': ' . $msg . "\n\n";
        $log=new File($filename);
        return $log->append($output);
    }
}
 
/**
 * Debug calling file path
 * @author Michal Tatarynowicz (Fase Framework)
 * @license http://www.opensource.org/licenses/mit-license.php The MIT License
 */
function caller_file ($skip=1)
{
    $trace = caller_backtrace($skip);
    foreach ($trace as $step)
    {
        if (@$step['file']) return $step['file'];
    }
    return false;
}
 
/**
 * Returns nicely formatted call stack
 * @author Michal Tatarynowicz (Fase Framework)
 * @license http://www.opensource.org/licenses/mit-license.php The MIT License
 */       
 
function caller_backtrace ($skip=1) {
    $trace = debug_backtrace();
    $output = array();
 
    for ($i=$skip;$i<count($trace);$i++)
    {
        $step=$trace[$i];
        if (! empty($step['file']))
        {
            if (isset($step['object']) && is_object($step['object']))
            {     
                $class = get_class($step['object']);
            }
            else
            {
                $class = @$step['class'];             
            }
            $type  = @$step['type'];
            $funct = @$step['function'];
     
            $output[] = array
            (
                'name'  => $class? $class.$type.$funct.'()': $funct.'()',
                'place' => str_replace(ROOT, '', $step['file']).':'.$step['line'],
                'file'  => $step['file'],
                'class' => $class,
                'type'  => $type,
                'funct' => $funct
            );
        }
        else if (! empty ($step['class']))
        {
            $class = str_replace(' ', '_', ucwords(str_replace('_', ' ', @$step['class'])));
            $funct = @$step['function'];             
            $output[] = array
            (
                'name'=> $class . '->' . $funct . '()',
                'place'=>'',
                'file'=>'',
                'class'=>$class,
                'type'=>'',
                'funct'=>$funct,                 
            );
        }
    }
    return $output;
}
 
/**
 * Returns caller function's full stack trace
 * @author Michal Tatarynowicz (Fase Framework)
 * @license http://www.opensource.org/licenses/mit-license.php The MIT License
 */
function caller_path ($skip=1)
{
    $parsed = caller_backtrace($skip);   
 
    $output = array();
    foreach ($parsed as $step)
    {
        list($name, $place) = array_values($step);
        $output[] = $name . '::' . $place;
    }
 
    return join( ' > ', $output );
}
 
/**
 * Returns calling method or function name
 * @author Michal Tatarynowicz (Fase Framework)
 * @license http://www.opensource.org/licenses/mit-license.php The MIT License
 */
function caller_name ($skip=1)
{
    $step = caller_backtrace($skip);
    return $step[0]['class'] . '->' . $step[1]['funct'] . '()';
}
 
/**
 * Retuns caller function's filename and line number
 * @author Michal Tatarynowicz (Fase Framework)
 * @license http://www.opensource.org/licenses/mit-license.php The MIT License
 */
function caller_place ($skip=1)
{
    $step = caller_backtrace($skip);
    if ($step[0]['place'])
    {
        return $step[0]['place'];
    }
    else
    {
        return $step[0]['name'];
    }
       
}
?>

Advertisements

Comments»

1. davide - June 14, 2006

Great, but I get an error. 🙂

I’m not sure about doing it in the right way.

When I add the vendors() call in the bootstrap I get

Fatal error: Call to undefined function: vendors() in …

Thanks

2. rossoft - June 14, 2006

ok I load it with require_once (I was thinking that it work with vendor function)

require_once ROOT. DS .’vendors’ . DS . ‘logs’ . DS . ‘logs.php’;

3. Felix Geisendörfer - June 14, 2006

Hey rossoft, I like that idea, you could open an RFC on trac for this in 2.0 ; ). Bye

4. rossoft - June 14, 2006

thanks, done

5. Richard@Home » Blog Archive » links for 2006-06-15 - June 15, 2006

[…] RosSoft » Logging with source object name and function A nifty error logging plugin (tags: cakephp plugin) […]

6. Grant Cox - June 15, 2006

Wow, this is really useful. I had wanted something like this for a while, but didn’t know that there was such a function as debug_backtrace in PHP. However, I put this into an existing project with a number of existing log() calls, and some of them were not displaying correctly (would show the caller function as “debug_traceback”). I modified the print statements to include line numbers, and this would also occasionally not work – printing the same class:function instead of file:line.

Anyway, I have rewritten the caller_traceback function, which fixes these for me. I will email this to you for your perusal.

7. rossoft - June 15, 2006

Thanks Grant Cox, I’ve included Filename:linenumber (but your caller_traceback function doesn’t work in my case)

8. davide - June 16, 2006

I prefer the version with no filename. Makes a more readable logs, IMO.

However it would be nice if you can configure the log format, something like log4j. And sure, make some system for rolling the log files on some criterias, for example dimensions, or date, and so on.

Some hints 🙂

9. RosSoft » Register Global Callback functions - June 18, 2006

[…] For Example: in my extension to CakeLog class, you can do: […]

10. hugh f - June 25, 2006

Great stuff, thanks for that. I had a minor problem loading the vendor file in bootstrap, turned out to simply be some strange quotes copied from this page – replaced with normal single quote and all worked fine. Thanks again!

11. dvtuoqbclg - March 18, 2007

straight guys ass raped

12. noinoPart - June 14, 2007

xrtest

13. kashish - August 21, 2007

Hi,

I am new to Cake php. I want to know how i can made missing controller,missing actions etc errors to be logged to error.log.

I have set define(‘LOG_ERROR’, 2); in core.php and have provided 777 permissions to /tmp/logs folder.

In addition to this, i want that 404 errors should be logged in apache’s log file but its not happening currently. May be cakephp bypasses this.

Please guide me.

Thanks in advance,
Kashish


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: