Home arrow PHP arrow Page 8 - Logging With PHP

Big Brother Is Watching - PHP

Want to log script activity in your Web application, but haveno clue where to begin? Take our handy tour of PHP's logging functions,and find out how simple it really is.

TABLE OF CONTENTS:
  1. Logging With PHP
  2. The Bare Necessities
  3. Turning The Tables
  4. Turning Up The Heat
  5. Biting Into A PEAR
  6. Destination Unknown
  7. Artificial Intelligence
  8. Big Brother Is Watching
  9. Closing Time
By: icarus, (c) Melonfire
Rating: starstarstarstarstar / 53
November 27, 2002

print this article
SEARCH DEV SHED

TOOLS YOU CAN USE

advertisement
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.

<?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 ?>
Here's a snippet from the access log:

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)
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:

<?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); ?>
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.

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.

<?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); ?>
Here's a snippet from the audit table:

+---------------------+-------------+-------+ | 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 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,

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 | +---------------------+-------------+------------------+
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.

 
 
>>> More PHP Articles          >>> More By icarus, (c) Melonfire
 

blog comments powered by Disqus
escort Bursa Bursa escort Antalya eskort
   

PHP ARTICLES

- Hackers Compromise PHP Sites to Launch Attac...
- Red Hat, Zend Form OpenShift PaaS Alliance
- PHP IDE News
- BCD, Zend Extend PHP Partnership
- PHP FAQ Highlight
- PHP Creator Didn't Set Out to Create a Langu...
- PHP Trends Revealed in Zend Study
- PHP: Best Methods for Running Scheduled Jobs
- PHP Array Functions: array_change_key_case
- PHP array_combine Function
- PHP array_chunk Function
- PHP Closures as View Helpers: Lazy-Loading F...
- Using PHP Closures as View Helpers
- PHP File and Operating System Program Execut...
- PHP: Effects of Wrapping Code in Class Const...

Developer Shed Affiliates

 


Dev Shed Tutorial Topics: