Logging With PHP
Want to log script activity in your Web application, but have
no clue where to begin? Take our handy tour of PHP’s logging functions,
and find out how simple it really is.
I have to warn you not to be misled by the title of this article. It isn’t really about cutting down trees with PHP.
I know that PHP is the Swiss Army knife of Web scripting languages, but I don’t think its developers have come up with a way to have it reduce our tree cover (at least not yet). Rather, this article is about a different sort of logging – the sort which involves writing messages to files or devices on a regular basis, and using these messages to “do something useful”, be it generating a report or building an audit trail for activity tracking.
Over the next few pages, I’m going to take a quick look at the various mechanisms available to log script activity via PHP, demonstrating both built-in functions and add-on classes that allow you to add logging functionality to your applications. I’ll also spend some time on the PHP functions and configuration options related to logging, demonstrating how, for example, PHP errors can be sent to the Web server error log or emailed to an administrator when they are over a particular priority level.
My primary audience for this tutorial is the novice to intermediate PHP user – if you’re an advanced user, you probably already know enough about logging with PHP, and might prefer to skip the rest of this article in favour of more nutritious fare. Everyone else – keep reading!{mospagebreak title=The Bare Necessities} Logging data to a file in PHP can be as simple or as complex as you want to make it. Break it down, though, and it all comes down to these three simple lines of code:
1. Open the target file (or create it if it doesn’t already exist);
2. Append your data to the end of the file;
3. Close the file.
You can encapsulate this as a function,
In order to illustrate this, consider the following example of an SQL table used to store log messages:
Another option might be to send log messages to a specified email address via PHP’s mail() function – for example, alerting a sysop whenever a script encounters errors. Here’s an example:
0 – send the message to the system logger (“syslogd” on *NIX, and the Event Log on Windows NT);
1 – send the message to the specified email address;
3 – send the message to the specified file;
Here’s a trivial example which demonstrates how this works:
Like the error_log() function, the PEAR Log class allows logging to a variety of different destinations – system logger, text file, email address, database and even MCAL. Here’s an example demonstrating basic usage:
Consider the following example, which demonstrates:
On *NIX systems, setting the “error_log” variable to the special value “syslog” logs all errors via the standard “syslog” daemon.{mospagebreak title=Big Brother Is Watching} Finally, let’s wrap things up with a couple of examples that show how the various techniques demonstrated above can be used to build logs and audit trails for a Web application.
In the first example, every time a Web page is displayed, a log entry is made in an “access.log” file. This log entry is a comma-separated list of values containing the URL requested, the client browser identification string, and a timestamp.
Consider this next example, which provides an API for adding, editing and deleting users to (from) a Web application. Each time the user database is edited, a separate audit() process tracks the change, logging both the nature of the change and information about the user initiating the change. This log data is stored in a separate SQL table, from where it can be retrieved for statistical reporting, user activity monitoring or debugging.
I hope you enjoyed reading this article as much as I enjoyed writing it. If you’d like to know more about the topics discussed in the previous pages, here are some links you should bookmark:
PHP file manipulation functions, at http://www.php.net/manual/en/ref.filesystem.php
PHP mail functions, at http://www.php.net/manual/en/ref.mail.php
PHP MySQL functions, at http://www.php.net/manual/en/ref.mysql.php
PHP error logging functions, at http://www.php.net/manual/en/ref.errorfunc.php
The PHP Log class, at http://pear.php.net/package-info.php?package=Log
PEAR, at http://pear.php.net
Till next time…stay healthy!
Note: All examples in this article have been tested on Linux/i586 with PHP 4.2.3. Examples are illustrative only, and are not meant for a production environment. Melonfire provides no warranties or support for the source code described in this article. YMMV!
I have to warn you not to be misled by the title of this article. It isn’t really about cutting down trees with PHP.
I know that PHP is the Swiss Army knife of Web scripting languages, but I don’t think its developers have come up with a way to have it reduce our tree cover (at least not yet). Rather, this article is about a different sort of logging – the sort which involves writing messages to files or devices on a regular basis, and using these messages to “do something useful”, be it generating a report or building an audit trail for activity tracking.
Over the next few pages, I’m going to take a quick look at the various mechanisms available to log script activity via PHP, demonstrating both built-in functions and add-on classes that allow you to add logging functionality to your applications. I’ll also spend some time on the PHP functions and configuration options related to logging, demonstrating how, for example, PHP errors can be sent to the Web server error log or emailed to an administrator when they are over a particular priority level.
My primary audience for this tutorial is the novice to intermediate PHP user – if you’re an advanced user, you probably already know enough about logging with PHP, and might prefer to skip the rest of this article in favour of more nutritious fare. Everyone else – keep reading!{mospagebreak title=The Bare Necessities} Logging data to a file in PHP can be as simple or as complex as you want to make it. Break it down, though, and it all comes down to these three simple lines of code:
Fundamentally, logging data to a file consists of three steps:
<?php // open file $fd = fopen($filename, “a”); // write string fwrite($fd, $str . “n”); // close file fclose($fd); ?>
1. Open the target file (or create it if it doesn’t already exist);
2. Append your data to the end of the file;
3. Close the file.
You can encapsulate this as a function,
and then use it liberally within your code as and when required.
<?php function logToFile($filename, $msg) { // open file $fd = fopen($filename, “a”); // write string fwrite($fd, $msg . “n”); // close file fclose($fd); } ?>
You can make the function a little more professional by having it automatically append the date and time of the log message to the log file as well:
<?php function logToFile($filename, $msg) { // open file $fd = fopen($filename, “a”); // write string fwrite($fd, $msg . “n”); // close file fclose($fd); } $v = “Mary had a little lamb”; if (!is_numeric($v)) { logToFile(“my.log”, “Non-numeric variable encountered”); } $a = array(“chocolate”, “strawberry”, “peach”); if (!in_array(‘fish’, $a)) { logToFile(“my.log”, “No fish available”); } $conn = @mysql_connect(“localhost”, “joe”, “pass”); if (!$conn) { logToFile(“my.log”, “Could not connect to database”); die(“Could not connect to database”); } ?>
Here’s an example of the output:
<?php function logToFile($filename, $msg) { // open file $fd = fopen($filename, “a”); // append date/time to message $str = “[" . date("Y/m/d h:i:s", mktime()) . "] ” . $msg; // write string fwrite($fd, $str . “n”); // close file fclose($fd); } ?>
{mospagebreak title=Turning The Tables} While the most common destination for log data is a text file, it’s quite possible that you might want to send your log messages elsewhere as well. A frequently-used alternative to a text file, especially when the number of writes isn’t too high, is an SQL database, where log messages are appended as records to the end of a table.
[2002/11/25 06:02:42] Non-numeric variable encountered [2002/11/25 06:02:42] No fish available [2002/11/25 06:02:43] Could not connect to database
In order to illustrate this, consider the following example of an SQL table used to store log messages:
And here’s the rewritten logToDB() function, this time built around PHP’s MySQL database functions and the table above:
CREATE TABLE `log` ( `date` TIMESTAMP NOT NULL, `type` TINYINT NOT NULL, `msg` VARCHAR(255) NOT NULL );
If you don’t estimate seeing a very large number of writes, using a database to store logs can offer significant advantages over a regular file, purely from the point of view of easier retrieval and sorting. Storing log messages in this manner makes it possible to easily retrieve ordered subsets of the log data, either by date or message type.
function logToDB($msg, $type) { // open connection to database $connection = mysql_connect(“localhost”, “joe”, “pass”) or die (“Unable to connect!”); mysql_select_db(“logdb”) or die (“Unable to select database!”); // formulate and execute query $query = “INSERT INTO log (date, type, msg) VALUES(NOW(), ‘$type’, ‘$msg’)”; mysql_query($query) or die (“Error in query: $query. ” . mysql_error()); // close connection mysql_close($connection); } $a = array(“chocolate”, “strawberry”, “peach”); if (!in_array(‘fish’, $a)) { logToDB(“No fish available”, 14); }
Another option might be to send log messages to a specified email address via PHP’s mail() function – for example, alerting a sysop whenever a script encounters errors. Here’s an example:
{mospagebreak title=Turning Up The Heat} If the thought of rolling your own code doesn’t appeal to you, you can also use PHP’s built-in error_log() function, which logs data both to a file and elsewhere. The error_log() function needs a minimum of two arguments: the error message to be logged, and an integer indicating where the message should be sent. There are three possible integer values in PHP 4.x:
function logToMail($msg, $address) { // append date/time to message $str = “[" . date("Y/m/d h:i:s", mktime()) . "] ” . $msg; mail($address, “Log message”, $str); } $conn = @mysql_connect(“localhost”, “joe”, “pass”); if (!$conn) { logToMail(“Could not connect to database”, “webmaster@my.domain.name.com”); }
0 – send the message to the system logger (“syslogd” on *NIX, and the Event Log on Windows NT);
1 – send the message to the specified email address;
3 – send the message to the specified file;
Here’s a trivial example which demonstrates how this works:
Now, if you look at the system log file after running the script, you’ll see something like this:
<?php // set a variable $temp = 101.6; // test it and log an error // this will only work if // you have “log_errors” and “error_log” set in your php.ini file if ($temp > 98.6) { error_log(“Body temperature above normal.”, 0); } ?>
You can also write the error message to a file,
[28-Feb-2002 15:50:49] Body temperature above normal.
or send it out as email.
<?php // set a variable $temp = 101.6; // test it and log an error if ($temp > 98.6) { error_log(“Body temperature above normal.”, 3, “a.out”); } ?>
It’s possible to combine this error logging facility with a custom error handler to ensure that all script errors get logged to a file. Here’s an example which demonstrates this:
<?php // set a variable $temp = 101.6; // test it and log an error if ($temp > 98.6) { error_log(“Body temperature above normal.”, 1, “administrator@this.body.com”); } ?>
And here’s the output that gets logged to the system log file:
<?php // custom handler function eh($type, $msg, $file, $line) { // log all errors error_log(“$msg (error type $type)”, 0); // if fatal error, die() if ($type == E_USER_ERROR) { die($msg); } } // report all errors error_reporting(E_ALL); // define custom handler set_error_handler(“eh”); // let’s now write some bad code // this will trigger a warning, since the file doesn’t exist include(“common.php”); ?>
{mospagebreak title=Biting Into A PEAR} As if all that wasn’t enough, PHP offers one more alternative – a special Log class that comes courtesy of PEAR, the PHP Extension and Application Repository (http://pear.php.net). In case you didn’t know, PEAR is an online repository of free PHP software, including classes and modules for everything from data archiving to XML parsing. This Log class is maintained by Jon Parise, and the latest version can be downloaded from http://pear.php.net/package-info.php?package=Log
[28-Feb-2002 16:15:06] Failed opening ‘common.php’ for inclusion (include_path=’.;’) (error type 2)
Like the error_log() function, the PEAR Log class allows logging to a variety of different destinations – system logger, text file, email address, database and even MCAL. Here’s an example demonstrating basic usage:
The first step here is to include() the Log class:
<?php // include class include(“Log.php”); // create Log object $l = &Log::singleton(“file”, “my.log”); // test it $v = “Mary had a little lamb”; if (!is_numeric($v)) { $l->log(“Non-numeric variable encountered”, PEAR_LOG_WARNING); } $a = array(“chocolate”, “strawberry”, “peach”); if (!in_array(‘fish’, $a)) { $l->log(“No fish available”, PEAR_LOG_ERR); } $conn = @mysql_connect(“localhost”, “joe”, “pass”); if (!$conn) { $l->log(“Could not connect to database”, PEAR_LOG_CRIT); } ?>
Once that’s done, a new Log object can be created. This object constructor requires, as its first parameter, a string indicating the kind of log to open – current valid values are ‘console’, ‘syslog’, ‘sql’, ‘file’, and ‘mcal’. Depending on the log type, additional data may be provided – the name of the file to use in case of a file logger, for example.
// include class include(“Log.php”);
The Log class internally defines eight priority levels for logging – here’s the list, culled directly from the source code of the class:
// create Log object $l = &Log::singleton(“file”, “my.log”);
Each log message that you send to the logger can be flagged with a specific priority, and the logger can be set up to log only those messages matching or exceeding a specific priority level (by default, all messages are logged). This can be clearly seen from the test code below, in which each message to the logger includes a priority level:
$priorities = array( PEAR_LOG_EMERG => ‘emergency’, PEAR_LOG_ALERT => ‘alert’, PEAR_LOG_CRIT => ‘critical’, PEAR_LOG_ERR => ‘error’, PEAR_LOG_WARNING => ‘warning’, PEAR_LOG_NOTICE => ‘notice’, PEAR_LOG_INFO => ‘info’, PEAR_LOG_DEBUG => ‘debug’ );
Here’s what the log file looks like:
$v = “Mary had a little lamb”; if (!is_numeric($v)) { $l->log(“Non-numeric variable encountered”, PEAR_LOG_WARNING); } $a = array(“chocolate”, “strawberry”, “peach”); if (!in_array(‘fish’, $a)) { $l->log(“No fish available”, PEAR_LOG_ERR); } $conn = @mysql_connect(“localhost”, “joe”, “pass”); if (!$conn) { $l->log(“Could not connect to database”, PEAR_LOG_CRIT); }
If you’d like to tell the logger to only log messages above a certain priority level – for example, critical and above – this priority level should be specified as the fifth argument to the object constructor. Consider the following revision of the previous example:
Nov 26 06:47:15 [warning] Non-numeric variable encountered Nov 26 06:47:15 [error] No fish available Nov 26 06:47:17 [critical] Could not connect to database
In this case, only messages flagged as PEAR_LOG_ERR and above will be written to the specified log file.{mospagebreak title=Destination Unknown} The Log class also supports sending log messages to the console, the system logger, an SQL database or a user-specified email address. Take a look:
<?php // include class include(“Log.php”); // create Log object $l = &Log::singleton(“file”, “my.log”, NULL, array(), PEAR_LOG_ERR); // test it $v = “Mary had a little lamb”; if (!is_numeric($v)) { $l->log(“Non-numeric variable encountered”, PEAR_LOG_WARNING); } $a = array(“chocolate”, “strawberry”, “peach”); if (!in_array(‘fish’, $a)) { $l->log(“No fish available”, PEAR_LOG_ERR); } $conn = @mysql_connect(“localhost”, “joe”, “pass”); if (!$conn) { $l->log(“Could not connect to database”, PEAR_LOG_CRIT); } ?>
In this case, log messages are directed to the text console (if you’re running this script via a Web server, the console is the browser window). Here’s the output:
<?php // include class include(“Log.php”); // create Log object $l = &Log::singleton(“console”); // test it $v = “Mary had a little lamb”; if (!is_numeric($v)) { $l->log(“Non-numeric variable encountered”, PEAR_LOG_WARNING); } $a = array(“chocolate”, “strawberry”, “peach”); if (!in_array(‘fish’, $a)) { $l->log(“No fish available”, PEAR_LOG_ERR); } $conn = @mysql_connect(“localhost”, “joe”, “pass”); if (!$conn) { $l->log(“Could not connect to database”, PEAR_LOG_CRIT); } ?>
Messages can also be sent to an SQL database,
Nov 26 22:05:25 [warning] Non-numeric variable encountered Nov 26 22:05:25 [error] No fish available Nov 26 22:05:27 [critical] Could not connect to database
which can then be queried to retrieve subsets of the log messages, sorted by date or priority level.
<?php // include class include(“Log.php”); // create Log object // second argument is table name // fourth argument is PHP::DB compatible DSN for database access $l = &Log::singleton(“sql”, “log_table”, “”, array(‘dsn’ => ‘mysql://joe:pass@localhost/test’)); // test it $v = “Mary had a little lamb”; if (!is_numeric($v)) { $l->log(“Non-numeric variable encountered”, PEAR_LOG_WARNING); } $a = array(“chocolate”, “strawberry”, “peach”); if (!in_array(‘fish’, $a)) { $l->log(“No fish available”, PEAR_LOG_ERR); } $conn = @mysql_connect(“localhost”, “joe”, “pass”); if (!$conn) { $l->log(“Could not connect to database”, PEAR_LOG_CRIT); } ?>
Finally, log messages can also be directed to a specified email address, as in the following example:
mysql> SELECT * FROM log_table WHERE priority >= 4; +—————-+——-+———-+———————————-+ | logtime | ident | priority | message | +—————-+——-+———-+———————————-+ | 20021126074936 | | 4 | Non-numeric variable encountered | | 20021126074936 | | 4 | Non-numeric variable encountered | | 20021126074937 | | 4 | Non-numeric variable encountered | +—————-+——-+———-+———————————-+ 3 rows in set (0.05 sec)
You can customize the mail message by adding an array containing a custom From: and Subject: line to the object constructor, as below:
<?php // include class include(“Log.php”); // create Log object $l = &Log::singleton(“mail”, “admin@host.com”); // test it $v = “Mary had a little lamb”; if (!is_numeric($v)) { $l->log(“Non-numeric variable encountered”, PEAR_LOG_WARNING); } $a = array(“chocolate”, “strawberry”, “peach”); if (!in_array(‘fish’, $a)) { $l->log(“No fish available”, PEAR_LOG_ERR); } $conn = @mysql_connect(“localhost”, “joe”, “pass”); if (!$conn) { $l->log(“Could not connect to database”, PEAR_LOG_CRIT); } ?>
{mospagebreak title=Artificial Intelligence} You can also configure PHP to automatically log all script errors to a specific file via the special “log_errors” configuration directive in “php.ini”. This directive, when set to true, logs all PHP errors to either a user-specified log file (the value of this file must be specified in the “error_log” configuration directive, also set via “php.ini”), or to the Web server error log if no log file is specified.
<?php // include class include(“Log.php”); // create Log object $l = &Log::singleton(“mail”, “admin@host.com”, NULL, array(‘from’ => ‘L. Ogger’, ‘subject’ => ‘Log message’)); // test it $v = “Mary had a little lamb”; if (!is_numeric($v)) { $l->log(“Non-numeric variable encountered”, PEAR_LOG_WARNING); } $a = array(“chocolate”, “strawberry”, “peach”); if (!in_array(‘fish’, $a)) { $l->log(“No fish available”, PEAR_LOG_ERR); } $conn = @mysql_connect(“localhost”, “joe”, “pass”); if (!$conn) { $l->log(“Could not connect to database”, PEAR_LOG_CRIT); } ?>
Consider the following example, which demonstrates:
In this case, I’m manually instantiating an error by attempting to include a file which does not exist. Obviously, PHP will barf and display an error screen containing the following:
<?php // turn on automatic error logging ini_set(‘log_errors’, true); // include non-existent file include(“non.existent.file.php”); ?>
The same error also appears in the server’s error log:
Warning: Failed opening ‘non.existent.file.php’ for inclusion (include_path=’.;/usr/local/php/includes’) in error.php on line 10
You can turn off PHP error display, and only have the error message appear in the log file, by setting the “display_errors” variable (also accessible via “php.ini”) to false. Consider the following variant of the previous example, which demonstrates:
[Tue Nov 26 12:49:31 2002] [error] PHP Warning: Failed opening ‘non.existent.file.php’ for inclusion (include_path=’.;/usr/local/php/includes’) in error.php on line 10
In this case, though an error takes place, it is never displayed to the user, but merely gets logged to the server’s error log.
<?php // turn on automatic error logging ini_set(‘log_errors’, true); // turn off error display ini_set(‘display_errors’, false); // include non-existent file include(“non.existent.file.php”); ?>
On *NIX systems, setting the “error_log” variable to the special value “syslog” logs all errors via the standard “syslog” daemon.{mospagebreak title=Big Brother Is Watching} Finally, let’s wrap things up with a couple of examples that show how the various techniques demonstrated above can be used to build logs and audit trails for a Web application.
In the first example, every time a Web page is displayed, a log entry is made in an “access.log” file. This log entry is a comma-separated list of values containing the URL requested, the client browser identification string, and a timestamp.
Here’s a snippet from the access log:
<?php // create log string $str = date(“Y/m/d h:i:s”, mktime()) . “,” . $_SERVER['REQUEST_URI'] . “,” . $_SERVER['HTTP_USER_AGENT'] . “n”; // write to file error_log($str, 3, “access.log”); // rest of page here ?>
Since this data is in a structured format, it can easily be analyzed and a “hit count” created for each URL in the file. This next script does exactly that:
2002/11/26 09:07:38,/alpha.php,Mozilla/4.0 (compatible; MSIE 5.0; Windows 95) 2002/11/26 09:07:38,/alpha.php,Mozilla/4.0 (compatible; MSIE 5.0; Windows 95) 2002/11/26 09:10:31,/home/hello.php,Mozilla/4.0 (compatible; MSIE 5.0; Windows 95) 2002/11/26 09:17:38,/index.php,Mozilla/4.0 (compatible; MSIE 5.0; Windows 95) 2002/11/26 09:17:38,/base/index.php,Mozilla/4.0 (compatible; MSIE 5.0; Windows 95)
This script parses the “access.log” file, and creates a PHP associative array whose keys correspond to the URLs found in the file. The value associated with each key is an integer indicating the number of appearances the URL makes in the file. Once the entire file has been parsed, the $urlStats array contains a list of all the unique URLs in the access log, together with the number of times each has appeared. This data can then be used to generate a report of the most frequently-accessed URLs.
<?php // create array to hold unique URLs $urlStats = array(); // read access log $lines = file(“access.log”); // iterate through access log foreach ($lines as $l) { $data = explode(“,”, $l); $ts = $data[0]; $url = $data[1]; $agent = $data[2]; // check to see if URL exists in array // if it does, increment incidence count // if it does not, create a new key with incidence count 1 if ($urlStats[$url]) { $urlStats[$url]++; } else { $urlStats[$url] = 1; } } // print list of unique URLs with count print_r($urlStats); ?>
Consider this next example, which provides an API for adding, editing and deleting users to (from) a Web application. Each time the user database is edited, a separate audit() process tracks the change, logging both the nature of the change and information about the user initiating the change. This log data is stored in a separate SQL table, from where it can be retrieved for statistical reporting, user activity monitoring or debugging.
Here’s a snippet from the audit table:
<?php // assume that administrator has logged in to system to perform user-administration tasks // admin username is stored in a session variable by default // this is useful for audit purposes session_start(); $_SESSION['LOGGED_IN_USER'] = “john”; // add a new user function addUser($user, $pass, $perms) { // open connection to database $connection = mysql_connect(“localhost”, “joe”, “pass”) or die (“Unable to connect!”); mysql_select_db(“myapp”) or die (“Unable to select database!”); // formulate and execute query $query = “INSERT INTO users (user, pass, perms) VALUES(‘$user’, ‘$pass’, ‘$perms’)”; mysql_query($query) or die (“Error in query: $query. ” . mysql_error()); // log activity to audit database audit(“ADD_USER”, $_SESSION['LOGGED_IN_USER'], “$user:$pass:$perms”, addslashes($query)); // close connection mysql_close($connection); } // edit an existing user function updateUser($user, $pass, $perms) { $connection = mysql_connect(“localhost”, “joe”, “pass”) or die (“Unable to connect!”); mysql_select_db(“myapp”) or die (“Unable to select database!”); // formulate and execute query $query = “UPDATE users SET pass = ‘$pass’, perms = ‘$perms’ WHERE user = ‘$user’”; mysql_query($query) or die (“Error in query: $query. ” . mysql_error()); // log activity to audit database audit(“UPDATE_USER”, $_SESSION['LOGGED_IN_USER'], “$user:$pass:$perms”, addslashes($query)); // close connection mysql_close($connection); } // delete an existing user function deleteUser($user) { $connection = mysql_connect(“localhost”, “joe”, “pass”) or die (“Unable to connect!”); mysql_select_db(“myapp”) or die (“Unable to select database!”); // formulate and execute query $query = “DELETE FROM users WHERE user = ‘$user’”; mysql_query($query) or die (“Error in query: $query. ” . mysql_error()); // log activity to audit database audit(“DELETE_USER”, $_SESSION['LOGGED_IN_USER'], “$user”, addslashes($query)); // close connection mysql_close($connection); } // generic audit function // logs all activity to a database function audit($op, $owner, $args, $msg) { $connection = mysql_connect(“localhost”, “root”, “pass”) or die (“Unable to connect!”); mysql_select_db(“trails”) or die (“Unable to select database!”); // formulate and execute query $query = “INSERT INTO audit (timestamp, op, owner, args, msg) VALUES (NOW(), ‘$op’, ‘$owner’, ‘$args’, ‘$msg’)”; mysql_query($query) or die (“Error in query: $query. ” . mysql_error()); } addUser(“joe”, “joe”, 3); addUser(“sarahh”, “bsdfg49″, 1); updateUser(“joe”, “joe”, 4); deleteUser(“sarahh”); addUser(“sarah”, “bsdfg49″, 1); ?>
This audit table can then be queried to obtain detailed information on the activities performed by the various users, sorted by time or type of activity. For example,
+———————+————-+——-+ | timestamp | op | owner | +———————+————-+——-+ | 2002-11-26 08:28:05 | UPDATE_USER | john | | 2002-11-26 08:28:05 | DELETE_USER | john | | 2002-11-26 08:28:05 | ADD_USER | john | | 2002-11-26 08:33:14 | ADD_USER | joe | +———————+————-+——-+
This is a somewhat trivial example, but it serves to demonstrate the concept of logging activity and using those logs to build an audit trail. While you can make this as complex as you want, tracking everything from user clicks to form input in order to gain a better understanding of how users navigate through and use your application, remember that every addition to the log affects the overall performance of your application; log too much data and your application will suffocate and die.{mospagebreak title=Closing Time} And that’s about it for the moment. In this article, I offered you a brief overview of logging in PHP, demonstrating how you can use built-in functions, off-the-shelf libraries or your own code to easily and efficiently create logs of the activity taking place in your application. I demonstrated logging to a file, to a database, to an email address and to the console, and wrapped things up with a couple of simple examples that demonstrated how logs could be built and analyzed in a real-world application.
mysql> SELECT timestamp, op, args FROM trails WHERE timestamp >= mysql> 2002-11-26 AND owner = ‘joe’; +———————+————-+——————+ | timestamp | op | args | +———————+————-+——————+ | 2002-11-26 08:33:29 | ADD_USER | joe:joe:3 | | 2002-11-26 08:33:29 | ADD_USER | sarahh:bsdfg49:1 | | 2002-11-26 08:33:29 | UPDATE_USER | joe:joe:4 | | 2002-11-26 08:33:29 | DELETE_USER | sarahh | | 2002-11-26 08:33:29 | ADD_USER | sarah:bsdfg49:1 | +———————+————-+——————+
I hope you enjoyed reading this article as much as I enjoyed writing it. If you’d like to know more about the topics discussed in the previous pages, here are some links you should bookmark:
PHP file manipulation functions, at http://www.php.net/manual/en/ref.filesystem.php
PHP mail functions, at http://www.php.net/manual/en/ref.mail.php
PHP MySQL functions, at http://www.php.net/manual/en/ref.mysql.php
PHP error logging functions, at http://www.php.net/manual/en/ref.errorfunc.php
The PHP Log class, at http://pear.php.net/package-info.php?package=Log
PEAR, at http://pear.php.net
Till next time…stay healthy!
Note: All examples in this article have been tested on Linux/i586 with PHP 4.2.3. Examples are illustrative only, and are not meant for a production environment. Melonfire provides no warranties or support for the source code described in this article. YMMV!
沒有留言:
張貼留言