<?php
/***
This example script performs the following :
1) Take the log file data/example.log, which contains well-formatted entries such as :
2016-01-01 13:20:01 httptracking[11776] Processing buffered http requests...
2016-01-01 13:20:01 httptracking[11776] 0 http requests processed
2016-01-01 13:25:02 httptracking[11908] Processing buffered http requests...
2016-01-01 13:25:02 httptracking[11908] 2 http requests processed
2016-01-01 13:30:01 httptracking[12043] Processing buffered http requests...
2016-01-01 13:30:01 httptracking[12043] 0 http requests processed
The various fields of this log file, which resembles Apache or ssh auth logs, are :
- A timestamp
- A process name ("httptracking")
- A process id, within square brackets
- A message
The variable-length parts of this table are :
- the process name
- the message part
2.1) Create a first table, httptracking_1, which will hold the various parts of the log file
2.2) Create a second table, httptracking_2, where the "process" and "message" fields have
been replaced with an id in a string store table
3) Compare the results in size and number of records
***/
require ( 'DbStringStore.php' ) ;
// Customize here the access parameters to your local database
define ( MYSQL_HOST , 'localhost' ) ;
define ( MYSQL_USER , 'root' ) ;
define ( MYSQL_PASSWORD , '' ) ;
define ( MYSQL_DATABASE , 'phpclasses' ) ;
define ( LOGFILE , 'data/example.log' ) ;
// String store entry types - one for the process name, one for the message part
define ( STRING_STORE_PROCESS , 0 ) ;
define ( STRING_STORE_MESSAGE , 1 ) ;
// Connect to your local database
$dblink = mysqli_connect ( MYSQL_HOST, MYSQL_USER, MYSQL_PASSWORD ) ;
// Uncomment this if you want to create a brand new database for running this test
/***
$query = "CREATE DATABASE " . MYSQL_DATABASE . " DEFAULT CHARSET latin1" ;
mysqli_query ( $dblink, $query ) ;
***/
// Select our test database
mysqli_select_db ( $dblink, MYSQL_DATABASE ) ;
// Create the version with inline variable-length fields
create_standard_version ( $dblink, LOGFILE ) ;
// Create the version with a string store
create_string_store_version ( $dblink, LOGFILE, 'httptracking_string_store' ) ;
/********************************************************************************
*
* Helper functions.
*
********************************************************************************/
// Create the version with variable-length data stored in the same table
function create_standard_version ( $dblink, $logfile )
{
// Recreate the httptracking_1 table if it already exists
mysqli_query ( $dblink, "DROP TABLE IF EXISTS httptracking_1" ) ;
$query = "
CREATE TABLE httptracking_1
(
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
timestamp DATETIME NOT NULL,
process VARCHAR(32) NOT NULL DEFAULT '',
process_id INT NOT NULL DEFAULT 0,
message VARCHAR(1024) NOT NULL DEFAULT '',
PRIMARY KEY ( id ),
KEY ( timestamp )
) ENGINE = MyISAM ;
" ;
mysqli_query ( $dblink, $query ) ;
// Read the logfile, split each record parts and insert a new row in the table
$fp = fopen ( $logfile, "r" ) ;
while ( ( $line = fgets ( $fp ) ) !== false )
{
list ( $timestamp, $process, $pid, $message ) = get_log_parts ( $line ) ;
$process = mysqli_escape_string ( $dblink, $process ) ;
$message = mysqli_escape_string ( $dblink, $message ) ;
$query = "
INSERT INTO httptracking_1
SET
timestamp = '$timestamp',
process = '$process',
process_id = $pid,
message = '$message'
" ;
mysqli_query ( $dblink, $query ) ;
}
fclose ( $fp ) ;
}
// Create the version with variable-length data stored in the same table
function create_string_store_version ( $dblink, $logfile, $store_name )
{
// Recreate the httptracking_2 table if it already exists
mysqli_query ( $dblink, "DROP TABLE IF EXISTS httptracking_2" ) ;
$query = "
CREATE TABLE httptracking_2
(
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
timestamp DATETIME NOT NULL,
process_ssid BIGINT UNSIGNED NOT NULL DEFAULT 0,
process_id INT NOT NULL DEFAULT 0,
message_ssid BIGINT UNSIGNED NOT NULL DEFAULT 0,
PRIMARY KEY ( id ),
KEY ( timestamp )
) ENGINE = MyISAM ;
" ;
mysqli_query ( $dblink, $query ) ;
// Create the string store (or instanciate it if it already exists)
// Keep the default size of 1024 characters and don't index the string value part
$store = new DbStringStore ( $dblink, $store_name ) ;
// Read the logfile, split each record parts and insert a new row in the table
$fp = fopen ( $logfile, "r" ) ;
while ( ( $line = fgets ( $fp ) ) !== false )
{
list ( $timestamp, $process, $pid, $message ) = get_log_parts ( $line ) ;
$process_id = $store -> Insert ( STRING_STORE_PROCESS, $process ) ;
$message_id = $store -> Insert ( STRING_STORE_MESSAGE, $message ) ;
$query = "
INSERT INTO httptracking_2
SET
timestamp = '$timestamp',
process_ssid = $process_id,
process_id = $pid,
message_ssid = $message_id
" ;
mysqli_query ( $dblink, $query ) ;
}
fclose ( $fp ) ;
}
// Get parts from one log entry, ie : timestamp, process name, process id (within square brackets) and message
function get_log_parts ( $line )
{
$line = trim ( $line ) ;
$timestamp = substr ( $line, 0, 19 ) ;
$remainder = substr ( $line, 20 ) ;
$re = '/
(?P<process> [^\[]+)
\[
(?P<pid> [^\]]+)
\]
\s*
(?P<message> .*)
/imsx' ;
preg_match ( $re, $remainder, $match ) ;
return ( [ $timestamp, $match [ 'process' ], $match [ 'pid' ], $match [ 'message' ] ] ) ;
}
|