source: trunk/bin/alternc_stats_web.php @ 1397

Revision 1397, 5.7 KB checked in by anarcat, 8 years ago (diff)

sortir des initialisations statiques de la boucle

  • 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 = $full = 0;
60foreach ($argv as $pos => $arg) {
61  switch ($arg) {
62  case "-v":
63    unset($argv[$pos]);
64    $verbose = 1;
65    break;
66  case "-f":
67    unset($argv[$pos]);
68    $full = 1;
69    @mysql_query("DELETE FROM stat_http");
70    break;
71  }
72}
73
74$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");
75
76/**
77 * match "escaped quotes" or "everything except quotes"
78 *
79 * this might represent a significant performance hit
80 */
81$noquote = '(?:(?:(?<=\\\)")|(?:[^"]))*';
82
83// Exemple de ligne apache :
84// 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
85
86// this pattern should match it
87$pattern = '/^[^ ]* [^ ]* [^ ]* \\[([0-9]*)\\/([a-zA-Z]*)\\/([0-9]*):[0-9]*:[0-9]*:[0-9]* [^ ]* "'.$noquote.'" ([0-9-]*) ([0-9-]*) "'.$noquote.'" "'.$noquote.'" [0-9]* ([^ ]*)$/';
88
89$total_hits = $total_good = 0;
90
91// process all logfiles
92foreach ($argv as $file) {
93
94  if ($verbose) {
95    echo "################################################\n";
96    echo date("d/m/Y H:i:s")." : Traitement de $file\n";
97    echo "################################################\n";
98  }
99
100  if (substr($file,-3)==".gz") {
101    $open="gzopen";
102    $gets="gzgets";
103    $close="gzclose";
104  } else {
105    $open="fopen";
106    $gets="fgets";
107    $close="fclose";
108  }
109
110  if (($f = $open($file, "rb")) === FALSE) {
111    die("impossible d'ouvrir le log $file");
112  }
113
114  $i = $l= $good = 0;
115
116  $domstat=array(); // On stocke sous forme de clé "dom/day" => "hit or bandwith"
117  $domuid=array();  // Cache des uids associés aux domaines.
118
119  // parse a line at a time
120  while ($s=$gets($f,BUFSIZE)) {
121    $s=trim($s);
122    if (preg_match($pattern,$s,$mat)) {
123      // ok, 1: jour  2: mois (english)  3: année  4: http result (200/404 ...) 5: taille  6: domaine
124      // Ligne ok.
125      //    echo "Ligne ok : ";
126      //    for($j=1;$j<count($mat);$j++) echo "$j:".$mat[$j]." ";
127      // On calcule le jour : (= yearmonthday)
128      $day=$mat[3].$months[$mat[2]].$mat[1];
129      $dom = mysql_escape_string(strtolower($mat[6]));
130      $domstat[$dom."/".$day]["hit"]++;
131      $domstat[$dom."/".$day]["size"]+=intval($mat[5]);
132      $good++;
133    } else {
134      if ($verbose)
135        printf("Can't parse: %.60s...\n", $s);
136    }
137    if ($i/100==intval($i/100)) { echo "."; flush(); }
138    $i++; $l++;
139
140    // insérer une fois que notre bloc de lignes est plein
141    if ($i==$each) {
142      if ($verbose) echo " $l lines read\nInserting... ";
143      insert_lines($domstat, &$domuid);
144      $domstat = array();
145      $i=0;
146    }
147  }
148
149  // insérer les lignes qui n'avaient pas rempli un bloc
150  if ($verbose) echo "\nInserting remaining lines... ";
151  insert_lines($domstat, &$domuid); 
152  $domstat = array();
153
154  $close($f);
155 
156  $total_hits += $l;
157  $total_good += $good;
158
159  if ($verbose) echo "\n$l lines read ($good good)\n";
160
161}
162
163if ($verbose) echo "\n$total_hits lines read total ($total_good good)\n";
164
165// check validity
166if ($full) {
167  list($res) = mysql_fetch_array(mysql_query("SELECT SUM(hit) FROM stat_http"));
168  if ($res == $total_good) {
169    echo "correct count: $res\n";
170  } else {
171    echo "difference between database hits and lines read: $res => $total_good\n";
172  }
173}
174
175// handy function to avoid a copy-paste
176function insert_lines($domstat, &$domuid) {
177  global $verbose;
178  // on insère le tableau dans mysql.
179  $update=0; $insert=0;
180  foreach($domstat as $date => $stat) {
181    preg_match("/^([^\\/]*)\\/(.*)$/",$date,$mat);
182    $dom =$mat[1];
183    $date = $mat[2];
184    // on cherche l'uid de ce domaine
185    if (!$domuid[$dom]) {
186      list($domuid[$dom])=@mysql_fetch_array(mysql_query("SELECT compte FROM sub_domaines WHERE (domaine='".$dom."' AND sub='') OR (concat(sub,'.',domaine)='".$dom."');"));
187    }
188    // a-t-on déjà ce domaine ce jour ?
189    list($ct)=@mysql_fetch_array(mysql_query("SELECT COUNT(*) FROM stat_http WHERE day='".$date."' AND domain='".$dom."';"));
190    if ($ct) {
191      $sql="UPDATE stat_http SET hit= hit + '".$stat["hit"]."', size= size + '".$stat["size"]."' WHERE domain='".$dom."' AND day='".$date."';";
192      $update++;
193    } else {
194      $sql="INSERT INTO stat_http SET uid='".$domuid[$dom]."',day='".$date."',domain='".$dom."', hit='".$stat["hit"]."', size='".$stat["size"]."';";
195      $insert++;
196    }
197    mysql_query($sql) || die("Query failed: " . mysql_error());
198  }
199  if ($verbose) echo "$update updates and $insert inserts (uidcache size = ".count($domuid).") \n";
200
201}
202
203?>
Note: See TracBrowser for help on using the repository browser.