root/alternc-stats/tags/0.4/bin/alternc_stats_web.php

Revision 2063, 5.6 kB (checked in by anarcat, 1 year ago)

remove unnecessary trailing ?>

  • 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/php -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  */
51 include("/var/alternc/bureau/class/config_nochk.php");
52
53 // Libère le bureau !
54 alternc_shutdown();
55
56 $argv0 = array_shift($argv);
57
58 # crude getopt for portability
59 $verbose = $full = 0;
60 foreach ($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
92 foreach ($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
163 if ($verbose) echo "\n$total_hits lines read total ($total_good good)\n";
164
165 // check validity
166 if ($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
176 function 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
Note: See TracBrowser for help on using the browser.