summaryrefslogtreecommitdiffstats
path: root/contrib
diff options
context:
space:
mode:
Diffstat (limited to 'contrib')
-rw-r--r--contrib/.cvsignore1
-rw-r--r--contrib/Makefile.in36
-rw-r--r--contrib/README38
-rw-r--r--contrib/create_tables.sql51
-rw-r--r--contrib/make_combined_log.pl139
-rw-r--r--contrib/mysql_import_combined_log.pl224
6 files changed, 489 insertions, 0 deletions
diff --git a/contrib/.cvsignore b/contrib/.cvsignore
new file mode 100644
index 0000000..f3c7a7c
--- /dev/null
+++ b/contrib/.cvsignore
@@ -0,0 +1 @@
Makefile
diff --git a/contrib/Makefile.in b/contrib/Makefile.in
new file mode 100644
index 0000000..c2bd203
--- /dev/null
+++ b/contrib/Makefile.in
@@ -0,0 +1,36 @@
1# @configure_input@
2
3# Modify these top variables.
4SUBDIRS =
5
6EXTRA_DIST = README \
7 create_tables.sql \
8 make_combined_log.pl \
9 mysql_import_combined_log.pl
10
11#Don't modify anything below here
12
13srcdir = @abs_srcdir@
14builddir = @abs_builddir@
15
16STD_DIST = Makefile.in
17
18DISTFILES = $(STD_DIST) $(EXTRA_DIST)
19
20all:
21
22install:
23
24update:
25
26clean:
27
28distclean: clean
29 $(RM) Makefile
30
31local-dist: $(DISTFILES)
32 mkdir -p $(DESTDIR)
33 cp -dp --parents $(DISTFILES) $(DESTDIR)
34
35.PHONY: include all-subdirs update-subdirs install-subdirs \
36 clean-subdirs distclean-subdirs dist
diff --git a/contrib/README b/contrib/README
new file mode 100644
index 0000000..bf0e65f
--- /dev/null
+++ b/contrib/README
@@ -0,0 +1,38 @@
1This directory contains contributed scripts/programs/utilites for mod_log_sql.
2
3* create_tables.sql
4
5This is the create table SQL commands to create the access, headers_in,
6headers_out, cookies, and notes tables in the MySQL database.
7Use it like this.
8mysql -u user -h host -p apachelogdatabase < create_tables.sql
9Where:
10 user is the username to log in as,
11 host is the hostname the server is on,
12 apachelogdatabase is the database to put the tables into
13 -p will have mysql ask you for a password for the user
14
15*make_combined_log.pl
16
17This perl script will extract the data from mod_log_sql's tables in the
18database and export a standard Apache combined log file. Use this to run
19logs through a program like webalizer.
20
21You must edit the perl script to configure variables before you run it.
22Usage:
23./make_combined_log.pl days virtualhost
24Where:
25 days is the number of days to fetch (starting from now and going back
26 in time)
27 virtualhost is the name of the virtualhost to retrieve
28
29Example:
30 ./make_combined_log.pl 2 example.com
31
32*mysql_import_combined_log.pl
33
34This is a perl script written by Aaron Jenson that imports a combined log file
35from apache into a SQL database table.. You can use this script to import logs
36from a webserver you are converting over from the standard Apache log system to
37mod_log_sql. A Usage statement can be fetch by running the program with no
38parameters or with --help or -?.
diff --git a/contrib/create_tables.sql b/contrib/create_tables.sql
new file mode 100644
index 0000000..0fe0f4b
--- /dev/null
+++ b/contrib/create_tables.sql
@@ -0,0 +1,51 @@
1create table access_log (
2 id char(19) ,
3 agent varchar(255) ,
4 bytes_sent int unsigned ,
5 child_pid smallint unsigned,
6 cookie varchar(255),
7 machine_id varchar(25),
8 request_file varchar(255),
9 referer varchar(255) ,
10 remote_host varchar(50) ,
11 remote_logname varchar(50) ,
12 remote_user varchar(50) ,
13 request_duration smallint unsigned ,
14 request_line varchar(255),
15 request_method varchar(10) ,
16 request_protocol varchar(10) ,
17 request_time char(28),
18 request_uri varchar(255),
19 request_args varchar(255),
20 server_port smallint unsigned,
21 ssl_cipher varchar(25),
22 ssl_keysize smallint unsigned,
23 ssl_maxkeysize smallint unsigned,
24 status smallint unsigned ,
25 time_stamp int unsigned ,
26 virtual_host varchar(255)
27);
28
29create table notes (
30 id char(19),
31 item varchar(80),
32 val varchar(80)
33);
34
35create table headers_in (
36 id char(19),
37 item varchar(80),
38 val varchar(80)
39);
40
41create table headers_out (
42 id char(19),
43 item varchar(80),
44 val varchar(80)
45);
46
47create table cookies (
48 id char(19),
49 item varchar(80),
50 val varchar(80)
51);
diff --git a/contrib/make_combined_log.pl b/contrib/make_combined_log.pl
new file mode 100644
index 0000000..2c55271
--- /dev/null
+++ b/contrib/make_combined_log.pl
@@ -0,0 +1,139 @@
1#!/usr/bin/perl
2
3# $Id: make_combined_log.pl,v 1.2 2004/02/12 23:32:55 urkle Exp $
4#
5# make_combined_log.pl
6#
7# Usage: make_combined_log <days> <virtual host>
8#
9# This perl script extracts the httpd access data from a MySQL database
10# and formats it properly for parsing by 3rd-party log analysis tools.
11#
12# The script is intended to be run out by cron. Its commandline arguments tell
13# it how many days' worth of access records to extract, and which virtual_host
14# you are interested in (because many people log several virthosts to one MySQL
15# db.) This permits you to run it daily, weekly, every 9 days -- whatever you
16# decide.
17#
18# Note: By "days" I mean "chunks of 24 hours prior to the moment this script is
19# run." So if you run it at 4:34 p.m. on the 12th, it will go back through 4:34
20# p.m. on the 11th.
21#
22# Known issues:
23# * Because GET and POST are not discriminated in the MySQL log, we'll just
24# assume that all requests are GETs. This should have negligible effect
25# on any analysis software. This could be remedied IF you stored the full
26# HTTP request in your database instead of just the URI, but that's going to
27# cost you a LOT of space really quickly...
28#
29# * Because this is somewhat of a quick hack it doesn't do the most robust
30# error checking in the world. Run it by hand to confirm your usage before
31# putting it in crontab.
32
33$| = 1;
34
35use DBI;
36
37# Remove the # in front of this line when you have
38# edited the variables below.
39#$has_edited_source = 1;
40#
41# Set up the proper variables to permit database access
42#
43$serverName = "your.dbhost.com";
44$serverPort = "3306";
45$serverUser = "someuser";
46$serverPass = "somepass";
47$serverTbl = "acc_log_tbl";
48$serverDb = "apache";
49
50if (!defined($has_edited_source)) {
51 print "Please edit this file and configure it first.\n";
52 print "This program is $0\n";
53 exit 1;
54}
55# Remember, $#ARGV is parameters minus one...
56if ($#ARGV != 1) {
57 print "Usage $0 days virtualhost\n";
58 exit 1;
59}
60
61$days = $ARGV[0];
62$virthost = $ARGV[1];
63
64#
65# Other constants
66#
67$st_tz = "-0800";
68$dt_tz = "-0700";
69
70$now = time();
71$start = $now - (86400 * $days);
72
73#
74# Connect and fetch the records
75#
76$dbh = DBI->connect("DBI:mysql:database=$serverDb;host=$serverName;port=$serverPort",$serverUser,$serverPass);
77if (not $dbh) {
78 die "Unable to connect to the database. Please check your connection variables. (Bad password? Incorrect perms?)";
79}
80
81$records = $dbh->prepare("select remote_host,remote_user,request_uri,time_stamp,status,bytes_sent,referer,agent,request_method,request_protocol from `$serverTbl` where virtual_host='$virthost' and time_stamp >= $start order by time_stamp");
82$records->execute;
83if (not $records) {
84 die "No such table or the select returned no records."
85}
86
87#Right
88#ariston.netcraft.com - - [14/Nov/2001:05:13:39 -0800] "GET / HTTP/1.0" 200 502 "-" "Mozilla/4.08 [en] (Win98; I)"
89#ariston.netcraft.com - - [14/Nov/2001:05:13:39 -0800] "GET / HTTP/1.0" 200 502 "-" "Mozilla/4.08 [en] (Win98; I)"
90
91#Bad
92#ariston.netcraft.com - - [2001-11-14 05:13:39 -0800] "GET / HTTP/1.1" 200 502 "-" "Mozilla/4.08 [en] (Win98; I)"
93#ariston.netcraft.com - - [2001-11-14 05:13:39 -0800] "GET / HTTP/1.1" 200 502 "-" "Mozilla/4.08 [en] (Win98; I)"
94
95
96#
97# Pull out the data row by row and format it
98#
99while (@data = $records->fetchrow_array) {
100 ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($data[3]);
101 $year=$year+1900;
102
103 # Create format for leading-zero formatting
104 if ($mday < 10) { $mday = "0$mday"; }
105 if ($mon < 10) { $mon = "0$mon"; }
106 if ($hour < 10) { $hour = "0$hour"; }
107 if ($min < 10) { $min = "0$min"; }
108 if ($sec < 10) { $sec = "0$sec"; }
109
110 # Convert numeric month to string month
111 for ($mon) {
112 if (/00/) { $mon = "Jan";}
113 elsif (/01/) { $mon = "Feb";}
114 elsif (/02/) { $mon = "Mar";}
115 elsif (/03/) { $mon = "Apr";}
116 elsif (/04/) { $mon = "May";}
117 elsif (/05/) { $mon = "Jun";}
118 elsif (/06/) { $mon = "Jul";}
119 elsif (/07/) { $mon = "Aug";}
120 elsif (/08/) { $mon = "Sep";}
121 elsif (/09/) { $mon = "Oct";}
122 elsif (/10/) { $mon = "Nov";}
123 elsif (/11/) { $mon = "Dec";}
124 }
125
126 # Create the output
127 print "$data[0] $data[1] - [$mday/$mon/$year:$hour:$min:$sec ";
128 if ($isdst) {
129 print "$dt_tz\] ";
130 } else {
131 print "$st_tz\] ";
132 }
133 print "\"$data[8] $data[2] $data[9]\" $data[4] $data[5] \"$data[6]\" \"$data[7]\"\n";
134}
135
136#
137# Done
138#
139$records->finish;
diff --git a/contrib/mysql_import_combined_log.pl b/contrib/mysql_import_combined_log.pl
new file mode 100644
index 0000000..bffec20
--- /dev/null
+++ b/contrib/mysql_import_combined_log.pl
@@ -0,0 +1,224 @@
1#!/usr/bin/perl -w
2# $Id: mysql_import_combined_log.pl,v 1.4 2004/02/21 18:09:50 urkle Exp $
3# Written by Aaron Jenson.
4# Original source: http://www.visualprose.com/software.php
5# Updated to work under Perl 5.6.1 by Edward Rudd
6use strict;
7use Getopt::Long qw(:config bundling);
8use DBI;
9use Date::Parse;
10
11my %options = ();
12my $i = 0;
13my $sql = '';
14my $valuesSql = '';
15my $line = '';
16my $dbh = 0;
17my $sth = 0;
18my @parts = ();
19my $part;
20my $TIMESTAMP = 3;
21my $REQUEST_LINE = 4;
22my @cols = (
23 'remote_host', ## 0
24 'remote_logname', ## 1
25 'remote_user', ## 2
26 'request_time', ## 3.string
27 'time_stamp', ## 3.posix
28 'request_line', ## 5
29 'request_method', ## 6
30 'request_uri', ## 7
31 'request_args', ## 8
32 'request_protocol', ## 9
33 'status', ## 10
34 'bytes_sent', ## 11
35 'referer', ## 12
36 'agent' ## 13
37);
38my $col = '';
39
40GetOptions (\%options,
41 "version" => sub { VERSION_MESSAGE(); exit 0; },
42 "help|?" => sub { HELP_MESSAGE(); exit 0; },
43 "host|h=s",
44 "database|d=s",
45 "table|t=s",
46 "username|u=s",
47 "password|p=s",
48 "logfile|f=s");
49
50$options{host} ||= 'localhost';
51$options{database} ||= '';
52$options{username} ||= '';
53$options{password} ||= '';
54$options{logfile} ||= '';
55
56if( ! $options{database} )
57{
58 HELP_MESSAGE();
59 print "Must supply a database to connect to.\n";
60 exit 1;
61}
62
63if( ! $options{table} )
64{
65 HELP_MESSAGE();
66 print "Must supply table name.\n";
67 exit 1;
68}
69
70if( $options{logfile} )
71{
72 if( ! -e $options{logfile} )
73 {
74 print "File '$options{logfile}' doesn't exist.\n";
75 exit 1;
76 }
77 open(STDIN, "<$options{logfile}") || die "Can't open $options{logfile} for reading.";
78}
79
80$dbh = Connect();
81if (! $dbh) {
82 exit 1;
83}
84
85$sql = "INSERT INTO $options{table} (";
86foreach $col (@cols)
87{
88 $sql .= "$col," if( $col );
89}
90chop($sql);
91$sql .= ') VALUES (';
92my ($linecount,$insertcount) = (0,0);
93while($line = <STDIN>)
94{
95 $linecount++;
96 @parts = SplitLogLine( $line );
97 next if( $parts[$TIMESTAMP+1] == 0 );
98 $valuesSql = '';
99 for( $i = 0; $i < @cols; ++$i )
100 {
101 $parts[$i] =~ s/\\/\\\\/g;
102 $parts[$i] =~ s/'/\\'/g;
103 $valuesSql .= "'$parts[$i]'," if( $cols[$i] );
104 }
105 chop($valuesSql);
106
107 $sth = $dbh->prepare("$sql$valuesSql)");
108 if( ! $sth->execute() )
109 {
110 print "Unable to perform specified query.\n$sql$valuesSql\n" . $sth->errstr() . "\n";
111 } else {
112 $insertcount++;
113 }
114 $sth->finish();
115}
116print "Parsed $linecount Log lines\n";
117print "Inserted $insertcount records\n";
118print "to table '$options{table}' in database '$options{database}' on '$options{host}'\n";
119
120# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
121# Connects to a MySQL database and returns the connection.
122# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
123sub Connect
124{
125 my $dsn = "DBI:mysql:$options{database};hostname=$options{host}";
126 return DBI->connect( $dsn, $options{username}, $options{password} );
127}
128
129
130# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
131# Splits up a log line into its parts.
132# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
133sub SplitLogLine
134{
135 my $line = shift;
136 my $i = 0;
137 my $inQuote = 0;
138 my $char = '';
139 my $part = '';
140 my @parts = ();
141 my $count = 0;
142 chomp($line);
143 for( $i = 0; $i < length($line); ++$i )
144 {
145 $char = substr($line, $i, 1);
146 if( $char eq ' ' && ! $inQuote )
147 {
148 ## print "Found part $part.\n";
149 if( $count == $TIMESTAMP )
150 {
151 push(@parts, "[".$part."]");
152 $part = str2time($part);
153 }
154 push(@parts, $part);
155 if( $count == $REQUEST_LINE )
156 {
157 my @request = split(/[ ?]/, $part);
158 push(@parts, $request[0]);
159 push(@parts, $request[1]);
160 if( $request[3] )
161 {
162 push(@parts, $request[2]);
163 push(@parts, $request[3]);
164 }
165 else
166 {
167 push(@parts, '');
168 push(@parts, $request[2]);
169 }
170 $count += 5;
171 }
172 else
173 {
174 ++$count;
175 }
176 $part = '';
177 }
178 elsif( $char eq '"' || $char eq '[' || $char eq ']' )
179 {
180 $inQuote = !$inQuote;
181 }
182 else
183 {
184 $part .= $char;
185 }
186 }
187 push(@parts,$part) if $part;
188
189 return @parts;
190}
191
192
193# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
194# Prints the usage/help message for this program.
195# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
196sub HELP_MESSAGE
197{
198 print<<EOF;
199Imports an Apache combined log into a MySQL database.
200Usage: mysql_import_combined_log.pl -d <database name> -t <table name> [-h <hostname>] [-u <username>] [-p <password>] [-f <filename]
201 --host|-h <host name> The host to connect to. Default is localhost.
202 --database|-d <database name> The database to use. Required.
203 --username|-u <username> The user to connect as.
204 --password|-p <password> The user's password.
205 --table|-t <table name> The name of the table in which to insert data.
206 --logfile|-f <file name> The file to read from. If not given, data is read from stdin.
207 --help|-? Print out this help message.
208 --version Print out the version of this software.
209EOF
210}
211
212
213
214# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
215# Prints the version information for this program
216# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
217sub VERSION_MESSAGE
218{
219 print "mysql_import_combined_log.pl version 1.2\n";
220 print "Version 1.0 Written by Aaron Jenson.\n";
221 print "Update to work with perl 5.6.1 by Edward Rudd\n";
222}
223
2241;