phpundmysql.de

Apache Logs direkt in MySQL einlesen

Jeder Apache protokolliert standardmäßig Aufrufe der Webseite im so genannten Common Log Format (CLF). Die Logdaten finden sich zeilenweise in der Datei access.log. Gesteuert wird dies über einen Eintrag in der httpd.conf, der in etwa so aussieht:

LogFormat „%h %l %u %t \“%r\“ %>s %b \“%{Referer}i\“ \“%{User-Agent}i\““ combined

Jeder Teil der Zeichenkette – beginnend mit einem % und begrenzt durch ein Leerzeichen respektive das Zeichenkettenende – steht für eine geloggte Information. Das obige Standardformat enthält beispielsweise folgendes:

Abkürzung Bedeutung
%h Host, IP-Adresse des Aufrufs
%l Logname, Ergebnis von identd
%u User, Benutzername wenn eingeloggten
%t Time, Zeitpunkt der Anfrage
%r Request, gewünschte Anfrage-URL und HTTP-Methode (GET, POST…)
%>s Status, numerischer Antwortstatus, eigentlich %s, bei der Verwendung von %>s wird der finale Status zurück gegeben
%b Antwortlänge in Bytes ohne Header
%{header}i Ein beliebiger Header, z.B. User-Agent

Eine vollständige Auflistung der möglichen Bestandteile findet sich in der Apache Dokumentation.

Eine passende MySQL Tabelle gibt es natürlich nicht adhoc. Sie muss erst angelegt werden. Dies sieht dann in etwa so aus:

CREATE TABLE IF NOT EXISTS 'ACCESSLOG' (
'ip' varchar(50) NOT NULL,
'ident' varchar(250) NOT NULL,
'userid' varchar(100) NOT NULL,
'momentum' varchar(50) NOT NULL,
'request' varchar(2048) NOT NULL,
'statuscode' mediumint(4) NOT NULL,
'size' int(11) NOT NULL,
'referer' varchar(2048) NOT NULL,
'useragent' varchar(2048) NOT NULL
) ENGINE=InnoDB;

Zum Laden der Datei in die MySQL Tabelle bemühen wir die Kommandozeilentools des Datenbankclients. Nach dem Verbinden mit dem Datenbankserver reicht ein LOAD DATA INFILE aus. Allerdings sind ein paar Kniffe notwendig:

LOAD DATA LOCAL INFILE 'C:\\Software\\access_20130514.log'
INTO TABLE apache.accesslog
FIELDS TERMINATED BY ' '
OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY '\r\n'
(ip, ident, userid, @t1, @t2, request, statuscode, size, referer,
useragent)
SET momentum = CONCAT(@t1, ' ', @t2);

Die Logdatei wird dabei wie ein CSV behandelt, nur dass die einzelnen Felder nicht per Semikolon voneinander getrennt sind, sondern durch ein Sonderzeichen. Um Zeichenkette mit potentiellen Spaces korrekt zu behandeln, wird definiert, dass einzelne Felder im Zweifel durch doppelte Leerzeichen eingefasst sind, so beispielsweise der User Agent. Der letzte Stolperstein ist das Datum, das aus der Tages- und Zeitangabe besteht. Da diese durch ein Leerzeichen getrennt sind, würde das LOAD DATA diese eigentlich getrennt voneinander einlesen. Hier im Beispiel werden diese beiden Werte allerdings per CONCAT wieder aneinander gesetzt und gemeinsam eingelesen.

Mehr Arbeit bedarf es nicht. Es mag sein, dass der LOAD DATA INFILE Befehl einige Warnungen erzeugt, wenn in der Datei fehlende Werte auftreten. Dies zu beheben ist allerdings nicht schwer.

Kommentare sind deaktiviert.