PHPGangsta - Der praktische PHP Blog

PHP Blog von PHPGangsta


Traffic pro eingeloggtem User herausfinden

with 7 comments

Den Traffic einer ganzen Seite herauszufinden ist nicht sonderlich schwer in Zeiten von awstats, webalizer und diversen anderen Apache-Log-Analyzern.

Doch ich wollte damals bei meinem eigenen Browsergame den Traffic pro eingeloggtem User messen. Idee war damals, den „Free Accounts“ 100MB pro Monat zu schenken, falls mehr benötigt wird, muss ein Premium-Account her.

Doch wie stellt man das an? Das Apache-Log hilft nicht wirklich, denn dort kann man nicht die einzelnen (eingeloggten) User unterscheiden. Ich habe damals 3 Lösungen gefunden:

  • mit dem Output Buffer von PHP arbeiten, Stringlänge bestimmen und mitloggen, dann Seite an den Browser schicken
  • Irgendwie die IP-Adressen des Users merken, und dann das Apache-Log durchparsen und rechnen.
  • die Apache-Extension mod_log_sql

Möglichkeit 1 sieht dann ungefähr so aus:

<?php
ob_start();

// some html content here

$trafficbytes = strlen(ob_get_flush());
// insert traffic into database

?>

Habe es nie ausführlich getestet, aber ich denke es ist langsam (da das HTML erst am Ende geflushed wird anstatt zwischendurch schon Häppchen zu verschicken). Außerdem muß man sich noch um Bilder kümmern, denn die sollen ja auch mitgezählt werden. Dazu würde ich eine Rewrite-Rule empfehlen, die bei jedem Bildrequest noch schnell ein php-Script ausführt. Auch das beeinflusst natürlich die Performance des Besuchers und des Webservers.

Die zweite Möglichkeit ist nicht ganz einfach umzusetzen. Die IP-Adresse allein ist nicht sonderlich aussagekräftig, einen Benutzer damit zu verfolgen recht aufwändig. In Zeiten von Proxies (Grüße an AOL), Neueinwahl bei DSL, mehrere Benutzer hinter einem Heimrouter etc reicht das nicht aus, um darüber den Benutzer zu bestimmen, gerade wenn Bruder und Schwester gemeinsam über eine Leitung im Internet sind usw.

Die dritte Alternative ist das Apache-Modul, welches ich dann auch genutzt habe: mod_log_sql. Dieses bindet man einfach in die entsprechene Apache-Config ein, und schon wird ein zusätzliches Log erzeugt, nämlich in der Datenbank. Dies kann man entweder für alle Seiten tun, oder nur für bestimmte VirtualHosts. Welche Spalten dort gefüllt werden sollen, in welcher Reihenfolge und mit welchen Daten, konfiguriert man in der apache-Config. Hier eine Beispielkonfiguration (hier für Linux, für Windows sieht es ähnlich aus: .dll statt .so usw.):

LoadModule log_sql_module modules/mod_log_sql.so
LoadModule log_sql_mysql_module modules/mod_log_sql_mysql.so

LogSQLLoginInfo mysqli://apacheloguser:apachelogpwd@localhost/apachelogdb
LogSQLCreateTables On
LogSQLMachineID mylocalmaschine
LogSQLTransferLogFormat AbHIhMmpRSstTUuvz
LogSQLTransferLogTable ztraffic_access_log
#LogSQLNotesLogTable ztraffic_notes
LogSQLCookieLogTable ztraffic_cookies
#LogSQLHeadersInLogTable ztraffic_headers_in
#LogSQLHeadersOutLogTable ztraffic_headers_out
LogSQLWhichCookies UserID     # hier könnten noch mehr Cookies stehen

Man kann alternativ zur eigenen Cookie-Tabelle auch ein bestimmtes Cookie mit ‚c‘ und „LogSQLWhichCookie“ in die access_log schrieben lassen. Hier eine Liste der Informationen, die man speichern kann.

Damit das Modul funktioniert, muß man noch das Modul „unique“ aktivieren, entweder per

a2enmod unique_id

oder via Einkommentieren von

LoadModule unique_id_module modules/mod_unique_id.so

Apache reload. Wenn man danach eine Seite besucht, liest man folgendes im apache error log:

[Tue Sep 01 19:59:46 2009] [notice] mod_log_sql: child established database connection
[Tue Sep 01 19:59:46 2009] [error] mysql_query returned (1)
[Tue Sep 01 19:59:46 2009] [error] table does not exist, preserving query
[Tue Sep 01 19:59:46 2009] [error] table doesn't exist...creating now
[Tue Sep 01 19:59:47 2009] [error] tables successfully created - retrying query
[Tue Sep 01 19:59:47 2009] [notice] query successful after table creation

Die Tabelle wurde also erfolgreich angelegt. Das Ergebnis sieht dann so aus:

modlogsql0

Der Inhalt der Tabelle (nur 1 Zeile):

modlogsql

Wäre dieser Test-Request kein 304er (Not Modified), hätten wir bei „bytes_sent“ auch eine Traffic-Angabe.

Mit Hilfe der Cookie-Tabelle können wir dann zB einmal täglich den Traffic jeden Users berechnen und in die entsprechende User-Tabelle füllen. Die Log-Tabelle sollte man dann wieder aufräumen und nicht länger benötigte Zeilen löschen.

Übrigens ist das Modul nur für Linux supported. Unter Windows kann man es zwar auch kompilieren, das ist aber mehr hohem Aufwand verbunden. Ich habe damals (2004) durch Zufall eine kompilierte Version gefunden. Die ist aber heute nicht mehr brauchbar, da sie für eine sehr alte Apache-Version kompiliert wurde.

Wenn ihr Fragen habt, fragt! Oder wenn ihr evtl. bessere Lösungen kenn, her damit! Oder was könnte man noch alles anstellen mit diesen Apache-Logs in einer Datenbank?

—————————————————-

Weitere interessante Links zum Thema:

Anleitung für Debian Etch

Die offizielle Webseite des Moduls

Written by Michael Kliewe

September 1st, 2009 at 8:29 pm

Posted in PHP

Tagged with , , , , ,

7 Responses to 'Traffic pro eingeloggtem User herausfinden'

Subscribe to comments with RSS or TrackBack to 'Traffic pro eingeloggtem User herausfinden'.

  1. Hallo Michael,
    ein toller Beitrag. Sicherlich nützlich, um die Performance des Servers im Auge zu behalten und um die auszugebenden Seiten zu optimieren.

    Gruß
    Roman

    Roman

    3 Sep 09 at 12:35

  2. Hallo,

    wie kann man denn damit die Performance des Servers messen? Ich würde sagen, dass man mit dieser Aktion eher der Performance schadet.
    Oder kann man aus der entstehenden Log-Tabelle Informationen zur Performance ziehen?

    Seiten optimieren würde ich mit dem Apache-Log auch nicht wirklich, da sind einige Firefox-Addons etc. sicherlich sinnvoller. Man kann ja in dem Log nicht den Inhalt der Seiten sehen, also kann man sie auch nicht optimieren, oder doch?

    Klär mich auf!

    Michael Kliewe

    3 Sep 09 at 12:42

  3. Hallo Michael,
    okay, das war vllt. etwas falsch formuliert. Mein Gedanke war folgender:

    Wenn ich mit deinem Vorschlag den Traffic jeder aufgerufenen Seite messen kann, dann weiß ich auch, wo ich ansetzen muss, um die Last zu dezimieren.
    Performance im Sinne von Auslieferungsgeschwindigkeit lässt sich aus dem Log nicht ablesen.

    Eine Optimierung einer Seite lohnt sich auch erst, wenn eine gewisse Anzahl an Benutzern die Seite aufruft. Würde man z.B. eine Seite, die 30kb groß ist auf 25kb reduzieren können, so spart man pro 100 Aufrufe schon ein halbes MB.

    Roman

    3 Sep 09 at 12:56

  4. Hi Michael,

    kannst du etwas zur Performance sagen?

    Fitschi

    3 Sep 09 at 13:19

  5. @Roman: Das kann man aber auch bereits im „normalen“ Apache-Textlog herausfinden, dafür braucht man kein Logging in eine Datenbank.
    Wenn du also den Traffic herausfinden und optimieren willst, reicht das Textlog und altbewährte Apache-Log-Analyzer. Dafür würde ich nicht das Datenbank-Logging aktivieren.

    @Fitschi: Zur Performance des Moduls kann ich dir nichts sagen. Ich denke aber auch, dass es etwas vom Datenbankserver und der Auslastung des Apache abhängt. Bei 10 Zugriffen pro Sekunde geht weder der Apache noch der Datenbank-Server in die Knie. Bei tausenden Zugriffen pro Sekunde wird es schon interessanter, ob dann das Datenbank-Logging ein Flaschenhals sein könnte. Wäre interessant, wenn das mal jemand untersuchen könnte.

    Michael Kliewe

    3 Sep 09 at 13:43

  6. Um das nochmal zusammenzufassen: Datenbank-Logging ist nicht in jedem Fall optimal und sollte nicht immer aktiviert sein. Ich habe es nur als eine Alternative vorgestellt, wie man für einzelne eingeloggte Benutzer (die sich über eine UserID in der Session und im Cookie identifizieren) den Traffic herausfinden und loggen kann. Genau das geht nämlich nicht mit dem Standard-Apache-Log, dafür braucht man eben dieses Modul.

    Einen Einsatzzweck hatte ich schon genannt, nämlich wenn man versucht, Leuten klarzumachen, dass sie bitte einen Premium-Account bezahlen sollen. Das kann man natürlich mit erweiterten Features machen, aber auch zB indem man ihnen klar macht, dass sie Ressourcen auf dem Server verbrauchen und den Betreiber etwas kosten. Dann wird Benutzern vllt. eher klar, dass sie 1-2 Euro im Monat dafür bezahlen könnten.

    Wenn möglich, sollte man aber auf das Apache-Text-Logfile zurückgreifen und damit arbeiten. Dann umgeht man auch Probleme, wenn die Datenbank mal nicht erreichbar ist.

    Michael Kliewe

    3 Sep 09 at 13:48

  7. Ein wirklich toller Beitrag 🙂

    alopix

    4 Sep 09 at 08:07

Leave a Reply

You can add images to your comment by clicking here.