ADOdb

Database Abstraction Layer for PHP

User Tools

Site Tools


v5:reference:logging

Logging

ADOdb provides an internal debugging system that exposes the SQL commands used to execute a command, as well as other messages that can provide guidance when, for example, trying to establish a connection to the database. The earliest that debugging can be started is after instantiating the driver but before connection. In its simplest usage, debugging is enabled as follows:

include '/adodb-dir/adodb.inc.php';
 
$db = newAdoConnection('mysqli');
 
/*
* Initialize debugging
*/
$db->debug = true;
 
$db->connect('host','user','pass','database');

This might produce output something like:

-----<hr>
(mysqli): select * from usersx 
   
-----<hr>
Query: select * from usersx failed. Table 'db.usersx' doesn't exist
1146: Table 'db.usersx' doesn't exist
ADOConnection._Execute(select * from usersx, false)% line 1313, file: C:\dev\GitHub\ADOdb\adodb.inc.php
ADOConnection.Execute(select * from usersx)% line   46, file: C:\dev\tests\test7.php

The output is suitable for viewing in a browser, with messages from the database driver as well as backtrace data if there are problems. Note that debugging can be switched on and off during code execution as required.

Alternative Debugging Levels

The following alternative levels are available. Each produces a slightly different output.

Debug Level Description
true Default as described above
-1 The most minimal logging level. Formatted as the default option, but does not include backtrace data or any ADOdb debugging/logging messages
-99 Adds ADOdb messages to the above format, but no backtrace data
99 The logging equivalent of true
2 Use the datalogging object as described below

Overriding The Default Logging Function

The default logging behavior is to send all messages to STDOUT, but the behavior may be modified by either:

  1. Defining a constant ADODB_OUTP which holds the name of the function that overrides the standard value
  2. A variable $ADODB_OUTP which is globalized and achieves the same as above. This function can be dynamically changed.

Function Definition

The overriding function must accept 2 arguments:

  1. A String which contains the message
  2. A boolean which indicates whether to throw a newline. This may be discarded based on how the function works

Example Function

DEFINE ('ADODB_OUTP','myLogger');
 
function myLogger($msg,$discard)
{
    print "\nThis is my messsage: $msg";
} 

The ADOdataLoggingObject

From ADOdb Version 5.22, the Data Logging Object may be used to provide a much more granular control of messages, by also including elements such as logging level and error numbers in the debug output. There are no internal methods for extracting and displaying the information, so it must be used in conjunction with an override logging function (ADODB_OUTP) as described above.

The logging object is described below

**
* An object in which to log/store activity data
*/
class ADODataLoggingObject
{
	/*
	* The SQL statement(s) processed, if any
	*/
	public $sql;
 
	/*
	* The bind data, if any
	*/
	public $inputArray;
 
	/*
	* The database driver error
	*/
	public $errorNo = 0;
 
	/*
	* The database driver error message, or any message
        * deliberately pushed into the object
	*/
	public $errorMessage;
 
	/*
	* The ADOdb Meta error number
	*/
	public $metaErrorNo = 0;
 
	/*
	* The ADOdb Meta error message
	*/
	public $metaErrorMessage;
 
	/*
	* The backtrace
	*/
	public $backTrace;
 
	/*
	* An error level that can be set if required
	* default INFO
	*/
	public $errorLevel = LOG_INFO;
}

Available Constants

If the object logging is used, then the following constants are available.

Constant Description
ADODB_OUTP Describes the name of the function to override the default. The global $ADODB_OUTP cannot be used in the instance
ADODB_OUTP_OBJECT Set to 1, tells the logging system to process the logging messages as objects, not strings
ADODB_OUTP_MIN_LEVEL (Default Value LOG_INFO). Any log messages with a level greater than specified are silently discarded.

Behavior of existing debug mssage

Many drivers use the logging feature to pass state information, for example the PDO driver shows information about the setting of driver attributes if debugging is enabled

foreach($options as $k=>$v) {
  if ($this->debug) {
    ADOconnection::outp('Setting attribute: ' . $k . ' to ' . $v);
  }
  $this->_connectionID->setAttribute($k,$v);
}

If object logging is enabled, each message will be automatically converted to a data logging object, with a logging level of LOG_INFO.

Change In Behavior Of ADG_OUTP

If the logging object is used then the first argument of the override function is an ADOdataLoggingObject

logMessage(ADOdataLoggingObject $obj, bool $newline=false) {}

Using Monolog For Logging Data

The PHP standard logging class Monolog can be used directly with the ADOdataLoggingObject. in this example, we use it to create a classic text log from the ADOdb output.

 
DEFINE('ADODB_OUTP','logMessage');
DEFINE('ADODB_OUTP_OBJECT',1);
 
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
 
require '/dev/github/vendor/autoload.php';
 
/*
* Tags log messages with ADOdb
*/
$loggingObject = new \Monolog\Logger('ADOdb');
$loggingObject->pushHandler(new StreamHandler('/var/logs/adodb.log', Logger::WARNING));
 
 
/**
* Override function for logging
*
* @param  ADOdataLoggingObject $obj
* @param  bool                 $newline
* @return void
*/
function logMessage(ADOdataLoggingObject $obj, bool $newline=false)
{
        global $loggingObject;
        $message = sprintf('%s: %s',$obj->metaErrorNo, $obj->errorMessage);
 
	$loggingObject->log(Logger::WARNING,$message);
 
}

Developer Considerations

When migrating a call to ADOConection::outp() from a string to an object, to improve the logging capabilities, you simply need to decide what level of logging the call is to be made at. example from the db2 driver, we are checking that a bind parameter is correctly set. Because the error handling does not go through the full debug_execute function, we can only pass a minimum amount of information

$ok = @db2_bind_param($stmtid, $ordinal, $psVar, DB2_PARAM_IN);
if (!$ok)
{
    $this->_errorMsg = @db2_stmt_errormsg();
    $this->_errorCode = @db2_stmt_error();
    if ($this->debug)
	ADOConnection::outp("Bind failed: " . $this->_errorMsg);
	return false;
}

We get an error something like “Bind failed: Invalid data type”. But if we convert to an object,

$ok = @db2_bind_param($stmtid, $ordinal, $psVar, DB2_PARAM_IN);
if (!$ok)
{
    $this->_errorMsg = @db2_stmt_errormsg();
    $this->_errorCode = @db2_stmt_error();
    if ($this->debug)
    {
        $obj = new ADOdataLoggingObject;
        $obj->errorNo = $this->_errorCode;
        $obj->errorMsg = $this->_errorMsg;
 
        $obj->metaErrorNo = $this->errorMsg($obj->errorNo);
        $obj->metaErrorMessage = $this->metaErrorMsg($obj->metaErrorNo);				
        $obj->backTrace        = _adodb_backtrace(true,9999,2,false);
        $obj->errorLevel       = LOG_ERR;
 
	ADOConnection::outp($obj);
	return false;
    }
}

produces a much more useful error which can also be filtered with ADODB_OUTP_MIN_LEVEL

v5/reference/logging.txt · Last modified: 2020/01/01 04:53 by mnewnham