source: trunk/bin/alternc_stats_web.php @ 1389

Revision 1389, 5.0 KB checked in by anarcat, 8 years ago (diff)

am�liorer la sortie un peu

  • Property svn:eol-style set to native
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
Line 
1#!/usr/bin/php4 -q
2<?php
3
4/**
5 * Statistiques webs par compte AlternC
6 *
7 * Ce script lit tous les fichiers de log apache et insère les
8 * statistiques de visite par jour et par domaine / sous-domaine dans
9 * la table stat_http
10 *
11 * On assume que:
12 *
13 * - on est appelé à traiter un fichier de log donné qu'une seule fois
14 * - les fichiers de logs sont traités en ordre chronologique
15 *
16 * La façon correcte de faire ceci est de traiter access.log.0 juste
17 * après la rotation.
18 */
19
20/* Configuration */
21
22/**
23 * Combien de lignes de logs traite-t-on par bloc
24 *
25 * 10000 conseillé, plus possible (à tester), moins vivement
26 * déconseillé
27 */
28$each=10000;
29
30/**
31 * the maximum line length
32 *
33 * lines larger than this will not be parsed properly
34 *
35 * Was originally 2048, but was skipping too much of virus log
36 * entries. We still have some with 4096, but much less (at worst
37 * 1/10000 hits)
38 */
39@define('BUFSIZE', 4096);
40
41/* end of configuration */
42
43/**
44 * never stop because of time
45 */
46@set_time_limit(0);
47
48/**
49 * bypass login checks
50 */
51include("/var/alternc/bureau/class/config_nochk.php");
52
53// Libère le bureau !
54alternc_shutdown();
55
56$argv0 = array_shift($argv);
57
58# crude getopt for portability
59$verbose = 0;
60foreach ($argv as $pos => $arg) {
61  if ($arg == "-v") {
62    unset($argv[$pos]);
63    $verbose = 1;
64  }
65}
66
67// process all logfiles
68foreach ($argv as $file) {
69
70  if ($verbose) {
71    echo "################################################\n";
72    echo date("d/m/Y H:i:s")." : Traitement de $file\n";
73    echo "################################################\n";
74  }
75
76if (substr($file,-3)==".gz") {
77  $open="gzopen";
78  $gets="gzgets";
79  $close="gzclose";
80} else {
81  $open="fopen";
82  $gets="fgets";
83  $close="fclose";
84}
85
86  if (($f = $open($file, "rb")) === FALSE) {
87    die("impossible d'ouvrir le log $file");
88  }
89
90$i=0; $l=0;
91
92$domstat=array(); // On stocke sous forme de clé "dom/day" => "hit or bandwith"
93$domuid=array();  // Cache des uids associés aux domaines.
94
95
96$months=array("Jan"=>"01","Feb"=>"02","Mar"=>"03","Apr"=>"04","May"=>"05","Jun"=>"06","Jul"=>"07","Aug"=>"08","Sep"=>"09","Oct"=>"10","Nov"=>"11","Dec"=>"12");
97
98/**
99 * match "escaped quotes" or "everything except quotes"
100 *
101 * this might represent a significant performance hit
102 */
103$noquote = '(?:(?:(?<=\\\)")|(?:[^"]))*';
104
105// Exemple de ligne apache :
106// crawl18.dir.com - login [14/Jun/2004:06:38:47 +0200] "GET /modules/newbb?days=100 HTTP/1.0" 200 20156 "-" "Pompos/1.3 http://dir.com/pompos.html" 2 esperance-jeunes.org
107
108// this pattern should match it
109$pattern = '/^[^ ]* [^ ]* [^ ]* \\[([0-9]*)\\/([a-zA-Z]*)\\/([0-9]*):[0-9]*:[0-9]*:[0-9]* [^ ]* "'.$noquote.'" ([0-9-]*) ([0-9-]*) "'.$noquote.'" "'.$noquote.'" [0-9]* ([^ ]*)$/';
110
111// parse a line at a time
112while ($s=$gets($f,BUFSIZE)) {
113  $s=trim($s);
114  if (preg_match($pattern,$s,$mat)) {
115    // ok, 1: jour  2: mois (english)  3: année  4: http result (200/404 ...) 5: taille  6: domaine
116    // Ligne ok.
117    //    echo "Ligne ok : ";
118    //    for($j=1;$j<count($mat);$j++) echo "$j:".$mat[$j]." ";
119    // On calcule le jour : (= yearmonthday)
120    $day=$mat[3].$months[$mat[2]].$mat[1];
121    $dom = mysql_escape_string(strtolower($mat[6]));
122    $domstat[$dom."/".$day]["hit"]++;
123    $domstat[$dom."/".$day]["size"]+=intval($mat[5]);
124    $good++;
125  } else {
126    if ($verbose)
127      printf("Can't parse: %.60s...\n", $s);
128  }
129  if ($i/100==intval($i/100)) { echo "."; flush(); }
130  $i++; $l++;
131
132  // insérer une fois que notre bloc de lignes est plein
133  if ($i==$each) {
134    if ($verbose) echo " $l lines read\nInserting... ";
135    insert_stuff($domstat, &$domuid);
136    $domstat = array();
137    $i=0;
138  }
139}
140
141// insérer les lignes qui n'avaient pas rempli un bloc
142if ($verbose) echo "\n$l lines read ($good good)\nInserting remaining lines... ";
143 insert_stuff($domstat, &$domuid); 
144 $domstat = array();
145
146 $close($f);
147 
148}
149
150// handy function to avoid a copy-paste
151function insert_stuff($domstat, &$domuid) {
152  global $verbose;
153    // on insère le tableau dans mysql.
154    $update=0; $insert=0;
155    foreach($domstat as $date => $stat) {
156      preg_match("/^([^\\/]*)\\/(.*)$/",$date,$mat);
157      $dom =$mat[1];
158      $date = $mat[2];
159      // on cherche l'uid de ce domaine
160      if (!$domuid[$dom]) {
161        list($domuid[$dom])=@mysql_fetch_array(mysql_query("SELECT compte FROM sub_domaines WHERE (domaine='".$dom."' AND sub='') OR (concat(sub,'.',domaine)='".$dom."');"));
162      }
163      // a-t-on déjà ce domaine ce jour ?
164      list($ct)=@mysql_fetch_array(mysql_query("SELECT COUNT(*) FROM stat_http WHERE day='".$date."' AND domain='".$dom."';"));
165      if ($ct) {
166        $sql="UPDATE stat_http SET hit= hit + '".$stat["hit"]."', size= size + '".$stat["size"]."' WHERE domain='".$dom."' AND day='".$date."';";
167        $update++;
168      } else {
169        $sql="INSERT INTO stat_http SET uid='".$domuid[$dom]."',day='".$date."',domain='".$dom."', hit='".$stat["hit"]."', size='".$stat["size"]."';";
170        $insert++;
171      }
172      mysql_query($sql) || die("Query failed: " . mysql_error());
173    }
174    if ($verbose) echo "$update updates and $insert inserts (uidcache size = ".count($domuid).") \n";
175}
176
177?>
Note: See TracBrowser for help on using the repository browser.