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__ |