Jump to content
  • Checkout
  • Login
  • Get in touch

osCommerce

The e-commerce.

application error handler


bruyndoncx

Recommended Posts

I found a script to create a custom application error log and automatically tailing the log through ajax, as you might be used to on unix systems.

source: https://gist.github.com/taktos/2766122

 

modified slightly to only report unique errors

 

1) create file application_error_handler.php in catalog/includes

 

 

<?php
/*
APPLICATION_LIVE will be used in process to tell if we are in a development or production environment.  
It's generally set as early as possible (often the first code to run), before any config, url routing, etc.

*/

/*
--------------------------------------------------------------------
DEFAULT ERROR HANDLING
--------------------------------------------------------------------
Default error logging.  Some of these may be changed later based on APPLICATION_LIVE.
*/
error_reporting(E_ALL & ~E_STRICT & ~E_NOTICE);
ini_set ( "display_errors", "0");
ini_set ( "display_startup_errors", "0");
ini_set ( "log_errors", 1);
ini_set ( "log_errors_max_len", 0);
ini_set ( "error_log", DIR_FS_CATALOG."/pathtoerrors/php_error_log.txt");


if ( APPLICATION_LIVE == 'N' ) {
    error_reporting(E_ALL & E_NOTICE);
    
    // A few changes to error handling for development.
    // We will want errors to be visible during development.
    ini_set ( "display_errors", "1");
    ini_set ( "display_startup_errors", "0");
    ini_set ( "html_errors", "1");
    ini_set ( "docref_root", "http://www.php.net/");
    ini_set ( "error_prepend_string", "<div style='color:blue; font-family:verdana; padding: 0px; border:1px solid blue;'>");
    ini_set ( "error_append_string", "</div>");
}
?>

 

2) edit the path for the error log file

 

3) find the error_reporting line in application_top and remove it

 

4) include application_error_handler.php after the configure section (as you need DIR_FS_CATALOG defined)

optionally add a define for APPLICATION_LIVE to the configure.php file to enable development debug section

 

5) in your pathroerrors directory, create 2 files php_log.php and php_tail.php

 

php_log.php

 

<?php
/**
 * Require the library
 */
require 'php_tail.php';
/**
 * Initilize a new instance of PHPTail
 * @var PHPTail
 */
$tail = new PHPTail(dirname($_SERVER['SCRIPT_FILENAME']) . "/php_error_log.txt");

/**
 * We're getting an AJAX call
 */
if(isset($_GET['ajax']))  {
        echo $tail->getNewLines($_GET['lastsize'], $_GET['grep'], $_GET['invert']);
        die();
}
/**
 * Regular GET/POST call, print out the GUI
 */
$tail->generateGUI();
?>

 

php_tail.php

 

<?php

class PHPTail {
        
        
        /**
         * Location of the log file we're tailing
         * @var string
         */
        private $log = "";
        /**
         * The time between AJAX requests to the server.
         *
         * Setting this value too high with an extremly fast-filling log will cause your PHP application to hang.
         * @var integer
         */
        private $updateTime;
        /**
         * This variable holds the maximum amount of bytes this application can load into memory (in bytes).
         * @var string
         */
        private $maxSizeToLoad;
        /**
         *
         * PHPTail constructor
         * @[member=param] string $log the location of the log file
         * @[member=param] integer $defaultUpdateTime The time between AJAX requests to the server.
         * @[member=param] integer $maxSizeToLoad This variable holds the maximum amount of bytes this application can load into memory (in bytes). Default is 2 Megabyte = 2097152 byte
         */
        public function __construct($log, $defaultUpdateTime = 200, $maxSizeToLoad = 2097152) {
                $this->log = $log;
                $this->updateTime = $defaultUpdateTime;
                $this->maxSizeToLoad = $maxSizeToLoad;
        }
        /**
         * This function is in charge of retrieving the latest lines from the log file
         * @[member=param] string $lastFetchedSize The size of the file when we lasted tailed it.  
         * @[member=param] string $grepKeyword The grep keyword. This will only return rows that contain this word
         * @[member=Return] Returns the JSON representation of the latest file size and appended lines.
         */
        public function getNewLines($lastFetchedSize, $grepKeyword, $invert) {

                /**
                 * Clear the stat cache to get the latest results
                 */
                clearstatcache();
                /**
                 * Define how much we should load from the log file
                 * @var
                 */
                $fsize = filesize($this->log);
                $maxLength = ($fsize - $lastFetchedSize);
                /**
                 * Verify that we don't load more data then allowed.
                 */
                if($maxLength > $this->maxSizeToLoad) {
                        return json_encode(array("size" => $fsize, "data" => array("ERROR: PHPTail attempted to load more (".round(($maxLength / 1048576), 2)."MB) then the maximum size (".round(($this->maxSizeToLoad / 1048576), 2)."MB) of bytes into memory. You should lower the defaultUpdateTime to prevent this from happening. ")));  
                }
                /**
                 * Actually load the data
                 */
                $data = array();
                if($maxLength > 0) {
                        
                        $fp = fopen($this->log, 'r');
                        fseek($fp, -$maxLength , SEEK_END);
                        $data = explode("\n", fread($fp, $maxLength));
                        
                }
                /**
                 * Run the grep function to return only the lines we're interested in.
                 */
                if($invert == 0) {
                        $data = preg_grep("/$grepKeyword/",$data);
                }
                else {
                        $data = preg_grep("/$grepKeyword/",$data, PREG_GREP_INVERT);
                }
                
                // CB start enforcing unique errors - no repeated msgs
                $uniqs = array();
                foreach ($data as $carinemsg)  {
                  $uniqs[] = substr($carinemsg, strpos($carinemsg,'PHP'));
                }
//                print_r($uniqs);
//                asort($uniqs);
                if (is_array($uniqs)) $data = array_unique($uniqs);
                
                // CB end of additions
                
                /**
                 * If the last entry in the array is an empty string lets remove it.
                 */
                if( is_array($data) && end($data) == "") {
                        array_pop($data);
                }
                return json_encode(array("size" => $fsize, "data" => $data));   
        }
        /**
         * This function will print out the required HTML/CSS/JS
         */
        public function generateGUI() {
                ?>
                <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
                "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
                <html xmlns="http://www.w3.org/1999/xhtml">
                        <head>
                                <title>PHPTail</title>
                                <meta http-equiv="content-type" content="text/html;charset=utf-8" />

                                <link type="text/css" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.9/themes/flick/jquery-ui.css" rel="stylesheet"></link>
                                <style type="text/css">
                                        #grepKeyword, #settings {
                                                font-size: 80%;
                                        }
                                        .float {
                                                background: white;
                                                border-bottom: 1px solid black;
                                                padding: 10px 0 10px 0;
                                                margin: 0px;  
                                                height: 30px;
                                                width: 100%;
                                                text-align: left;
                                        }
                                        .results {
                                                padding-bottom: 20px;
                                        }
                                </style>

                                <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script>
                                <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.9/jquery-ui.min.js"></script>
                                
                                <script type="text/javascript">
                                        /* <![CDATA[ */
                                        //Last know size of the file
                                        lastSize = <?php
                                          if (filesize($this->log) > 0 ) {
                                          echo filesize($this->log); } else {echo 0;} ?>;
                                        //Grep keyword
                                        grep = "";
                                        //Should the Grep be inverted?
                                        invert = 0;
                                        //Last known document height
                                        documentHeight = 0;
                                        //Last known scroll position
                                        scrollPosition = 0;
                                        //Should we scroll to the bottom?
                                        scroll = true;
                                        $(document).ready(function(){

                                                // Setup the settings dialog
                                                $( "#settings" ).dialog({
                                                        modal: true,
                                                        resizable: false,
                                                        draggable: false,
                                                        autoOpen: false,
                                                        width: 590,
                                                        height: 270,
                                                        buttons: {
                                                                Close: function() {
                                                                        $( this ).dialog( "close" );
                                                                }
                                                        },
                                                        close: function(event, ui) {
                                                                grep = $("#grep").val();
                                                                invert = $('#invert input:radio:checked').val();
                                                                $("#grepspan").html("Grep keyword: \"" + grep + "\"");
                                                                $("#invertspan").html("Inverted: " + (invert == 1 ? 'true' : 'false'));
                                                        }
                                                });
                                                //Close the settings dialog after a user hits enter in the textarea
                                                $('#grep').keyup(function(e) {
                                                        if(e.keyCode == 13) {
                                                                $( "#settings" ).dialog('close');
                                                        }
                                                });             
                                                //Focus on the textarea                                 
                                                $("#grep").focus();
                                                //Settings button into a nice looking button with a theme
                                                $("#grepKeyword").button();
                                                //Settings button opens the settings dialog
                                                $("#grepKeyword").click(function(){
                                                        $( "#settings" ).dialog('open');
                                                        $("#grepKeyword").removeClass('ui-state-focus');
                                                });
                                                //Set up an interval for updating the log. Change updateTime in the PHPTail contstructor to change this
                                                setInterval ( "updateLog()", <?php echo $this->updateTime; ?> );
                                                //Some window scroll event to keep the menu at the top
                                                $(window).scroll(function(e) {
                                                    if ($(window).scrollTop() > 0) {
                                                        $('.float').css({
                                                            position: 'fixed',
                                                            top: '0',
                                                            left: 'auto'
                                                        });
                                                    } else {
                                                        $('.float').css({
                                                            position: 'static'
                                                        });
                                                    }
                                                });
                                                //If window is resized should we scroll to the bottom?
                                                $(window).resize(function(){
                                                        if(scroll) {
                                                                scrollToBottom();
                                                        }
                                                });
                                                //Handle if the window should be scrolled down or not
                                                $(window).scroll(function(){
                                                        documentHeight = $(document).height();
                                                        scrollPosition = $(window).height() + $(window).scrollTop();
                                                        if(documentHeight <= scrollPosition) {
                                                                scroll = true;
                                                        }
                                                        else {
                                                                scroll = false;
                                                        }
                                                });
                                                scrollToBottom();
                                                                                        
                                        });
                                        //This function scrolls to the bottom
                                        function scrollToBottom() {
                                                $('.ui-widget-overlay').width($(document).width());
                                            $('.ui-widget-overlay').height($(document).height());

                                                $("html, body").scrollTop($(document).height());
                                                if($( "#settings" ).dialog("isOpen")) {
                                                        $('.ui-widget-overlay').width($(document).width());
                                                    $('.ui-widget-overlay').height($(document).height());
                                                    $( "#settings" ).dialog("option", "position", "center");
                                                }
                                        }
                                        //This function queries the server for updates.
                                        function updateLog() {
                                                $.getJSON('/beta/errors/php_log.php?ajax=1&lastsize='+lastSize + '&grep='+grep + '&invert='+invert, function(data) {
                                                        lastSize = data.size;
                                                        $.each(data.data, function(key, value) {
                                                                $("#results").append('' + value + '<br/>');
                                                        });
                                                        if(scroll) {
                                                                scrollToBottom();
                                                        }
                                                });
                                        }
                                        /* ]]> */
                                </script>
                        </head>
                        <body>
                                <div id="settings" title="PHPTail settings">
                                        <p>Grep keyword (return results that contain this keyword)</p>
                                        <input id="grep" type="text" value=""/>
                                        <p>Should the grep keyword be inverted? (Return results that do NOT contain the keyword)</p>
                                        <div id="invert">
                                                <input type="radio" value="1" id="invert1" name="invert" /><label for="invert1">Yes</label>
                                                <input type="radio" value="0" id="invert2" name="invert" checked="checked" /><label for="invert2">No</label>
                                        </div>
                                </div>
                                <div class="float">
                                        <button id="grepKeyword">Settings</button>
                                        <span>Tailing file: <?php echo $this->log; ?></span> | <span id="grepspan">Grep keyword: ""</span> | <span id="invertspan">Inverted: false</span>
                                </div>
                                <div id="results">
                                </div>
                        </body>
                </html>
                <?php
        }
}
?>

 

Done, point your browser to pathtoerrorlog/php_log.php and start browsing your site to generate errors (notices)

KEEP CALM AND CARRY ON

I do not use the responsive bootstrap version since i coded my responsive version earlier, but i have bought every 28d of code package to support burts effort and keep this forum alive (albeit more like on life support).

So if you are still here ? What are you waiting for ?!

 

Find the most frequent unique errors to fix:

grep "PHP" php_error_log.txt | sed "s/^.* PHP/PHP/g" |grep "line" |sort | uniq -c | sort -r > counterrors.txt

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...