OJS OCS OMP OHS

You are viewing the PKP Support Forum | PKP Home Wiki



[Patches] Stacktrace to log file, custom ADODB log function

OJS development discussion, enhancement requests, third-party patches and plug-ins.

Moderators: jmacgreg, btbell, michael, bdgregg, barbarah, asmecher

Forum rules
Developer Resources:

Documentation: The OJS Technical Reference and the OJS API Reference are both available from the OJS Documentation page.

Git: You can access our public Git Repository here. Comprehensive Git usage instructions are available on the wiki.

Bugzilla: You can access our Bugzilla report tracker here.

Search: You can use our Google Custom Search to search across our main website, the support forum, and Bugzilla.

Questions and discussion are welcome, but if you have a workflow or usability question you should probably post to the OJS Editorial Support and Discussion subforum; if you have a technical support question, try the OJS Technical Support subforum.

[Patches] Stacktrace to log file, custom ADODB log function

Postby rmichael » Tue Nov 18, 2008 2:38 pm

While testing and debugging my work with OJS, it is helpful to have SQL debugging and stack tracing enabled at all times. (I'll likely even leave them enabled on our production server, since it's frequently difficult to duplicate a problem after the first occurrence.) Here are two patches I use.

The ADODB custom logger isn't necessarily appropriate for main inclusion. Though, I think teaching people about the possibility of debug logging to a file would be helpful because it is hard to use OJS while it's dumping lots of SQL above every page. The code is commented in the patch; so even after applied, it requires user intervention.

The stacktrace to log file functionality would be a big help, however. I'm sure this code isn't great, but maybe it's a start toward inclusion. You must add "stacktrace_to_logfile = On" to config.inc.php.

Thoughts?

Code: Select all
--- ojs-2.2.2-clean/index.php   2008-11-18 10:54:24.000000000 -0500
+++ ojs-2.2.2-test/index.php    2008-11-18 15:40:36.000000000 -0500
@@ -52,6 +52,26 @@
 // $Id: index.php,v 1.23 2008/07/01 01:16:09 asmecher Exp $
 
 
+/*
+ * Uncomment the code immediately below and set "debug = On" in your "config.inc.php".
+ *
+ * Define a custom ADODB error log function.  See: "lib/adodb/adodb.inc.php".
+ * Unfortunately, HTML is inserted into the error message by _adodb_debug_execute(),
+ * in lib/adodb/adodb-lib.inc.php; crudely remove it for log readability.
+ * (We can't "unset($_SERVER['HTTP_USER_AGENT']", because that will break OJS.)
+ */
+/*
+$GLOBALS['ADODB_OUTP'] = 'ojsLogSql';
+
+function ojsLogSql ($msg, $newline) {
+  $msg = str_replace( array('&nbsp;', '<code>', '</code>', '<hr />'), "", $msg);
+  $msg = htmlspecialchars_decode($msg);
+  error_log("$msg $newline");
+}
+
+*/
+
+
 /**
  * Handle a new request.
  */


Code: Select all
--- ojs-2.2.2-clean/includes/functions.inc.php  2008-06-30 21:16:11.000000000 -0400
+++ ojs-2.2.2-test/includes/functions.inc.php   2008-11-18 15:33:21.000000000 -0500
@@ -83,10 +83,10 @@
                $isErrorCondition = false;
        }
 
-       echo "<h1>$reason</h1>";
+       $stackTraceOutput[] = "$reason";
 
        if ($showStackTrace && checkPhpVersion('4.3.0')) {
-               echo "<h4>Stack Trace:</h4>\n";
+
                $trace = debug_backtrace();
 
                // Remove the call to fatalError from the call trace.
@@ -138,13 +138,46 @@
                        $file = isset($bt['file'])?$bt['file']:'(unknown)';
                        $line = isset($bt['line'])?$bt['line']:'(unknown)';
 
-                       echo "<strong>File:</strong> {$file} line {$line}<br />\n";
-                       echo "<strong>Function:</strong> {$class}{$type}{$function}($args)<br />\n";
+                       // Record all the trace information as an array in the main output array.
+                       $stacktraceOutput[] = array($file, $line, $class, $type, $function, $args);
+               }
+       }
+
+       // Check the destination of the stack trace output.
+       $stackTraceToLogfile = Config::getVar('debug', 'stacktrace_to_logfile');
+
+       // If the destination is the log file, plain print information without markup.
+       if ($stackTraceToLogfile) {
+
+               // The first element is the $reason, and we only print it once.
+               error_log("OJS Fatal Error: $stackTraceOutput[0]\n");
+               array_shift($stackTraceOutput);
+
+               // The remaining elements are each an array containing trace specific output; iterate over them.
+               foreach ($stackTraceOutput as $traceOutput) {
+                       echo "Stack Trace:\n";
+                       echo "File: {$traceOutput[0]} line {$traceOutput[1]}\n";
+                       echo "Function: {$traceOutput[2]}{$traceOutput[3]}{$traceOutput[4]}($traceOutput[5])\n";
+               }
+
+       // Else, the destination is the browser, print HTML.
+       } else {
+               // Even if the stacktrace is going to the browser, put short note in the log file.
+               error_log("OJS Fatal Error: $stackTraceOutput[0]\n");
+
+               // The first element is the $reason, and we only print it once.
+               echo "<h1>$stackTraceOutput[0]</h1>";
+               array_shift($stackTraceOutput);
+
+               // The remaining elements are each an array containing trace specific output; iterate over them.
+               foreach ($stackTraceOutput as $traceOutput) {
+                       echo "<h4>Stack Trace:</h4>\n";
+                       echo "<strong>File:</strong> {$traceOutput[0]} line {$traceOutput[1]}<br />\n";
+                       echo "<strong>Function:</strong> {$traceOutput[2]}{$traceOutput[3]}{$traceOutput[4]}($traceOutput[5])<br />\n";
                        echo "<br/>\n";
                }
        }
 
-       error_log("OJS: $reason");
        die();
 }
 
rmichael
 
Posts: 113
Joined: Fri Mar 30, 2007 3:32 pm

Re: [Patches] Stacktrace to log file, custom ADODB log function

Postby mcrider » Tue Nov 18, 2008 3:10 pm

Hi Richard,

Very cool, thanks. I just finished writing a custom error handler (http://pkp.sfu.ca/bugzilla/show_bug.cgi?id=3850), though I'm not sure I'm completely happy with it. I would have liked a way to encapsulate the SQL backtrace into the log messages, but we really want to try not to bundle OJS with a patched version of ADOdb. I'll certainly use it for my own debugging though.

Cheers,
Matt
mcrider
 
Posts: 952
Joined: Mon May 05, 2008 10:29 am
Location: Vancouver, BC

Re: [Patches] Stacktrace to log file, custom ADODB log function

Postby rmichael » Tue Nov 18, 2008 3:58 pm

My motivation was to be able to monitor everything OJS does (catching problems the first time), either to a logfile or to the browser. In practice, I almost never want that output to the browser, but when it's to a logfile, I don't want it wrapped in HTML. So the set_error_handler stuff you're doing sounds helpful to generalize this.

As regards ADODB, I used the approach suggested in their source to change their outp() logging function, and it's not modifying ADODB itself. On the other hand, setting an ADODB global at the top of the main index.php file doesn't really seem like the right place to do this. Further, it's a shame ADODB wraps messages HTML before they enter the logger function. The message passed to the log function should be destination agnostic, and the log function itself should be controlling the destination-dependent formatting.

Glad it's helped someone though. :)
rmichael
 
Posts: 113
Joined: Fri Mar 30, 2007 3:32 pm

Re: [Patches] Stacktrace to log file, custom ADODB log function

Postby rmichael » Wed Nov 19, 2008 11:40 am

I've noticed the stacktrace to logfile changes don't work as well as I'd hoped.

Unfortunately, ADODB does it's backtrace without calling outp(). In v4.xx, it also checks HTTP_USER_AGENT to decide if it should output HTML, which is inconvenient. The end of the adodb-lib.inc.php:_adodb_backtrace() also outputs (by default, since $printOrAr = true by default) before it returns. Though in ADODB5 (5.06a anyway), _adodb_backtrace() takes $ishtml as a parameter (however, they don't do much with it; for example, still htmlspecialchars() eveything regardless).

A worthwhile and minimal modification of ADODB would be to change adodb-lib.inc.php:_adodb_backtrace() to use outp(). If I do this, I'll post it.
rmichael
 
Posts: 113
Joined: Fri Mar 30, 2007 3:32 pm


Return to OJS Development

Who is online

Users browsing this forum: Baidu [Spider] and 3 guests