File Coverage

blib/lib/Apache/DBILogConfig.pm
Criterion Covered Total %
statement 4 6 66.6
branch n/a
condition n/a
subroutine 2 2 100.0
pod n/a
total 6 8 75.0


line stmt bran cond sub pod time code
1             package Apache::DBILogConfig;
2              
3             require 5.004;
4              
5 1     1   844 use strict;
  1         1  
  1         48  
6              
7             # MODULES
8              
9 1     1   1626 use mod_perl 1.11_01;
  0            
  0            
10             use Apache::Constants qw( :common );
11             use DBI;
12             use Date::Format;
13              
14             $Apache::DBILogConfig::VERSION = "0.02";
15              
16             # List of allowed formats and their values
17             my %Formats =
18             (
19             'a' => sub {return (shift)->connection->remote_ip}, # Remote IP Address
20             'A' => sub {}, # Local IP-address
21             'b' => sub {return (shift)->bytes_sent || '-'}, # Bytes sent, excluding heaers, in CLF format
22             'B' => sub {return (shift)->bytes_sent}, # Bytes sent, excluding heaers
23             'c' => sub {}, # Connection status when response is completed (X, +, -)
24             'e' => sub {return (shift)->subprocess_env(shift)}, # Any environment variable
25             'f' => sub {return (shift)->filename}, # Filename
26             'h' => sub {return (shift)->get_remote_host}, # Remote host
27             'H' => sub {return (shift)->protocol}, # The request protocol
28             'i' => sub {return (shift)->header_in(shift)}, # A header in the client request
29             'l' => sub {return (shift)->get_remote_logname}, # Remote log name (from identd)
30             'm' => sub {return (shift)->method}, # The request method
31             'n' => sub {return (shift)->notes(shift)}, # The contents of a note from another module
32             'o' => sub {return (shift)->header_out(shift)}, # A header from the reply
33             'p' => sub {return (shift)->get_server_port}, # Server port
34             'P' => sub {return $$}, # Apache child PID
35             'q' => sub {return $_[0]->args ? '?' . $_[0]->args : ''}, # The query string (prepended with a ?
36             # if the query exists)
37             'r' => sub {return (shift)->the_request}, # First line of the request
38             's' => sub {return (shift)->status}, # Status
39             't' => sub {return time2str $_[1] || "%d/%b/%Y:%X %z", $_[0]->request_time}, # Time: CLF or strftime
40             'T' => sub {return time - (shift)->request_time}, # Time taken to serve the request
41             'u' => sub {return (shift)->connection->user}, # Remote user from auth
42             'U' => sub {return (shift)->uri}, # URL
43             'v' => sub {return (shift)->server->server_hostname}, # The canonical ServerName
44             'V' => sub {} # The UseCanonicalName server name
45             );
46              
47             # SUBS
48              
49             sub logger {
50              
51             my $r = shift;
52             $r = $r->last; # Handle internal redirects
53             $r->subprocess_env; # Setup the environment
54              
55             # Connect to the database
56             my $source = $r->dir_config('DBILogConfig_data_source');
57             my $username = $r->dir_config('DBILogConfig_username');
58             my $password = $r->dir_config('DBILogConfig_password');
59             my $dbh = DBI->connect($source, $username, $password);
60             unless ($dbh) {
61             $r->log_error("Apache::DBILogConfig could not connect to $source - $DBI::errstr");
62             return DECLINED;
63             } # End unless
64             $r->warn("DBILogConfig: Connected to $source as $username");
65              
66             # Parse the formats ( %[conditions]{param}format=field [...] )
67             my @format_list = (); # List of anon hashes {field, format, param, conditions}
68             my $format_string = Apache->request->dir_config('DBILogConfig_log_format');
69             while ($format_string =~ /%(!)?([^\{[:alpha:]]*)(?:\{([^\}]+)\})?(\w)=(\S+)/g) {
70             my ($op, $conditions, $param, $format, $field) = ($1, $2, $3, $4, $5);
71              
72             # Or conditions together
73             my @conditions = map q($r->status == ) . $_, split /,/, $conditions;
74             $conditions = join(' or ', @conditions);
75              
76             $conditions = qq{!($conditions)} if $op eq '!'; # Negate if necessary
77             $conditions ||= 1; # If no conditions we want a guranteed true condition
78             $r->warn("DBILogConfig: format=$format, field=$field, param=$param, conditions=$conditions");
79             push @format_list, {'field' => $field, 'format' => $format, 'param' => $param,
80             'conditions' => $conditions};
81             } # End foreach
82              
83             # Create the statement and insert data
84             my $table = $r->dir_config('DBILogConfig_table');
85             @format_list = grep eval $_->{'conditions'}, @format_list; # Keep only ones whose conditions are true
86             my $fields = join ', ', map $_->{'field'}, @format_list; # Create string of fields
87             my $values = join ', ', map $dbh->quote($Formats{$_->{'format'}}->($r, $_->{'param'})), @format_list; # Create str of values
88             my $statement = qq(INSERT INTO $table ($fields) VALUES ($values));
89             $r->warn("DBILogConfig: statement=$statement");
90             $dbh->do($statement);
91              
92             $dbh->disconnect;
93              
94             return OK;
95              
96             } # End logger
97              
98             sub handler {shift->post_connection(\&logger)}
99              
100             1;
101              
102             __END__