Statistiques à partir des logs Apache
Les logs Apache ce sont ces fichiers définis par les directives CustomLog et ErrorLog dans Apache. C’est certes la tendance de tout logger (voir une obligation pour les hébergeurs), mais on peut aussi obtenir pas mal d’informations avec ceux-ci, pour des statistiques parfois très poussées.
Ce sont ces fichiers qui sont utilisés par des logiciels de stats comme awstats. Nous allons voir ici comment configurer Apache de sorte à enregistrer les informations utiles, et comment utiliser ces fichiers pour obtenir des informations sur l’activité de votre site internet et de votre serveur. Nous étudieront plus spécifiquement les logs d’accès (CustomLog).
Pré-requis :
Connaissances
- Connaissances de base en systèmes X (Linux, Unix, *BSD …)
- Culture générale en informatique
- Connaissances de base en HTTP
Matériel / Logiciel
- Un serveur Apache
Spécifications :
- OS : Linux
- Distribution : Debian Etch
- Objectif : Stats avec les logs Apache
Configuration Apache
La configuration globale des logs d’accès Apache se trouve dans le fichier /etc/apache2/apache2.conf.
Il est possible sur Apache de configurer le format des logs, et le contenu de ceux ci. Cette configuration se fait grâce à ces lignes :
LogFormat « %h %l %u %t \ »%r\ » %>s %b \ »%{Referer}i\ » \ »%{User-Agent}i\ »" combined
LogFormat « %h %l %u %t \ »%r\ » %>s %b » common
LogFormat « %{Referer}i -> %U » referer
LogFormat « %{User-agent}i » agent
La syntaxe est la suivante :
LogFormat Format_de_la_ligne nom_du_format
LogFormat : C’est pour annoncer notre configuration
Format_de_la_ligne : Le contenu de notre log:
| Variable de format | Description | Exemple |
| %a | L’IP distante |
92.125.XX.XX |
| %A | L’IP du serveur local | 192.168.2.110 |
| %B | Taille de la réponse (en octet) | 0 |
| %b | Même chose que au dessus au format Common Log | - |
| %{foobar}C | Le contenu du cookie foobar * | %{user}C toto45 |
| %D | Le temps que le serveur a mis pour servir la requête (en micro-sec) |
3295 |
| %{FOOBAR}e | La valeur de la variables d’environnement FOOBAR * |
%{KIKOO}e |
| %f | Le nom du fichier appelé | /var/www/site/index.html |
| %h | L »hôte distante | 92.125.XX.XX |
| %H | Le protocole utilisé + la version | HTTP/1.1 |
| %{Foobar}i | La valeur d’une option d’en tête* | %{Host}i www.my-linux.fr |
| %m | La méthode de requête | GET |
| %{Foobar}n | Le contenu de la note Foobar à partir d’un autre module* |
%{forensic-id}n |
| %{Foobar}o | Même chose que %{Foobar}, mais en sortie du serveur * | %{Keep-alive}o timeout=5, max=100 |
| %p | Le port avec lequel la requête a été servit | 80 |
| %{format}p | Le port avec lequel la requête a été servit (canonical) Le port actuel du serveur (local) Le port distant (remote) |
%{local}p 80 |
| %P | Le PID du process fils avec lequel la requête a été servit | 9857 |
| %{format}P |
Le PID du process fils avec lequel la requête a été servit (pid) |
%{tid}P 3084101296 |
| %q | La query string * | ?page=action&id=2 |
| %r | Première ligne de la requête * | GET /index.html HTTP/1.1 |
| %s | La statut retourné | 200 |
| %t | La date d’exécution de la requête* | [06/Mar/2009:23:47:18 +0100] |
| %{format}t | La date avec un format strftime* | %{%d-%m-%Y}t 06-03-2009 |
| %T | Même chose que %D mais en secondes | 0 |
| %u | Le login de l’utilisateur, si il s’est authentifié par HTTP | admin |
| %U | Le chemin dans l’URL demandé sans query string | /index.html |
| %v | La valeur du paramètre ServerName de l’environnement de la requête demandée (VirtualHost ou environnement global) | www.my-linux.fr |
| %V | La valeur de l’Host | my-linux.fr |
| %X | Statut de la connexion quand la réponse sera complétée : X : Connexion avorté avant la fin de la réponse + : La connexion doit être gardée après la fin de la réponse - : La connexion doit être fermée après la fin de la réponse |
+ |
Tableau basé sur la doc http://httpd.apache.org/docs/2.2/mod/mod_log_config.html#formats
* Contiennent des espaces, et peuvent donc poser problème pour l’analyse.
Les variables de format qui n’ont pas de résultats retournent un « - ».
Nom_du_fomat : C’est le nom du format à ajouter en fin de ligne CustomLog pour s’en servir.
Dans la suite nous utiliserons le format « combined », qui est la forme « standard » qui nous permettra d’avoir le plus d’informations intéressantes.
Il est conseillé si des VirtualHosts sont mis en place sur votre serveur, de leur spécifier chacun un fichier de log différent.
Exemple :
<VirtualHost *:80>
ServerName www.site1.com
…
CustomLog /var/log/apache2/site1.com/access_log combined
</VirtualHost>
<VirtualHost *:80>
ServerName www.site2.com
…
CustomLog /var/log/apache2/site2.com/access_log combined
</VirtualHost>
<VirtualHost *:80>
ServerName www.site3.com
…
CustomLog /var/log/apache2/site3.com/access_log combined
</VirtualHost>
Analysons ces logs
Nos logs sont à présent créés, nous allons pouvoir les analyser. N’oublions pas qu’ils sont en combined et utilisent donc le LogFormat : %h %l %u %t \ »%r\ » %>s %b \ »%{Referer}i\ » \ »%{User-Agent}i\ »"
Voyons ce que donne l’affichage de ce fichier :
$ cat access_log
…
196.XXX.XXX.58 – - [07/Mar/2009:00:36:19 +0100] « GET /favicon.ico HTTP/1.1″ 404 270 « - » « Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.9.0.7) Gecko/2009021910″
…
Plusieurs lignes (ou hits) comme au dessus sont présentes, le LogFormat correspond bien au combined :
%h : 196.XXX.XXX.58
%l : -
%u : -
%t : [07/Mar/2009:00:36:19 +0100]
%r : GET /favicon.ico HTTP/1.1
%>s : 404
%b : 270
%{Referer}i : -
%{User-Agent}i : « Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.9.0.7) Gecko/2009021910 Firefox/3.0.7″
Ici la personne, qui a l’IP 196.XXX.XXX.58 a cherché à obtenir le7mars à 0h36 le fichier /favicon.ico qui n’est pas disponible (404), la taille de la réponse est de 270octet. Son navigateur est FireFox3.0.7 et son OS : MS Windows.
Notre objectif à présent c’est de connaitre ces informations pour tout les hits. Les méthodes utilisées ici ne sont pas les plus jolies, mais elles sont simples à retenir et ne nécessite généralement pas de composants à installer.
Top IP :
Affichons dans un premier exemple le top IP dans les logs :
On commence par afficher la première colonne correspondant aux IP :
$ cat http_access_log | awk ‘{print $1}’
79.XXX.XXX.35
79.XXX.XXX.35
79.XXX.XXX.35
79.XXX.XXX.35
79.XXX.XXX.35
79.XXX.XXX.35
79.XXX.XXX.35
79.XXX.XXX.35
79.XXX.XXX.35
79.XXX.XXX.35
79.XXX.XXX.35
79.XXX.XXX.35
79.XXX.XXX.35
79.XXX.XXX.35
88.XXX.XXX.21
88.XXX.XXX.21
88.XXX.XXX.21
83.XXX.XXX.93
83.XXX.XXX.93
83.XXX.XXX.93
83.XXX.XXX.93
83.XXX.XXX.93
83.XXX.XXX.93
83.XXX.XXX.93
83.XXX.XXX.93
83.XXX.XXX.93
83.XXX.XXX.93
83.XXX.XXX.93
…
Ca manque évidement de lisibilité, c’est la raison pour laquelle on va afficher une seule ligne par IP.
$ cat http_access_log | awk ‘{print $1}’ | sort | uniq -c
27 196.XXX.XXX.90
27 196.XXX.XXX.58
3 216.XXX.XXX.95
21 58.XXX.XXX.197
12 66.XXX.XXX.15
29 74.XXX.XXX.139
2 74.XXX.XXX.151
21 77.XXX.XXX.148
21 79.XXX.XXX.35
20 81.XXX.XXX.189
22 82.XXX.XXX.148
25 82.XXX.XXX.95
21 83.XXX.XXX.93
160 83.XXX.XXX.156
21 86.XXX.XXX.149
580 88.XXX.XXX.21
28 90.XXX.XXX.199
42 90.XXX.XXX.55
On utilise sort ici pour regrouper les IP (en les rangeant dans l’ordre alphabétique).
uniq est utilisé pour supprimer les doublons, on rajoute -c pour compter le nombre d’entrés multiples.
Nous avons à présent le nombre de fois que chaque IP est présente dans le fichier. Pour continuer notre top IP nous allons classer ces IP par le nombre de fois qu’elles sont trouvées :
$ cat http_access_log | awk ‘{print $1}’ | sort | uniq -c | sort -gr
581 88.XXX.XXX.21
160 83.XXX.XXX.156
42 90.XXX.XXX.55
29 74.XXX.XXX.139
28 90.XXX.XXX.199
27 196.XXX.XXX.58
27 196.XXX.XXX.90
25 82.XXX.XXX.95
22 82.XXX.XXX.148
21 86.XXX.XXX.149
21 83.XXX.XXX.93
21 79.XXX.XXX.35
21 77.XXX.XXX.148
21 58.XXX.XXX.197
20 81.XXX.XXX.189
12 66.XXX.XXX.15
3 216.XXX.XXX.95
2 74.XXX.XXX.151
On re-tri tout ça par ordre numérique (g) et on inverse le résultat (r).
Top hits en erreur :
On va à présent afficher les hits en erreur.
Le status des hits de trouve en colone 9.
$ cat http_access_log | awk ‘{print $9}’
200
200
200
200
200
200
200
200
200
200
200
200
200
200
200
200
404
404
200
200
200
200
200
200
200
200
301
200
Tout ça c’est bien, mais il est bien de connaitre quelles sont les requêtes en erreur.
Dans notre exemple nous allons lister les hits en « No found » avec le code 404; on va donc chercher les lignes avec 404 comme valeur de la colonne 9, et qui afficheront les hits correspondants. Awk va nous aider dans ce nouveau besoin; il est en effet possible d’y insérer des conditions.
$ cat http_access_log | awk ‘{ if ($9 == « 404″) print $7 }’
/favicon.ico
/favicon.ico
/favicon.ico
/favicon.ico
/favicon.ico
/favicon.ico
/favicon.ico
/favicon.ico
/favicon.ico
/favicon.ico
/favicon.ico
/favicon.ico
/favicon.ico
/favicon.ico
/favicon.ico
/favicon.ico
/favicon.ico
/favicon.ico
/favicon.ico
/favicon.ico
/robots.txt
/favicon.ico
/favicon.ico
/favicon.ico
/favicon.ico
/favicon.ico
/favicon.ico
/favicon.ico
/favicon.ico
/favicon.ico
/favicon.ico
/favicon.ico
/favicon.ico
/favicon.ico
/favicon.ico
/favicon.ico
/favicon.ico
/favicon.ico
/favicon.ico
/favicon.ico
/favicon.ico
/favicon.ico
/favicon.ico
/favicon.ico
/favicon.ico
/favicon.ico
/favicon.ico
/favicon.ico
/favicon.ico
/favicon.ico
/favicon.ico
/favicon.ico
/favicon.ico
/favicon.ico
/favicon.ico
/favicon.ico
/favicon.ico
/favicon.ico
/favicon.ico
/favicon.ico
/favicon.ico
/favicon.ico
/favicon.ico
/adminsitrator
/favicon.ico
/favicon.ico
Ici donc on affiche la colone 7 si la colone 9 = 404.
Pour plus de lisibilité on applique les méthodes similaires à l’exercice précédent.
$ cat http_access_log | awk ‘{ if ($9 == « 404″) print $7 }’ | sort | uniq -c | sort -gr
64 /favicon.ico
1 /robots.txt
1 /adminsitrator
Ici il y a donc 64 hits en 404 qui ont chercher à obtenir la ressource /favicon.ico.
Ce tuto est à présent terminé, vous savez à présent utiliser les logs Apache avec le minimum d’outils présents sur la plupart des shells Unix/Linux/*BSD .