Dies und das

Apache-Access-Log: Auswertung mittels PHP

Worum geht es (In einem Satz erklärt)

Mit diesem kleinen PHP-Skript kann man das Access-Log-File (Log-Datei des Apache-Servers) übersichtlich auswerten

Log-File-Auswertung etwas genauer erklärt

Ein Apache-Server ist eine Server-Software (also ein Programm meist auf Unix-/Linux-Basis) auf einem Internet-Rechner, derverschiedene Dienste zur Datei-Auslieferung im Internet bietet. Dazu gehören z.B.: dynamisch erstellte Web-Sites (mittels PHP, Perl, ...) aber auch statische Dateien, wie Bilder, JavaScript-Dateien und vieles mehr. Wie eigentlich jeder Server werden alle erdenklichen Aktionen protokolliert (geloggt). Das geschieht meist in Dateien. Jede Server-Aktion erzeugt also einen Log-Datei-Eintrag (also eine Art Log-Buch als Datei). Diese Seite bezieht sich auf das Access-Log (Access=Zugriff). Kurz: wann wird welche Datei vom Server ausgeliefert

Bestandteile einer Access-Log-Datei

Jeder Eintrag einer Access-Log-Datei besteht aus einer Zeile. Hier ein Beispiel (die Zeile ist aus Platzgründen mit "" getrennt):

www.andre-jochim.de 127.0.0.1 - - [15/Jul/2010:03:25:21 +0000]
"GET /media/andre-jochim2.jpg HTTP/1.0" 200
(37963 "http://www.example.de/referrer.htm" "Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.2.6)
Gecko/20100625 Firefox/3.6.6 GTB6 (.NET CLR 3.5.30729)"

Und das sind die einzelnen Bestandteile:

  • Domain
  • IP-Nummer
  • Datum
  • Uhrzeit
  • Zeitzone
  • Abfrage-Methode (meist GET oder POST)
  • aufgerufende Datei
  • Header der ausgelieferten Datei
  • Status (200 heißt OK)
  • Größe der Datei
  • Referer (von welcher Website kam die Anfrage)
  • Browser (welcher Browser führte die Abfrage durch)

PHP-Skript zur Auswertung dieser Log-Datei

Hier eine ganz einfache Anwendung mit der Skript-Sprache PHP

Hier eine ganz einfache Anwendung mit der Skript-Sprache PHP
Dieses Skript ist weitest gehend Ressourcen schonend (der Speicher wird nicht überladen). Dennoch ist nicht auszuschließen, dass sehr große Log-Dateien Probleme machen.

Man kann bestimmte Dateien herausfiltern (wenn man sich z.B. nicht für HTML-Dateien interessiert).
Das Skript erstellt eine Datei mit folgenden Informationen:

  • wie häufig kommt jeder Datei-Typ in der Log-Datei vor
  • wie häufig kommt jede einzelne Datei in der Log-Datei vor

<?php

// Ausführungs-Zeit und Speicher hochsetzen, damit das Skript nicht zu früh abbricht

set_time_limit(999999999);
ini_set("memory_limit", "128M");

// Log-Datei:
$access_log = "andre_jochim_de.access.log";
$access_log_result = "{$access_log}.result.txt";

$fp = fopen($access_log, "r");
$result = array();
$cnt_types = array();
$cnt_files = array();

$cnt = 0;
// Datei zeilenweise auslesen:
while($buffer = fgets($fp, 1024)){

  $cnt++;
 
  // nur GET-Anfragen (Requests) verarbeiten:
  $expl = explode('"GET ', $buffer);
 
  // den hinteren Rest abspalten:
  $expl2 = explode(" HTTP/", $expl[1]);
 
  // Datei-Endungsbestimmung (dafür alle Get-Parameter entfernen):
  $expl3 = explode("?", $expl2[0]);
  $expl4 = explode(".", $expl3[0]);
 
  // Dateien ohne Endung auch zählen:
  if (count($expl4) == 1){
  $cnt_types["##without##"]++;
  $expl3[0] .= "##without##";
  }
 
  // Dateien mit Endung:
  else{
  $extension = array_pop($expl4);
  ### Datei-Typen zählen (auch htm, php oder ohne)
  $cnt_types[$extension]++;
 
  // unerwünschte Typen filtern:
  if (in_array($extension, array("html", "php", "htm"))) continue;
  }
 
  // das eigentliche Zählen der einzelnen Dateien (wenn Parameter dran, dann wieder ranhängen):
  $params = isset($expl3[1]) ? "?".$expl3[1] : "";
  $cnt_files[ $expl3[0].$params ]++;
 
 
  // für Tests - falls man nach 10 Zeilen aufhören möchte:
  #if ($cnt > 10){
  # dump("Ende weil Counter erreicht");
  # break;
  #}

}

fclose($fp);

// Absteigende Sortierung der Anzahlen (der Datei-Typen + der Dateien selbst):
arsort($cnt_types);
arsort($cnt_files);

// Bei Bedarf Ausgabe der Anzahlen:
#dump($cnt_types);
#dump($cnt_files);


// Schreiben der Anzahlen in eine Auswertungs-Datei:
$fp_write = fopen($access_log_result, "w");
foreach($cnt_types as $cnt_type=>$amount){
  fwrite($fp_write, $amount." -- ". $cnt_type."\n");
}

fwrite($fp_write, "\n\n\n############################################\n\n\n");

foreach($cnt_files as $file=>$amount){
  fwrite($fp_write, $amount." -- ". $file."\n");
}
fclose($fp_write);


// Funktion zur komfortablen Ausgabe von Zeichenketten und Arrays:
function dump($val){
  echo "<pre>";
  print_r($val);
  echo "</pre>";
  echo "<hr/>";
}


?>

Das liefert das Skript

Das Skript kann (siehe Kommentar im Quelltext) das Ergebnis im Browser ausgeben. Die Zahlen sind jeweils die Anzahlen der Datei-Typen/Dateien. Bei zu langen Listen empfiehlt es sich, die Ausgaben auszukommentieren.
Auf jeden Fall schreibt das Skript das Ergebnis auch in eine Auswertungs-Datei. Diese kann wie folgt aussehen:


29 -- php
15 -- png
12 -- html
7 -- swf
6 -- xml
4 -- gif
3 -- ##without##
...


############################################


5 -- /media/images/bild1.png
2 -- /media/images/bild_xy.png
1 -- /media/styles/main.css
...