Initial commit: Imported yaala 0.7.3.
[yaala.git] / lib / Yaala / Parser / Common.pm
1 package Yaala::Parser;
2
3 use strict;
4 use warnings;
5 use vars qw(%DATAFIELDS);
6
7 use Exporter;
8 use Yaala::Parser::WebserverTools qw(%MONTH_NUMBERS);
9 use Yaala::Data::Persistent qw#init#;
10 use Yaala::Config qw#get_config#;
11
12 @Yaala::Parser::EXPORT_OK = qw(parse extra %DATAFIELDS);
13 @Yaala::Parser::ISA = ('Exporter');
14
15 our $LASTDATE = init ('$LASTDATE', 'scalar');
16 our $EXTRA = init ('$EXTRA', 'hash');
17
18 if (!$$LASTDATE) { $$LASTDATE = 0; }
19 if (!defined ($EXTRA->{'total'})) { $EXTRA->{'total'} = 0; }
20 if (!defined ($EXTRA->{'days'} )) { $EXTRA->{'days'}  = {}; }
21
22 %DATAFIELDS = (
23         host    => 'key:host',
24         user    => 'key',
25         date    => 'key:date',
26         hour    => 'key:hour',
27         tld     => 'key',
28         file    => 'key',
29         status  => 'key:numeric',
30         bytes   => 'agg:bytes',
31         requests => 'agg'
32 );
33
34 # This needs to be done at runtime, since Data uses Setup which relies on
35 # %DATAFIELDS to be defined  -octo
36 require Yaala::Data::Core;
37 import Yaala::Data::Core qw#store#;
38
39 my $VERSION = '$Id: Common.pm,v 1.14 2003/12/07 14:56:38 octo Exp $';
40 print STDERR $/, __FILE__, ": $VERSION" if ($::DEBUG);
41
42 return (1);
43
44 sub parse
45 {
46         my $line = shift or return undef;
47         if ($line =~ /^(\S+) (\S+) (\S+) \[([^\]]+)\] "([^"]+)" (\d+) (\d+|-)$/)
48         {
49                 my ($host, $ident, $user, $date, $request, $status, $bytes) =
50                         ($1, $2, $3, $4, $5, $6, $7);
51
52                 my ($day, $month, $year, $hour, $minute, $second) =
53                         $date =~ m#(\d\d)/(\w{3})/(\d{4}):(\d\d):(\d\d):(\d\d)#;
54                 
55                 $month = $MONTH_NUMBERS{$month};
56                 $date = sprintf("%04u-%02u-%02u", $year, $month, $day);
57
58                 {
59                         my $tmp = int (sprintf ("%04u%02u%02u%02u%02u%02u",
60                                         $year, $month, $day, $hour, $minute, $second));
61                         
62                         if ($tmp < $$LASTDATE)
63                         {
64                                 print STDERR $/, __FILE__, ": Skipping.. ($tmp < $$LASTDATE)" if ($::DEBUG & 0x0200);
65                                 return (undef);
66                         }
67                         else { $$LASTDATE = $tmp; }
68                 }
69                 
70                 my ($method, $file, $params);
71                 if ($request =~ m#(\S+) ([^ \?]+)\??(\S*)#)
72                 {
73                         $method = $1;
74                         $file = $2;
75                         $params = (defined ($3) ? $3 : '');
76                 }
77                 else
78                 {
79                         print STDERR $/, __FILE__, ": Malformed request: ``$request''." if ($::DEBUG);
80                         return (0);
81                 }
82                 
83                 if (($user ne '-') and ($status >= 400) and ($status < 500))
84                 {
85                         $user = '*INVALID*';
86                 }
87
88                 if ($user eq '-') { $user = '*UNKNOWN*'; }
89                 if ($bytes eq '-') { $bytes = 0; }
90
91                 my $tld;
92                 if ($host =~ m/\.([a-z]{2,})$/i)
93                 {
94                         $tld = lc ($1);
95                 }
96                 else
97                 {
98                         $tld = '*UNRESOLVED*';
99                 }
100
101                 $EXTRA->{'total'}++;
102                 $EXTRA->{'days'}{$date}++;
103
104                 my %combined = (
105                                         'host'          =>      $host,
106                                         'user'          =>      $user,
107                                         'date'          =>      $date,
108                                         'hour'          =>      $hour,
109                                         'tld'           =>      $tld,
110                                         'file'          =>      $file,
111                                         'status'        =>      $status,
112                                         'bytes'         =>      $bytes,
113                                         'requests'      =>      1
114                                 );
115                 store (\%combined);
116         }
117         elsif ($::DEBUG)
118         {
119                 chomp ($line);
120                 print STDERR $/, __FILE__, ": Unable to parse: '$line'";
121         }
122 }
123
124 sub extra
125 {
126         my ($average, $days) = (0, 0);
127         
128         $days = scalar (keys (%{$EXTRA->{'days'}}));
129
130         return (0) unless ($days);
131         
132         $average = sprintf ("%.1f", ($EXTRA->{'total'} / $days));
133
134         $::EXTRA->{'Total requests'} = $EXTRA->{'total'};
135         $::EXTRA->{'Average requests per day'} = $average;
136         $::EXTRA->{'Reporting period'} = "$days days";
137 }