summaryrefslogtreecommitdiffstatsabout
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG53
-rw-r--r--Documentation/documentation.lyx2969
-rw-r--r--Documentation/documentation.tex1534
-rw-r--r--INSTALL303
-rw-r--r--Makefile147
-rw-r--r--README133
-rw-r--r--access_log.sql25
-rw-r--r--create_tables.sql50
-rwxr-xr-xmake_combined_log.pl4
-rw-r--r--mod_log_sql.c639
10 files changed, 5289 insertions, 568 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 1d38ca9..8be7dda 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,9 +1,10 @@
1$Id: CHANGELOG,v 1.15 2002/09/04 18:46:00 helios Exp $ 1$Id: CHANGELOG,v 1.16 2002/11/14 03:51:34 helios Exp $
2 2
3 3
4TODO: 4TODO:
5* Rethink documentation flow and rewrite? 5* Rethink documentation flow and rewrite?
6* Port connection portion to other DBMS? Genericize the module? Start with PostgreSQL. 6* Port connection portion to other DBMS? Genericize the module? Start with
7PostgreSQL.
7* check for mandatory conf directives / syntax quit if not 8* check for mandatory conf directives / syntax quit if not
8* GNU autoconf 9* GNU autoconf
9* merge server config into vh config 10* merge server config into vh config
@@ -14,13 +15,36 @@ TODO:
14* new format char: IP as bigint? 15* new format char: IP as bigint?
15* socket-based middleman daemon with configurable conns? 16* socket-based middleman daemon with configurable conns?
16 17
17* go ahead and allow dashes - quote the table name! 18
18* maxlength of request field should be longer 19* Cookies in separate table
20* ignore by cookie
21
22
19 23
20 24
21CHANGES: 25CHANGES:
22 26
231.17: 271.17:
28* In make_combined_log.pl, backtick-quoted the table name and added an
29 order-by clause within the select statement.
30* TCP port number for db connection is now configurable using LogSqlTCPPort
31* New directive LogSQLForcePreserve sends all log entries directly to the
32 preserve file and *entirely bypasses* the db. Useful for debugging, but
33 can be dangerous if you forget it's set!
34* Table names are now quoted in all cases with backticks in order to permit
35 names containing dashes (since many hostnames contain dashes).
36* The request_method field is now created as a varchar(10) instead of (6),
37 after it was pointed out to me that some methods can be longer than 6.
38* New directive LogSQLMachineID sets a string identifier for the webserver
39 machine. This is useful if you have a cluster of many webservers and you
40 want to differentiate between them in the logs: you can tell which log
41 entries came from each machine and thereby analyze your loadbalacing
42 performance. Activate with the TransferLogFormat character 'M'. Much
43 faster than doing some sort of wacky IP addr lookup via local_addr().
44* Added an alternative way of logging cookies. If you need to associate
45 multiple cookies with each request, the new way involves using
46 LogSQLWhichCookies (note the plural) and LogSQLCookieLogTable.
47
24* Renamed the module mod_log_sql to conform to the project goal of 48* Renamed the module mod_log_sql to conform to the project goal of
25 database-inspecificity. 49 database-inspecificity.
26* Added capability of logging Notes field. This is useful for folks using 50* Added capability of logging Notes field. This is useful for folks using
@@ -35,11 +59,11 @@ CHANGES:
35 be opened.) 59 be opened.)
36* Changed default socket file to /tmp/mysql.sock because that's the 60* Changed default socket file to /tmp/mysql.sock because that's the
37 default on a compiled MySQL. 61 default on a compiled MySQL.
38* Also check for '-' when I'm creating the table when MySQLMassVirtualHosting 62* Put back-quotes (`) around table name so that names with dashes are
39 is on, and change it to underscore. (Already did this with '.') 63 legal.
40* Took away the prepend of /tmp to the preserve filename. Now the 64* Took away the prepend of /tmp to the preserve filename. Now the
41 user can specify whatever local path they want. I figure that 65 user can specify whatever local path they want. I figure that
42 filesystem permissions will prevent people from doing anything 66 filesystem permissions will prevent people from doing anything
43 really dumb, and people have requested this change. 67 really dumb, and people have requested this change.
44* Better checking in the extract_cookie routine. Before, it could 68* Better checking in the extract_cookie routine. Before, it could
45 segfault if a person specified "c" but didn't define MySQLWhichCookie. 69 segfault if a person specified "c" but didn't define MySQLWhichCookie.
@@ -58,9 +82,10 @@ CHANGES:
58* Minor: remind user not to set createtables when massvirtual is on. 82* Minor: remind user not to set createtables when massvirtual is on.
59* If Apache started but MySQL was unavailable, the module would do 83* If Apache started but MySQL was unavailable, the module would do
60 everything it was supposed to (preserve entries, etc.) but not notify 84 everything it was supposed to (preserve entries, etc.) but not notify
61 the sysadmin. Added a log message to alert sysadmin if MySQL is 85 the sysadmin. Added a log message to alert sysadmin if MySQL is
62 unreachable at startup. 86 unreachable at startup.
63* New config key 'I' to extract & log unique_id, provided by mod_unique_id. 87* New config key 'I' to extract & log unique_id, provided by mod_unique_id.
88 unique_id is the key that links separate tables (access, notes, etc.)
64* Migrated to the Artistic License (as used by Perl). 89* Migrated to the Artistic License (as used by Perl).
65* Moved table creation into its own callable function 90* Moved table creation into its own callable function
66* Robustifying table creation 91* Robustifying table creation
@@ -161,7 +186,7 @@ CHANGES:
161 (e.g. GET, PUT, etc.) 186 (e.g. GET, PUT, etc.)
162* New config capabilities: 'z' 'q' & 'Q' to log SSL_CIPHER, 187* New config capabilities: 'z' 'q' & 'Q' to log SSL_CIPHER,
163 SSL_CIPHER_USEKEYSIZE and SSL_CIPHER_ALGKEYSIZE. These require 188 SSL_CIPHER_USEKEYSIZE and SSL_CIPHER_ALGKEYSIZE. These require
164 openssl and glibc-devel to be installed. (See the online 189 openssl and glibc-devel to be installed. (See the online
165 directives documentation and FAQ.) 190 directives documentation and FAQ.)
166* Fixed a bug in make_combined_log.pl that caused it to generate 191* Fixed a bug in make_combined_log.pl that caused it to generate
167 incorrect output on single-digit days. 192 incorrect output on single-digit days.
@@ -182,11 +207,13 @@ CHANGES:
182 MySQLTransferLogFormat 207 MySQLTransferLogFormat
183 Instruct the module what information to log to the MySQL transfer log 208 Instruct the module what information to log to the MySQL transfer log
184 MySQLRefererIgnore 209 MySQLRefererIgnore
185 List of referers to ignore, accesses that match will not be logged to MySQL 210 List of referers to ignore, accesses that match will not be logged to
211MySQL
186 MySQLRequestIgnore 212 MySQLRequestIgnore
187 List of URIs to ignore, accesses that match will not be logged to MySQL 213 List of URIs to ignore, accesses that match will not be logged to MySQL
188 MySQLRemhostIgnore 214 MySQLRemhostIgnore
189 List of remote hosts to ignore, accesses that match will not be logged to MySQL 215 List of remote hosts to ignore, accesses that match will not be logged
216to MySQL
190 MySQLDatabase 217 MySQLDatabase
191 The name of the MySQL database for logging 218 The name of the MySQL database for logging
192 MySQLWhichCookie 219 MySQLWhichCookie
@@ -256,7 +283,7 @@ CHANGES:
256 more. 283 more.
257* Now include a headerfile (http_log.h) that was missing. Its 284* Now include a headerfile (http_log.h) that was missing. Its
258 absence was giving us this warning message: "implicit declaration of 285 absence was giving us this warning message: "implicit declaration of
259 function `ap_log_error_old'." 286 function `ap_log_error_old'."
260* For numerics that Apache customarily logs as a "-" we now log a zero 287* For numerics that Apache customarily logs as a "-" we now log a zero
261 instead of a -1. This seems to be more intuitive, e.g. in the 288 instead of a -1. This seems to be more intuitive, e.g. in the
262 "bytes_sent" column. 289 "bytes_sent" column.
@@ -285,7 +312,7 @@ CHANGES:
2851.03: 3121.03:
286 313
287* Changed the check for 'mysql server has gone away' to be case 314* Changed the check for 'mysql server has gone away' to be case
288 insensitive, so that it works with MySQL 3.21 315 insensitive, so that it works with MySQL 3.21
289* Changed the behavior so that a link isn't established until it's 316* Changed the behavior so that a link isn't established until it's
290 necessary (e.g., if SQL logging is used for one virtual IP, a link 317 necessary (e.g., if SQL logging is used for one virtual IP, a link
291 won't be opened until there's an access to that IP). 318 won't be opened until there's an access to that IP).
diff --git a/Documentation/documentation.lyx b/Documentation/documentation.lyx
new file mode 100644
index 0000000..48c3968
--- /dev/null
+++ b/Documentation/documentation.lyx
@@ -0,0 +1,2969 @@
1#LyX 1.1 created this file. For more info see http://www.lyx.org/
2\lyxformat 218
3\textclass article
4\language english
5\inputencoding default
6\fontscheme default
7\graphics default
8\paperfontsize 10
9\spacing single
10\papersize letterpaper
11\paperpackage a4
12\use_geometry 1
13\use_amsmath 0
14\paperorientation portrait
15\paperwidth 8.5in
16\paperheight 11in
17\leftmargin 1in
18\topmargin 0.5in
19\rightmargin 1in
20\bottommargin 1in
21\secnumdepth 3
22\tocdepth 3
23\paragraph_separation indent
24\defskip medskip
25\quotes_language swedish
26\quotes_times 2
27\papercolumns 1
28\papersides 1
29\paperpagestyle default
30
31\layout Title
32\added_space_top vfill \added_space_bottom vfill
33Installing and Running mod_log_sql
34\layout Author
35
36Christopher Powell
37\layout Date
38
3911/13/02
40\layout Standard
41\pagebreak_bottom
42
43\begin_inset LatexCommand \tableofcontents{}
44
45\end_inset
46
47
48\layout Section
49
50Introduction
51\layout Subsection
52
53Homepage
54\layout LyX-Code
55
56http://www.grubbybaby.com/mod_log_sql/
57\layout Subsection
58
59Summary
60\layout Standard
61
62This Apache module will permit you to log Apache accesses (and a lot of
63 related information) to a SQL database.
64 Unlike logging to a flat text file (which is standard in Apache), there
65 are a lot of powerful advantages to logging to SQL.
66 This module can either replace or happily coexist with Apache's text file
67 logging facility.
68\layout Subsection
69
70Approach
71\layout Standard
72
73This project was formerly known as mod_log_mysql.
74 It has been renamed to mod_log_sql in order to reflect the project goal
75 of database-inspecificity.
76 The module currently supports MySQL, and development for other database
77 backends is underway.
78\layout Standard
79
80In order to save speed and overhead, links are kept alive in between queries.
81 This module uses one SQL link per httpd child.
82 Among other things, this means that this module supports logging into only
83 one MySQL server, and for now, also, only one SQL database.
84 But that's a small tradeoff compared to the blinding speed of this module.
85\layout Standard
86
87Virtual hosts are supported in the same manner they are in the regular logging
88 modules.
89 You define some basic 'global' directives in the main server config, then
90 you define more specific 'local' directives inside each virtualhost stanza.
91\layout Standard
92
93SQL links are opened by each child process when it is born.
94 Error reporting is robust throughout and will let you know about database
95 issues in the standard Apache error-log for the server or virtual server.
96\layout Standard
97
98A robust "preserve" capability has now been implemented.
99 This permits the module to preserve any failed INSERT commands to a local
100 file on its machine.
101 In any situation that the database is unavailable -- e.g.
102 the network fails, you reboot the db host, etc.
103 -- mod_log_sql will note this in the error log and begin appending its
104 log entries to the preserve file (which is created with the user & group
105 ID of the running Apache process, e.g.
106 "nobody" on many Linux installations).
107 When your database becomes available again, mod_log_sql seamlessly resumes
108 logging to it.
109 When convenient for the sysadmin, he/she can easily import the preserve
110 file into the database because it is simply a series of SQL insert statements:
111\layout LyX-Code
112
113# mysql -uadminuser -p mydbname < /tmp/mysql-preserve
114\layout Subsection
115
116Supported directives
117\layout Standard
118
119Please see the web-based documentation for full explanation of all supported
120 run-time directives.
121\layout Standard
122
123http://www.grubbybaby.com/mod_log_sql/directives.html
124\layout Standard
125
126See the FAQ for some handy examples:
127\layout Standard
128
129http://www.grubbybaby.com/mod_log_sql/faq.html
130\layout Subsection
131
132What gets logged by default?
133\layout Standard
134
135All the data that would be contained in the "Combined Log Format" is logged
136 by default, plus a little extra.
137 Your best bet is to begin by accepting this default, then later customize
138 the log configuration based on your needs.
139\layout Standard
140
141The online documentation of the run-time directives includes a full explanation
142 of what you can log, including examples.
143\layout Subsection
144
145Minor Notes
146\layout Itemize
147
148Note which directives go in the 'main server config' and which directives
149 apply to the 'virtual host config'.
150 This is made clear in the directive documentation.
151\layout Itemize
152
153The 'time_stamp' field is stored in an UNSIGNED INTEGER column, in the standard
154 unix "seconds since 1/1/1970 12:00:00" format.
155 This is superior to storing the access time as a string due to size requirement
156s: an UNSIGNED INT type fits in 4 bytes, whereas the Apache date string
157 (e.g.
158 "18/Nov/2001:13:59:52 -0800") requires 26 bytes -- significantly larger,
159 and those extra 22 bytes will add up over the thousands of accesses that
160 a busy server will experience.
161 Besides, an INT type is far more flexible for comparisons, etc.
162\begin_deeper
163\layout Standard
164
165In MySQL 3.21 and above you can easily convert this to a human readable format
166 using from_unixtime(), e.g.:
167\layout LyX-Code
168
169select remote_host,request_uri,from_unixtime(time_stamp) from access_log;
170\layout Standard
171
172The enclosed perl program
173\begin_inset Quotes sld
174\end_inset
175
176make_combined_log.pl
177\begin_inset Quotes srd
178\end_inset
179
180 shows how you can extract your access records in a format that is completely
181 Combined Log Format compliant.
182 You can then feed this to your favorite web log analysis tool.
183\end_deeper
184\layout Itemize
185
186The table's string values can be CHAR or VARCHAR, at a length of your choice.
187 VARCHAR is superior because it truncates long strings; CHAR types are fixed-len
188gth and will be padded with spaces.
189 Just like the time_stamp described above, that kind of space waste will
190 add up over thousands of records.
191\layout Itemize
192
193Be careful not to go overboard setting fields to NOT NULL.
194 If a field is marked NOT NULL then it must contain data in the INSERT or
195 the INSERT will fail, sometimes in a really mysterious way to the frustrated
196 sysad.
197\layout Itemize
198
199Apache normally logs numeric fields with a '-' character to mean "not applicable
200," e.g.
201 bytes_sent on a request with a 304 response code.
202 Since '-' is an illegal character in an SQL numeric field, such fields
203 are assigned the value 0 instead of '-' which, of course, makes perfect
204 sense anyway.
205\layout Subsection
206
207Author / Maintainer
208\layout Standard
209
210The actual logging code was taken from the already existing flat file text
211 modules, so all that credit goes to the Apache Server group.
212\layout Standard
213
214The MySQL routines and directives were added by Zeev Suraski <bourbon@netvision.n
215et.il>.
216\layout Standard
217
218All changes from 1.06+ and the new documentation were added by Chris Powell
219 <chris@grubbybaby.com>.
220 It seems that the module had fallen into the "unmaintained" category --
221 it hadn't been updated since 1998 -- so Chris adopted it as the new maintainer.
222\layout Section
223
224Installation
225\layout Subsection
226
227Requirements
228\layout Itemize
229
230A compatible system.
231 I have run mod_log_sql on Red Hat based systems (Red Hat, Mandrake).
232 These instructions should easily adapt to any modern distro.
233\layout Itemize
234
235Apache 1.2 or 1.3 installed.
236 (I run 1.3.22 and it works fine).
237 You should have already successfully compiled Apache and know what you're
238 doing there.
239\layout Itemize
240
241The MySQL development headers.
242 This is called different things on different distros.
243 For example, Red Hat 6.x called this RPM "MySQL-devel" whereas Mandrake
244 calls it "libmysql10-devel".
245\layout Itemize
246
247MySQL >= 3.23.15 configured, installed and running on either localhost or
248 an accessible networked machine.
249 You should already have a basic understanding of MySQL and how it functions.
250\layout Itemize
251
252Again, basic administrative skills with Apache and MySQL.
253 I try to make things as easy as possible in this file, but its purpose
254 is not to be an administrative tutorial.
255\layout Itemize
256
257Additionally, if you want to be able to log SSL information such as keysize
258 or cipher, you need OpenSSL and glibc-devel installed.
259 Both are available as RPMs.
260\layout Subsection
261
262Do I want a DSO?
263\layout Standard
264
265You need to know the answer to this question before you proceed.
266 The answer is pretty straightforward: what have you done in the past? If
267 you like all your Apache modules to be dynamic, then you should keep doing
268 that.
269 If you're more of an old-school type and prefer to compile the modules
270 right into apache, do that.
271 Both methods work equally well.
272\layout Standard
273
274FWIW, the DSO method is more modern and increasing in popularity because
275 apxs takes care of a lot of dirty little details for you.
276 As you'll see below, the static-module method is a little more complex.
277\layout Subsection
278
279Installation as an Apache DSO (Preferred)
280\layout Enumerate
281
282Perform all the following steps as root so that you have install privs,
283 etc.
284 Unpack the archive into a working directory.
285\begin_deeper
286\layout LyX-Code
287
288# tar zxf mod_log_sql.tar.gz -C /usr/local/src # cd /usr/local/src/mod_log_sql
289\end_deeper
290\layout Enumerate
291
292Edit Makefile for your system.
293\newline
294
295\begin_deeper
296\layout Standard
297
298NECESSARY:
299\layout Itemize
300
301The location where you installed Apache -- usually /usr/local/apache, 'locate
302 apxs' can help you find it.
303\layout Itemize
304
305The location of your MySQL libraries, find using 'locate libmysqlclient'
306\layout Itemize
307
308The location of your MySQL header files, find using 'locate mysql.h'
309\layout Standard
310
311OPTIONAL if you have included mod_ssl in Apache and want to log SSL data
312 such as keysize and cipher type:
313\layout Itemize
314
315The location of your SSL header files, find using 'locate mod_ssl.h'
316\layout Standard
317
318Now that you know these things, edit Makefile and replace the stock values
319 with your own.
320\layout Standard
321
322IMPORTANT: If you are not logging SSL info, comment out MODSSLHDRS by putting
323 a # character in front of it:
324\layout LyX-Code
325
326#MODSSLHDRS=/usr/include/...
327\end_deeper
328\layout Enumerate
329
330Instruct apxs to compile the module as a DSO.
331\begin_deeper
332\layout LyX-Code
333
334# make dso
335\end_deeper
336\layout Enumerate
337
338You should see output similar to the following:
339\begin_deeper
340\layout LyX-Code
341
342/usr/local/Apache/bin/apxs -Wc,-O2 -Wc,-Wall -Wc,-DEAPI -c -I/usr/include/mysql
343 -I/usr/local/src/apache_1.3.27-dso/src/modules/ssl -L/usr/lib -lmysqlclient
344 -lz mod_log_sql.c
345\layout LyX-Code
346
347gcc -DLINUX=22 -DNO_DBM_REWRITEMAP -DMOD_SSL=208111 -DUSE_HSREGEX -DEAPI
348 -DUSE_EXPAT -I../lib/expat-lite -fpic -DSHARED_CORE -DSHARED_MODULE -I/usr/local/
349Apache/include -O2 -Wall -DEAPI -I/usr/include/mysql -I/usr/local/src/apache_1.3.2
3507-dso/src/modules/ssl -c mod_log_sql.c
351\layout LyX-Code
352
353gcc -shared -o mod_log_sql.so mod_log_sql.o -Wc,-O2 -Wc,-Wall -Wc,-DEAPI -L/usr/li
354b -lmysqlclient -lz -lm -lcrypt -ldb
355\layout Standard
356
357You should see no errors and have a file called "mod_log_sql.so" in your
358 directory.
359\end_deeper
360\layout Enumerate
361
362Instruct apxs to install the DSO.
363\begin_deeper
364\layout LyX-Code
365
366# make dsoinstall
367\layout Standard
368
369You should see output similar to the following:
370\layout LyX-Code
371
372/usr/local/Apache/bin/apxs -i mod_log_sql.so
373\layout LyX-Code
374
375cp mod_log_sql.so /usr/local/Apache/libexec/mod_log_sql.so
376\layout LyX-Code
377
378chmod 755 /usr/local/Apache/libexec/mod_log_sql.so
379\end_deeper
380\layout Enumerate
381
382Module ordering within httpd.conf is important.
383 If you are logging SSL, you must make sure that
384\begin_deeper
385\layout LyX-Code
386
387LoadModule ssl_module libexec/libssl.so
388\layout Standard
389
390comes before
391\layout LyX-Code
392
393LoadModule sql_log_module libexec/mod_log_sql.so
394\layout Standard
395
396If you don't, you will get this error when you start Apache:
397\layout LyX-Code
398
399/usr/local/apache/libexec/mod_log_mysql.so: undefined symbol: ssl_var_lookup
400\layout LyX-Code
401
402/usr/local/apache/bin/apachectl startssl: httpd could not be started
403\layout Standard
404
405(Because mod_log_sql doesn't yet have the required symbols that mod_ssl
406 provides.)
407\layout Standard
408
409Now skip below to the "Configuration" section.
410\end_deeper
411\layout Subsection
412
413Installation as a static module compiled into httpd
414\layout Enumerate
415
416Perform all the following steps as root so that you have install privs,
417 etc.
418\layout Enumerate
419
420Unpack the archive into a working directory.
421\begin_deeper
422\layout LyX-Code
423
424# tar zxf mod_log_sql.tar.gz -C /usr/local/src # cd /usr/local/src/mod_log_sql
425\end_deeper
426\layout Enumerate
427
428
429\begin_inset LatexCommand \label{step:editMF}
430
431\end_inset
432
433Edit Makefile for your system.
434\newline
435
436\begin_deeper
437\layout Standard
438
439NECESSARY:
440\layout Itemize
441
442The location where you installed Apache -- usually /usr/local/apache, 'locate
443 apxs' can help you find it.
444
445\layout Itemize
446
447The location of your Apache *sources*, find using 'locate ABOUT_APACHE'
448
449\layout Itemize
450
451The location of your MySQL header files, find using 'locate mysql.h'
452\layout Itemize
453
454The location of your MySQL libraries, find using 'locate libmysqlclient'
455\layout Standard
456
457OPTIONAL if you have included mod_ssl in Apache and want to log SSL data
458 such as keysize and cipher type:
459\layout Itemize
460
461The location of your mod_ssl header files, find using 'locate mod_ssl.h'
462\layout Itemize
463
464The location of your OpenSSL header files, find using 'locate x509.h'
465\layout Itemize
466
467The location of your db1 header files, find using 'locate mpool.h'
468\layout Standard
469
470Now that you know these things, edit Makefile and replace the stock values
471 with your own.
472\layout Standard
473
474IMPORTANT: If you are not logging SSL info, comment out MODSSLHDRS, OPNSSLHDRS
475 and DB1HDRS by putting a # character in front of each one, e.g.
476 #OPNSSLHDRS=/usr/include/...
477\end_deeper
478\layout Enumerate
479
480# make static
481\layout Enumerate
482
483# make statinstall
484\layout Enumerate
485
486Change to your Apache source dir.
487\begin_deeper
488\layout LyX-Code
489
490# cd /usr/local/src/apache-1.3.22/src
491\end_deeper
492\layout Enumerate
493
494Re-make your httpd binary as follows.
495\begin_deeper
496\layout Enumerate
497
498Edit Configuration.apaci as follows...
499\begin_deeper
500\layout Itemize
501
502Append the following string to the EXTRA_LIBS= line.
503 ("/usr/lib/mysql" is from step
504\begin_inset LatexCommand \ref{step:editMF}
505
506\end_inset
507
508, where your MySQL libraries live):
509\layout LyX-Code
510
511-L/usr/lib/mysql -lmysqlclient -lm -lz
512\layout Itemize
513
514Find the mod_log_config.o line, and add this line immediately after it:
515\layout LyX-Code
516
517AddModule modules/sql/mod_log_sql.o
518\end_deeper
519\layout Enumerate
520
521# cp Configuration.apaci Configuration
522\layout Enumerate
523
524# ./Configure
525\layout Enumerate
526
527# make
528\layout Enumerate
529
530# strip httpd
531\end_deeper
532\layout Enumerate
533
534Test your new apache binary:
535\begin_deeper
536\layout LyX-Code
537
538# ./httpd -l
539\end_deeper
540\layout Enumerate
541
542You should see something like:
543\begin_deeper
544\layout LyX-Code
545
546Compiled-in modules:
547\layout LyX-Code
548
549http_core.c
550\layout LyX-Code
551
552mod_log_sql.c <-- That's the line you're looking for.
553\layout LyX-Code
554
555mod_env.c
556\layout LyX-Code
557
558mod_log_config.c
559\layout LyX-Code
560
561mod_mime.c
562\layout LyX-Code
563
564mod_negotiation.c ...
565\layout LyX-Code
566
567etc...
568\end_deeper
569\layout Enumerate
570
571Install your httpd binary.
572 Copy it over your old httpd binary, wherever it lives.
573 You can and should rename your old httpd first so that you can easily revert
574 to that working version in case of bugs with the new version.
575\begin_deeper
576\layout LyX-Code
577
578# /etc/rc.d/init.d/httpd stop
579\layout LyX-Code
580
581# mv /usr/local/Apache/bin/httpd ~/httpd-save
582\layout LyX-Code
583
584# cp -f ./httpd /usr/local/Apache/bin/
585\end_deeper
586\layout Section
587
588Configuration
589\layout Subsection
590
591Preparing MySQL
592\layout Standard
593
594You have to prepare the database to receive data from mod_log_sql, and set
595 up run-time directives in httpd.conf to control how and what mod_log_sql
596 logs.
597\layout Standard
598
599This section will discuss how to get started with a basic config.
600 Full documentation of the run-time directives is available here: http://www.grub
601bybaby.com/mod_log_sql/directives.html
602\layout Enumerate
603
604mod_log_sql can make its own tables on-the-fly, or you can pre-make the
605 tables by hand.
606 The advantage of letting the module make the tables is ease-of-use, but
607 for raw performance you will want to pre-make the tables in order to save
608 overhead.
609 In this basic setup we'll let the module create tables for us.
610\layout Enumerate
611
612We still need to have a logging database created and ready, so run the MySQL
613 command line client and create a database:
614\begin_deeper
615\layout LyX-Code
616
617# mysql -uadmin -pmypassword mysql> create database apachelogs;
618\end_deeper
619\layout Enumerate
620
621If you want to hand-create the tables, run the enclosed 'create-tables'
622 SQL script as follows:
623\begin_deeper
624\layout LyX-Code
625
626mysql> source create_tables.sql
627\end_deeper
628\layout Enumerate
629
630Create a specific MySQL userid that httpd will use to authenticate and enter
631 data.
632 This userid need not be an actual Unix user.
633 It is a userid internal to MySQL with specific privileges.
634 In the following example command, "apachelogs" is the database, "loguser"
635 is the userid to create, "my.apachemachine.com" is the name of the Apache
636 machine, and "l0gger" is the password to assign.
637 Choose values that are different from these examples.
638\begin_deeper
639\layout LyX-Code
640
641mysql> grant insert,create on apachelogs.* to loguser@my.apachemachine.com
642 identified by 'l0gger';
643\end_deeper
644\layout Enumerate
645
646You may be especially security-paranoid and not want "loguser" to have "create"
647 capability within the "apachelogs" databse.
648 You can disable that but the cost is that you cannot use the module's automatic
649-table-creation feature.
650 If that's an acceptable cost, hand-create the tables as described in step
651 1 and use the following GRANT statement instead of the one above:
652\begin_deeper
653\layout LyX-Code
654
655mysql> grant insert on apachelogs.* to loguser@my.apachemachine.com identified
656 by 'l0gger';
657\end_deeper
658\layout Enumerate
659
660Enable full logging of your MySQL daemon (at least temporarily for debugging
661 purposes) if you don't do this already.
662 Edit /etc/my.cnf and add the following line to your [mysqld] section:
663\begin_deeper
664\layout LyX-Code
665
666log=/var/log/mysql-messages
667\layout Standard
668
669Then restart MySQL.
670\layout LyX-Code
671
672# /etc/rc.d/init.d/mysql restart
673\end_deeper
674\layout Subsection
675
676Preparing Apache
677\layout Enumerate
678
679Tell the module what database to use and the appropriate authentication
680 information.
681\begin_deeper
682\layout Description
683
684EXAMPLE: Use the MySQL database called "apachelogs" running on "dbmachine.foo.com".
685 The module uses username "loguser" and password "l0gger" to authenticate
686 to the database.
687 The log entries will be INSERTed into the table called "access_log".
688\layout Standard
689
690So, edit httpd.conf and insert the following lines somewhere AFTER any LoadModule
691 / AddModule statements.
692 Make sure these statements are "global," i.e.
693 not inside any VirtualHost stanza.
694\layout LyX-Code
695
696LogSQLDatabase apachelogs
697\layout LyX-Code
698
699LogSQLLoginInfo dbmachine.foo.com loguser l0gger
700\layout LyX-Code
701
702LogSQLCreateTables on
703\end_deeper
704\layout Enumerate
705
706If your database resides on localhost instead of another host, specify the
707 MySQL server's socket file as follows:
708\begin_deeper
709\layout LyX-Code
710
711LogSQLSocketFile /your/path/to/mysql.sock
712\end_deeper
713\layout Enumerate
714
715The actual logging is set up on a virtual-host-by-host basis.
716 So, skip down to the virtual host you want to set up.
717 Instruct this virtual host to log entries to the table
718\begin_inset Quotes sld
719\end_inset
720
721access_log
722\begin_inset Quotes srd
723\end_inset
724
725 by inserting a LogSQLTransferLogTable directive.
726 (The LogSQLTransferLogTable directive is the minimum required to log --
727 other directives simply tune the module's behavior.)
728\begin_deeper
729\layout LyX-Code
730
731<VirtualHost 1.2.3.4>
732\layout LyX-Code
733
734[snip]
735\layout LyX-Code
736
737LogSQLTransferLogTable access_log
738\layout LyX-Code
739
740[snip]
741\layout LyX-Code
742
743</VirtualHost>
744\end_deeper
745\layout Enumerate
746
747Restart apache.
748\begin_deeper
749\layout LyX-Code
750
751# /etc/rc.d/init.d/httpd start
752\end_deeper
753\layout Subsection
754
755Testing the module
756\layout Enumerate
757
758Load your web site in a browser to trigger some hits, then confirm that
759 the entries are being successfully logged:
760\begin_deeper
761\layout LyX-Code
762
763# mysql -hmysql.host.com -umysqladmin -p -e "select * from access_log" apachelogs
764
765\layout LyX-Code
766
767Enter password:
768\layout LyX-Code
769
770(Several lines of output should follow, corresponding to your hits on the
771 site.)
772\layout Standard
773
774You now have basic functionality.
775 Don't disable your regular Apache logs until you feel comfortable that
776 the database is behaving as you'd like and that things are going well.
777\end_deeper
778\layout Enumerate
779
780If you do not see any entries in the access_log, then something is preventing
781 the inserts from happening.
782 This problem could be caused by several things:
783\begin_deeper
784\layout Itemize
785
786Improper privileges set up in the MySQL database
787\layout Itemize
788
789You aren't hitting a VirtualHost that has a LogSQLTransferLogTable entry
790
791\layout Itemize
792
793You didn't specify the right host
794\layout Standard
795
796If you have confirmed your LogSQL* directives and know them to be correct,
797 you should examine the httpd server logs for mod_log_sql messages; the
798 module will offer hints as to why it cannot connect, etc.
799 Also examine the MySQL log that you established in step 3.
800 Ensure that the INSERTs are not being rejected because of a malformed table
801 entry or other clerical error.
802 If you see no INSERT attempts in the log, the module isn't successfully
803 connecting to the database.
804\layout Standard
805
806The next thing to do is recompile the module with debugging output activated.
807 change the "#undef DEBUG" on line 8 of mod_log_sql.c to "#define DEBUG"
808 and recompile/reinstall.
809 The module will now output copious notes about what it is doing, and this
810 will help you (and the maintainer) solve the problem.
811\end_deeper
812\layout Standard
813
814You can now activate the advanced features of mod_log_sql.
815 These are all described in the next section.
816\layout Subsection
817
818Configuration directive reference
819\layout Subsubsection
820
821LogSQLLoginInfo
822\layout LyX-Code
823
824
825\series bold
826MANDATORY
827\series default
828
829\layout LyX-Code
830
831Syntax: LogSQLLoginInfo host user password
832\layout LyX-Code
833
834Example: LogSQLLoginInfo foobar.baz.com logwriter passw0rd
835\layout LyX-Code
836
837Context: server config
838\layout Quote
839
840Defines the general parameters of the MySQL host to which you will be logging.
841 host is the hostname or IP address of the MySQL machine.
842 user is the MySQL userid (not a Unix userid!) with INSERT privileges on
843 the table defined in LogSQLTransferLogTable.
844 password is that user's password.
845 This is defined only once in the httpd.conf file.
846\layout Subsubsection
847
848LogSQLDatabase
849\layout LyX-Code
850
851
852\series bold
853MANDATORY
854\layout LyX-Code
855
856Syntax: LogSQLDatabase database
857\layout LyX-Code
858
859Example: LogSQLDatabase loggingdb
860\layout LyX-Code
861
862Context: server config
863\layout Quote
864
865Defines the database that is used for logging.
866 database must be operating on the MySQL host defined in LogSQLLoginInfo.
867 This is defined only once in the httpd.conf file.
868\layout Subsubsection
869
870LogSQLTransferLogTable
871\layout LyX-Code
872
873
874\series bold
875MANDATORY
876\layout LyX-Code
877
878Syntax: LogSQLTransferLogTable table-name
879\layout LyX-Code
880
881Example: LogSQLTransferLogTable access_log_table
882\layout LyX-Code
883
884Context: virtual host
885\layout Quote
886
887Defines which table is used for logging of Apache's transfers; this is analogous
888 to Apache's TransferLog directive.
889 table-name must be a valid table within the database defined in LogSQLDatabase.
890\layout Quote
891
892This directive is not necessary if you declare LogSQLMassVirtualHosting
893 On, since that directive activates dynamically-named tables.
894 If you attempt to use LogSQLTransferLogTable at the same time a warning
895 will be logged and it will be ignored, since LogSQLMassVirtualHosting takes
896 priority.
897\layout Subsubsection
898
899LogSQLRequestIgnore
900\layout LyX-Code
901
902Syntax: LogSQLRequestIgnore req1 req2 req3 ...
903 reqN
904\layout LyX-Code
905
906Example: LogSQLRequestIgnore root.exe cmd.exe default.ida favicon.ico
907\layout LyX-Code
908
909Context: virtual host
910\layout Quote
911
912Lists a series of strings that, if present in the URI, will cause that request
913 NOT to be logged.
914 This directive is useful for cutting down on log clutter when you KNOW
915 that you do not want to log requests for certain objects.
916 (The example above is a genuinely useful one; it will prevent logging of
917 many common Microsoft-based worm intrusion attempts, as well as those ridiculou
918s requests for the favicon.)
919\layout Quote
920
921Each string is separated by a space, and NO regular expressions or globbing
922 are allowed.
923 Each string is evaluated as a substring of the URI using strstr().
924\layout Subsubsection
925
926LogSQLRemhostIgnore
927\layout LyX-Code
928
929Syntax: LogSQLRemhostIgnore host1 host2 host3 ...
930 hostN
931\layout LyX-Code
932
933Example: LogSQLRemhostIgnore localnet.com
934\layout LyX-Code
935
936Context: virtual host
937\layout Quote
938
939Lists a series of strings that, if present in the REMOTE_HOST, will cause
940 that request NOT to be logged.
941 This directive is useful for cutting down on log clutter when you KNOW
942 that you do not want to log requests from certain hosts, such as your own
943 internal network machines.
944\layout Quote
945
946Each string is separated by a space, and NO regular expressions or globbing
947 are allowed.
948 Each string is evaluated as a substring of the REMOTE_HOST using strstr().
949\layout Subsubsection
950
951LogSQLRefererIgnore
952\layout LyX-Code
953
954Syntax: LogSQLRefererIgnore ref1 ref2 ref3 ...
955 refN
956\layout LyX-Code
957
958Example: LogSQLRefererIgnore google.com
959\layout LyX-Code
960
961Context: virtual host
962\layout Quote
963
964Lists a series of strings that, if present in the HTTP_REFERER, will cause
965 that request NOT to be logged.
966 This directive is useful for cutting down on log clutter when you know
967 that you do not want to log requests from certain referers.
968\layout Quote
969
970Each string is separated by a space, and NO regular expressions or globbing
971 are allowed.
972 Each string is evaluated as a substring of the HTTP_REFERER using strstr().
973\layout Subsubsection
974
975LogSQLWhichCookie
976\layout LyX-Code
977
978Syntax: LogSQLWhichCookie cookiename
979\layout LyX-Code
980
981Example: LogSQLWhichCookie Clicks
982\layout LyX-Code
983
984Default: None.
985 You must set this if you wish to capture cookies.
986\layout LyX-Code
987
988Context: virtual host
989\layout Quote
990
991In HTTP, cookies have names to distinguish them from each other.
992 Using mod_usertrack, for example, you can give your user-tracking cookies
993 a name with the CookieName directive.
994\layout Quote
995
996If you have activated cookie logging in LogSQLTransferLogFormat, then LogSQLWhic
997hCookie tells mod_log_sql which cookie to log.
998 This is useful because many times you will be setting and receiving more
999 than one cookie from a client; without this directive you'd be unable to
1000 choose which cookie is your mod_usertrack cookie.
1001\layout Quote
1002
1003Note: although this was intended for people who are using mod_usertrack
1004 to set user-tracking cookies, you aren't restricted in any way.
1005 You can choose which cookie you wish to log to the database, and it doesn't
1006 necessarily have to have anything to do with mod_usertrack.
1007\layout Subsubsection
1008
1009LogSQLCreateTables
1010\layout LyX-Code
1011
1012Syntax: LogSQLCreateTables flag
1013\layout LyX-Code
1014
1015Example: LogSQLCreateTables On
1016\layout LyX-Code
1017
1018Default: Off
1019\layout LyX-Code
1020
1021Context: server config
1022\layout Quote
1023
1024mod_log_sql now has the ability to create its tables on-the-fly.
1025 The advantage to this is convenience: you don't have to execute any SQL
1026 by hand to prepare the table.
1027 This is especially helpful for people with lots of virtual hosts (who should
1028 also see the LogSQLMassVirtualHosting directive).
1029\layout Quote
1030
1031There is a slight disadvantage: if you wish to activate this feature, then
1032 the user specified by LogSQLLoginInfo must have CREATE privileges on the
1033 database.
1034 In an absolutely paranoid, locked-down situation you may only want to grant
1035 your mod_log_sql user INSERT privileges on the database; in that situation
1036 you are unable to take advantage of LogSQLCreateTables.
1037 But most people -- even the very security-conscious -- will find that granting
1038 CREATE on the logging database is reasonable.
1039\layout Quote
1040
1041This is defined only once in the httpd.conf file.
1042\layout Subsubsection
1043
1044LogSQLMassVirtualHosting
1045\layout LyX-Code
1046
1047Syntax: LogSQLMassVirtualHosting flag
1048\layout LyX-Code
1049
1050Example: LogSQLMassVirtualHosting On
1051\layout LyX-Code
1052
1053Default: Off
1054\layout LyX-Code
1055
1056Context: server config
1057\layout Quote
1058
1059If you administer a site hosting many, many virtual hosts then this option
1060 will appeal to you.
1061 If you activate LogSQLMassVirtualHosting then several things happen:
1062\begin_deeper
1063\layout Itemize
1064
1065the on-the-fly table creation feature is activated automatically
1066\layout Itemize
1067
1068the transfer log table name is dynamically set from the virtual host's name
1069 (example: a virtual host www.grubbybaby.com gets logged to table access_www_grubb
1070ybaby_com)
1071\layout Itemize
1072
1073which, in turn, means that each virtual host logs to its own segregated
1074 table.
1075 Because there is no data shared between virtual servers you can grant your
1076 users access to the tables they need; they will be unable to view others'
1077 data.
1078\end_deeper
1079\layout Quote
1080
1081This is a huge boost in convenience for sites with many virtual servers.
1082 Activating LogSQLMassVirtualHosting obviates the need to create every virtual
1083 server's table and provides more granular security possibilities.
1084\layout Quote
1085
1086This is defined only once in the httpd.conf file.
1087\layout Subsubsection
1088
1089LogSQLPreserveFile
1090\layout LyX-Code
1091
1092Syntax: LogSQLPreserveFile filename
1093\layout LyX-Code
1094
1095Example: LogSQLPreserveFile offline-preserve
1096\layout LyX-Code
1097
1098Default: mysql-preserve (in /tmp)
1099\layout LyX-Code
1100
1101Context: virtual host
1102\layout Quote
1103
1104mod_log_sql writes queries to this local preserve file in the event that
1105 it cannot reach the database, and thus ensures that your high-availability
1106 web frontend does not lose logs during a temporary database outage.
1107 This could happen for a number of reasons: the database goes offline, the
1108 network breaks, etc.
1109 You will not lose entries since the module has this backup.
1110 The file consists of a series of SQL statements that can be imported into
1111 your database at your convenience; furthermore, because the SQL queries
1112 contain the access timestamps you do not need to worry about out-of-order
1113 data after the import.
1114\layout Quote
1115
1116For security purposes the name you supply will be prepended with "/tmp/"
1117 to force creation of the file in /tmp.
1118\layout Quote
1119
1120If you do not define LogSQLPreserveFile then all virtual servers will log
1121 to the same default preserve file (/tmp/mysql-preserve).
1122 You can redefine this on a virtual-host basis in order to segregate your
1123 preserve files if you desire.
1124 Note that segregation is not really necessary, as the SQL statements that
1125 are written to the preserve file already distinguish between different
1126 virtual hosts.
1127\layout Quote
1128
1129The module will log to error-log if/when it notices a database outage, and
1130 upon database return.
1131 You will therefore know when the preserve file is being used, although
1132 it is your responsibility to import the file.
1133\layout Quote
1134
1135The file does not need to be created in advance.
1136 It is safe to remove or rename the file without interrupting Apache, as
1137 the module closes the filehandle immediately after completing the write.
1138 The file is created with the user & group ID of the running Apache process
1139 (e.g.
1140 'nobody' on many Linux distributions).
1141\layout Subsubsection
1142
1143LogSQLSocketFile
1144\layout LyX-Code
1145
1146Syntax: LogSQLSocketFile filename
1147\layout LyX-Code
1148
1149Example: LogSQLSocketFile /tmp/mysql.sock
1150\layout LyX-Code
1151
1152Default: /var/lib/mysql/mysql.sock
1153\layout LyX-Code
1154
1155Context: server config
1156\layout Quote
1157
1158At Apache runtime you can specify the MySQL socket file to use.
1159 Set this once in your main server config to override the default value.
1160 This value is irrelevant if your database resides on a separate machine.
1161\layout Quote
1162
1163mod_log_sql will automatically employ the socket for db communications if
1164 the database resides on the local host.
1165 If the db resides on a separate host the module will automatically use
1166 TCP/IP.
1167 This is a function of the MySQL API and is not user-configurable.
1168\layout Subsubsection
1169
1170LogSQLTransferLogFormat
1171\layout LyX-Code
1172
1173Syntax: LogSQLTransferLogFormat format-string
1174\layout LyX-Code
1175
1176Example: LogSQLTransferLogFormat huSUTv
1177\layout LyX-Code
1178
1179Default: AbHhmRSsTUuv
1180\layout LyX-Code
1181
1182Context: virtual host
1183\layout Quote
1184
1185Each character in the format-string defines an attribute of the request
1186 that you wish to log.
1187 The default logs the information required to create Combined Log Format
1188 logs, plus several extras.
1189 Here is the full list of allowable keys, which sometimes resemble their
1190 Apache counterparts, but do not always:
1191\layout Quote
1192
1193
1194\begin_inset Tabular
1195<lyxtabular version="2" rows="20" columns="5">
1196<features rotate="false" islongtable="false" endhead="1" endfirsthead="1" endfoot="0" endlastfoot="0">
1197<column alignment="center" valignment="top" leftline="true" rightline="true" width="" special="">
1198<column alignment="left" valignment="top" leftline="false" rightline="false" width="" special="">
1199<column alignment="left" valignment="top" leftline="true" rightline="true" width="" special="">
1200<column alignment="left" valignment="top" leftline="false" rightline="false" width="" special="">
1201<column alignment="left" valignment="top" leftline="true" rightline="true" width="" special="">
1202<row topline="true" bottomline="true" newpage="false">
1203<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1204\begin_inset Text
1205
1206\layout Standard
1207
1208
1209\series bold
1210Character
1211\end_inset
1212</cell>
1213<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1214\begin_inset Text
1215
1216\layout Standard
1217
1218
1219\series bold
1220What is this?
1221\end_inset
1222</cell>
1223<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1224\begin_inset Text
1225
1226\layout Standard
1227
1228
1229\series bold
1230MySQL DB field
1231\end_inset
1232</cell>
1233<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1234\begin_inset Text
1235
1236\layout Standard
1237
1238
1239\series bold
1240Recommended column type
1241\end_inset
1242</cell>
1243<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1244\begin_inset Text
1245
1246\layout Standard
1247
1248
1249\series bold
1250Example
1251\end_inset
1252</cell>
1253</row>
1254<row topline="true" bottomline="false" newpage="false">
1255<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1256\begin_inset Text
1257
1258\layout Standard
1259
1260A
1261\end_inset
1262</cell>
1263<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1264\begin_inset Text
1265
1266\layout Standard
1267
1268User agent
1269\end_inset
1270</cell>
1271<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1272\begin_inset Text
1273
1274\layout Standard
1275
1276agent
1277\end_inset
1278</cell>
1279<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1280\begin_inset Text
1281
1282\layout Standard
1283
1284varchar(255)
1285\end_inset
1286</cell>
1287<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1288\begin_inset Text
1289
1290\layout Standard
1291
1292Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0)
1293\end_inset
1294</cell>
1295</row>
1296<row topline="true" bottomline="false" newpage="false">
1297<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1298\begin_inset Text
1299
1300\layout Standard
1301
1302b
1303\end_inset
1304</cell>
1305<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1306\begin_inset Text
1307
1308\layout Standard
1309
1310Bytes transfered
1311\end_inset
1312</cell>
1313<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1314\begin_inset Text
1315
1316\layout Standard
1317
1318bytes_sent
1319\end_inset
1320</cell>
1321<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1322\begin_inset Text
1323
1324\layout Standard
1325
1326int unsigned
1327\end_inset
1328</cell>
1329<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1330\begin_inset Text
1331
1332\layout Standard
1333
133432561
1335\end_inset
1336</cell>
1337</row>
1338<row topline="true" bottomline="false" newpage="false">
1339<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1340\begin_inset Text
1341
1342\layout Standard
1343
1344c
1345\end_inset
1346</cell>
1347<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1348\begin_inset Text
1349
1350\layout Standard
1351
1352Text of cookie
1353\end_inset
1354</cell>
1355<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1356\begin_inset Text
1357
1358\layout Standard
1359
1360cookie
1361\end_inset
1362</cell>
1363<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1364\begin_inset Text
1365
1366\layout Standard
1367
1368varchar(255)
1369\end_inset
1370</cell>
1371<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1372\begin_inset Text
1373
1374\layout Standard
1375
1376Apache=sdyn.fooonline.net.130051007102700823
1377\end_inset
1378</cell>
1379</row>
1380<row topline="true" bottomline="false" newpage="false">
1381<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1382\begin_inset Text
1383
1384\layout Standard
1385
1386f
1387\end_inset
1388</cell>
1389<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1390\begin_inset Text
1391
1392\layout Standard
1393
1394\end_inset
1395</cell>
1396<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1397\begin_inset Text
1398
1399\layout Standard
1400
1401request_file
1402\end_inset
1403</cell>
1404<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1405\begin_inset Text
1406
1407\layout Standard
1408
1409varchar(255)
1410\end_inset
1411</cell>
1412<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1413\begin_inset Text
1414
1415\layout Standard
1416
1417\end_inset
1418</cell>
1419</row>
1420<row topline="true" bottomline="false" newpage="false">
1421<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1422\begin_inset Text
1423
1424\layout Standard
1425
1426H
1427\end_inset
1428</cell>
1429<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1430\begin_inset Text
1431
1432\layout Standard
1433
1434HTTP request protocol
1435\end_inset
1436</cell>
1437<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1438\begin_inset Text
1439
1440\layout Standard
1441
1442request_protocol
1443\end_inset
1444</cell>
1445<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1446\begin_inset Text
1447
1448\layout Standard
1449
1450varchar(10)
1451\end_inset
1452</cell>
1453<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1454\begin_inset Text
1455
1456\layout Standard
1457
1458HTTP/1.1
1459\end_inset
1460</cell>
1461</row>
1462<row topline="true" bottomline="false" newpage="false">
1463<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1464\begin_inset Text
1465
1466\layout Standard
1467
1468h
1469\end_inset
1470</cell>
1471<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1472\begin_inset Text
1473
1474\layout Standard
1475
1476Name of remote host
1477\end_inset
1478</cell>
1479<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1480\begin_inset Text
1481
1482\layout Standard
1483
1484remote_host
1485\end_inset
1486</cell>
1487<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1488\begin_inset Text
1489
1490\layout Standard
1491
1492varchar(50)
1493\end_inset
1494</cell>
1495<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1496\begin_inset Text
1497
1498\layout Standard
1499
1500blah.foobar.com
1501\end_inset
1502</cell>
1503</row>
1504<row topline="true" bottomline="false" newpage="false">
1505<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1506\begin_inset Text
1507
1508\layout Standard
1509
1510I
1511\end_inset
1512</cell>
1513<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1514\begin_inset Text
1515
1516\layout Standard
1517
1518Ident user info
1519\end_inset
1520</cell>
1521<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1522\begin_inset Text
1523
1524\layout Standard
1525
1526remote_logname
1527\end_inset
1528</cell>
1529<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1530\begin_inset Text
1531
1532\layout Standard
1533
1534varchar(50)
1535\end_inset
1536</cell>
1537<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1538\begin_inset Text
1539
1540\layout Standard
1541
1542bobby
1543\end_inset
1544</cell>
1545</row>
1546<row topline="true" bottomline="false" newpage="false">
1547<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1548\begin_inset Text
1549
1550\layout Standard
1551
1552m
1553\end_inset
1554</cell>
1555<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1556\begin_inset Text
1557
1558\layout Standard
1559
1560HTTP request method
1561\end_inset
1562</cell>
1563<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1564\begin_inset Text
1565
1566\layout Standard
1567
1568request_method
1569\end_inset
1570</cell>
1571<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1572\begin_inset Text
1573
1574\layout Standard
1575
1576varchar(6)
1577\end_inset
1578</cell>
1579<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1580\begin_inset Text
1581
1582\layout Standard
1583
1584GET
1585\end_inset
1586</cell>
1587</row>
1588<row topline="true" bottomline="false" newpage="false">
1589<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1590\begin_inset Text
1591
1592\layout Standard
1593
1594P
1595\end_inset
1596</cell>
1597<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1598\begin_inset Text
1599
1600\layout Standard
1601
1602httpd child PID
1603\end_inset
1604</cell>
1605<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1606\begin_inset Text
1607
1608\layout Standard
1609
1610child_pid
1611\end_inset
1612</cell>
1613<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1614\begin_inset Text
1615
1616\layout Standard
1617
1618smallint unsigned
1619\end_inset
1620</cell>
1621<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1622\begin_inset Text
1623
1624\layout Standard
1625
16263215
1627\end_inset
1628</cell>
1629</row>
1630<row topline="true" bottomline="false" newpage="false">
1631<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1632\begin_inset Text
1633
1634\layout Standard
1635
1636p
1637\end_inset
1638</cell>
1639<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1640\begin_inset Text
1641
1642\layout Standard
1643
1644httpd port
1645\end_inset
1646</cell>
1647<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1648\begin_inset Text
1649
1650\layout Standard
1651
1652server_port
1653\end_inset
1654</cell>
1655<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1656\begin_inset Text
1657
1658\layout Standard
1659
1660smallint unsigned
1661\end_inset
1662</cell>
1663<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1664\begin_inset Text
1665
1666\layout Standard
1667
166880
1669\end_inset
1670</cell>
1671</row>
1672<row topline="true" bottomline="false" newpage="false">
1673<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1674\begin_inset Text
1675
1676\layout Standard
1677
1678R
1679\end_inset
1680</cell>
1681<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1682\begin_inset Text
1683
1684\layout Standard
1685
1686Referer
1687\end_inset
1688</cell>
1689<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1690\begin_inset Text
1691
1692\layout Standard
1693
1694referer
1695\end_inset
1696</cell>
1697<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1698\begin_inset Text
1699
1700\layout Standard
1701
1702varchar(255)
1703\end_inset
1704</cell>
1705<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1706\begin_inset Text
1707
1708\layout Standard
1709
1710http://www.biglinkstoyou.com/linkpage.html
1711\end_inset
1712</cell>
1713</row>
1714<row topline="true" bottomline="false" newpage="false">
1715<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1716\begin_inset Text
1717
1718\layout Standard
1719
1720r
1721\end_inset
1722</cell>
1723<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1724\begin_inset Text
1725
1726\layout Standard
1727
1728Request in full form
1729\end_inset
1730</cell>
1731<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1732\begin_inset Text
1733
1734\layout Standard
1735
1736request_line
1737\end_inset
1738</cell>
1739<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1740\begin_inset Text
1741
1742\layout Standard
1743
1744varchar(255)
1745\end_inset
1746</cell>
1747<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1748\begin_inset Text
1749
1750\layout Standard
1751
1752GET /books-cycroad.html HTTP/1.1
1753\end_inset
1754</cell>
1755</row>
1756<row topline="true" bottomline="false" newpage="false">
1757<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1758\begin_inset Text
1759
1760\layout Standard
1761
1762S
1763\end_inset
1764</cell>
1765<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1766\begin_inset Text
1767
1768\layout Standard
1769
1770Time of request in UNIX format
1771\end_inset
1772</cell>
1773<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1774\begin_inset Text
1775
1776\layout Standard
1777
1778time_stamp
1779\end_inset
1780</cell>
1781<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1782\begin_inset Text
1783
1784\layout Standard
1785
1786int unsigned
1787\end_inset
1788</cell>
1789<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1790\begin_inset Text
1791
1792\layout Standard
1793
17941005598029
1795\end_inset
1796</cell>
1797</row>
1798<row topline="true" bottomline="false" newpage="false">
1799<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1800\begin_inset Text
1801
1802\layout Standard
1803
1804s
1805\end_inset
1806</cell>
1807<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1808\begin_inset Text
1809
1810\layout Standard
1811
1812HTTP status of request
1813\end_inset
1814</cell>
1815<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1816\begin_inset Text
1817
1818\layout Standard
1819
1820status
1821\end_inset
1822</cell>
1823<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1824\begin_inset Text
1825
1826\layout Standard
1827
1828smallint unsigned
1829\end_inset
1830</cell>
1831<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1832\begin_inset Text
1833
1834\layout Standard
1835
1836404
1837\end_inset
1838</cell>
1839</row>
1840<row topline="true" bottomline="false" newpage="false">
1841<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1842\begin_inset Text
1843
1844\layout Standard
1845
1846T
1847\end_inset
1848</cell>
1849<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1850\begin_inset Text
1851
1852\layout Standard
1853
1854Seconds to service request
1855\end_inset
1856</cell>
1857<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1858\begin_inset Text
1859
1860\layout Standard
1861
1862request_duration
1863\end_inset
1864</cell>
1865<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1866\begin_inset Text
1867
1868\layout Standard
1869
1870smallint unsigned
1871\end_inset
1872</cell>
1873<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1874\begin_inset Text
1875
1876\layout Standard
1877
18782
1879\end_inset
1880</cell>
1881</row>
1882<row topline="true" bottomline="false" newpage="false">
1883<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1884\begin_inset Text
1885
1886\layout Standard
1887
1888t
1889\end_inset
1890</cell>
1891<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1892\begin_inset Text
1893
1894\layout Standard
1895
1896Time of request in human format
1897\end_inset
1898</cell>
1899<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1900\begin_inset Text
1901
1902\layout Standard
1903
1904request_time
1905\end_inset
1906</cell>
1907<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1908\begin_inset Text
1909
1910\layout Standard
1911
1912char(28)
1913\end_inset
1914</cell>
1915<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1916\begin_inset Text
1917
1918\layout Standard
1919
1920[02/Dec/2001:15:01:26 -0800]
1921\end_inset
1922</cell>
1923</row>
1924<row topline="true" bottomline="false" newpage="false">
1925<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1926\begin_inset Text
1927
1928\layout Standard
1929
1930U
1931\end_inset
1932</cell>
1933<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1934\begin_inset Text
1935
1936\layout Standard
1937
1938Request in simple form
1939\end_inset
1940</cell>
1941<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1942\begin_inset Text
1943
1944\layout Standard
1945
1946request_uri
1947\end_inset
1948</cell>
1949<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1950\begin_inset Text
1951
1952\layout Standard
1953
1954varchar(255)
1955\end_inset
1956</cell>
1957<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1958\begin_inset Text
1959
1960\layout Standard
1961
1962/books-cycroad.html
1963\end_inset
1964</cell>
1965</row>
1966<row topline="true" bottomline="false" newpage="false">
1967<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1968\begin_inset Text
1969
1970\layout Standard
1971
1972u
1973\end_inset
1974</cell>
1975<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1976\begin_inset Text
1977
1978\layout Standard
1979
1980User info from HTTP authentication
1981\end_inset
1982</cell>
1983<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1984\begin_inset Text
1985
1986\layout Standard
1987
1988remote_user
1989\end_inset
1990</cell>
1991<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
1992\begin_inset Text
1993
1994\layout Standard
1995
1996varchar(50)
1997\end_inset
1998</cell>
1999<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
2000\begin_inset Text
2001
2002\layout Standard
2003
2004bobby
2005\end_inset
2006</cell>
2007</row>
2008<row topline="true" bottomline="true" newpage="false">
2009<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
2010\begin_inset Text
2011
2012\layout Standard
2013
2014v
2015\end_inset
2016</cell>
2017<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
2018\begin_inset Text
2019
2020\layout Standard
2021
2022Virtual host servicing the request
2023\end_inset
2024</cell>
2025<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
2026\begin_inset Text
2027
2028\layout Standard
2029
2030virtual_host
2031\end_inset
2032</cell>
2033<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
2034\begin_inset Text
2035
2036\layout Standard
2037
2038varchar(50)
2039\end_inset
2040</cell>
2041<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
2042\begin_inset Text
2043
2044\layout Standard
2045
2046www.foobar.com
2047\end_inset
2048</cell>
2049</row>
2050</lyxtabular>
2051
2052\end_inset
2053
2054
2055\layout Quote
2056
2057If you have compiled mod_log_sql with WANT_SSL_LOGGING, you also get these:
2058\layout Quote
2059
2060
2061\begin_inset Tabular
2062<lyxtabular version="2" rows="4" columns="4">
2063<features rotate="false" islongtable="false" endhead="0" endfirsthead="0" endfoot="0" endlastfoot="0">
2064<column alignment="center" valignment="top" leftline="true" rightline="false" width="" special="">
2065<column alignment="left" valignment="top" leftline="true" rightline="false" width="" special="">
2066<column alignment="left" valignment="top" leftline="true" rightline="false" width="" special="">
2067<column alignment="left" valignment="top" leftline="true" rightline="true" width="" special="">
2068<row topline="true" bottomline="true" newpage="false">
2069<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
2070\begin_inset Text
2071
2072\layout Standard
2073
2074
2075\series bold
2076Character
2077\end_inset
2078</cell>
2079<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
2080\begin_inset Text
2081
2082\layout Standard
2083
2084
2085\series bold
2086MySQL DB field it activates
2087\end_inset
2088</cell>
2089<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
2090\begin_inset Text
2091
2092\layout Standard
2093
2094
2095\series bold
2096MySQL DB field it activatesRecommended column type
2097\end_inset
2098</cell>
2099<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="true" rotate="false" usebox="none" width="" special="">
2100\begin_inset Text
2101
2102\layout Standard
2103
2104
2105\series bold
2106Example
2107\end_inset
2108</cell>
2109</row>
2110<row topline="true" bottomline="false" newpage="false">
2111<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
2112\begin_inset Text
2113
2114\layout Standard
2115
2116z
2117\end_inset
2118</cell>
2119<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
2120\begin_inset Text
2121
2122\layout Standard
2123
2124ssl_cipher
2125\end_inset
2126</cell>
2127<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
2128\begin_inset Text
2129
2130\layout Standard
2131
2132varchar(25)
2133\end_inset
2134</cell>
2135<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="true" rotate="false" usebox="none" width="" special="">
2136\begin_inset Text
2137
2138\layout Standard
2139
2140RC4-MD5
2141\end_inset
2142</cell>
2143</row>
2144<row topline="true" bottomline="false" newpage="false">
2145<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
2146\begin_inset Text
2147
2148\layout Standard
2149
2150q
2151\end_inset
2152</cell>
2153<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
2154\begin_inset Text
2155
2156\layout Standard
2157
2158ssl_keysize
2159\end_inset
2160</cell>
2161<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
2162\begin_inset Text
2163
2164\layout Standard
2165
2166smallint unsigned
2167\end_inset
2168</cell>
2169<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="true" rotate="false" usebox="none" width="" special="">
2170\begin_inset Text
2171
2172\layout Standard
2173
217456
2175\end_inset
2176</cell>
2177</row>
2178<row topline="true" bottomline="true" newpage="false">
2179<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
2180\begin_inset Text
2181
2182\layout Standard
2183
2184Q
2185\end_inset
2186</cell>
2187<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
2188\begin_inset Text
2189
2190\layout Standard
2191
2192ssl_maxkeysize
2193\end_inset
2194</cell>
2195<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="false" rotate="false" usebox="none" width="" special="">
2196\begin_inset Text
2197
2198\layout Standard
2199
2200smallint unsigned
2201\end_inset
2202</cell>
2203<cell multicolumn="0" alignment="center" valignment="top" topline="true" bottomline="false" leftline="true" rightline="true" rotate="false" usebox="none" width="" special="">
2204\begin_inset Text
2205
2206\layout Standard
2207
2208128
2209\end_inset
2210</cell>
2211</row>
2212</lyxtabular>
2213
2214\end_inset
2215
2216
2217\layout Section
2218
2219FAQ
2220\layout Subsection
2221
2222Why log to an SQL database?
2223\layout Standard
2224
2225To begin with, let's get it out of the way: logging to a database is not
2226 a panacea.
2227 But while there are complexities with this solution, the benefit can be
2228 substantial for certain classes of administrator or people with advanced
2229 requirements:
2230\layout Itemize
2231
2232Chores like log rotation go away, as you can DELETE records from the SQL
2233 database once they are no longer useful.
2234 For example, the excellent and popular log-analysis tool Webalizer (http://www.w
2235ebalizer.com/) does not need historic logs after it has processed them, enabling
2236 you to delete older logs.
2237
2238\layout Itemize
2239
2240People with clusters of web servers (for high availability) will benefit
2241 the most -- all their webservers can log to a single SQL database.
2242 This obviates the need to collate/interleave the many separate logfiles,
2243 which can be / highly/ problematic.
2244
2245\layout Itemize
2246
2247People acquainted with the power of SQL SELECT statements will know the
2248 flexibility of the extraction possibilities at their fingertips.
2249\layout Standard
2250
2251For example, do you want to see all your 404's? Do this:
2252\layout LyX-Code
2253
2254select remote_host,status,request_uri,bytes_sent,from_unixtime(time_stamp)
2255 from acc_log_tbl where status=404 order by time_stamp;
2256\layout LyX-Code
2257
2258+-----------------------------------+--------+--------------------------+-------
2259-----+---------------------------
2260\layout LyX-Code
2261
2262+ remote_host | status | request_uri
2263 | bytes_sent | from_unixtime(time_stamp)|
2264\layout LyX-Code
2265
2266+-----------------------------------+--------+--------------------------+-------
2267-----+---------------------------
2268\layout LyX-Code
2269
2270| marge.mmm.co.uk | 404 | /favicon.ico | 321
2271 | 2001-11-20 02:30:56 |
2272\layout LyX-Code
2273
2274| 62.180.239.251 | 404 | /favicon.ico | 333
2275 | 2001-11-20 02:45:25 |
2276\layout LyX-Code
2277
2278| 212.234.12.66 | 404 | /favicon.ico | 321
2279 | 2001-11-20 03:01:00 |
2280\layout LyX-Code
2281
2282| 212.210.78.254 | 404 | /favicon.ico | 333
2283 | 2001-11-20 03:26:05 |
2284\layout LyX-Code
2285
2286+-----------------------------------+--------+--------------------------+-------
2287-----+---------------------------+
2288\layout Standard
2289
2290Or do you want to see how many bytes you've sent within a certain directory
2291 or site? Do this:
2292\layout LyX-Code
2293
2294select request_uri,sum(bytes_sent) as bytes,count(request_uri) as howmany
2295 from acc_log_tbl where request_uri like '%mod_log_sql%' group by request_uri
2296 order by howmany desc;
2297\layout LyX-Code
2298
2299+-----------------------------------+---------+---------+
2300\layout LyX-Code
2301
2302| request_uri | bytes | howmany |
2303\layout LyX-Code
2304
2305+-----------------------------------+---------+---------+
2306\layout LyX-Code
2307
2308| /mod_log_sql/style_1.css | 157396 | 1288 |
2309\layout LyX-Code
2310
2311| /mod_log_sql/ | 2514337 | 801 |
2312\layout LyX-Code
2313
2314| /mod_log_sql/mod_log_sql.tar.gz | 9769312 | 456 |
2315\layout LyX-Code
2316
2317| /mod_log_sql/faq.html | 5038728 | 436 |
2318\layout LyX-Code
2319
2320| /mod_log_sql/INSTALL | 1196161 | 202 |
2321\layout LyX-Code
2322
2323| /mod_log_sql/directives.html | 1096821 | 171 |
2324\layout LyX-Code
2325
2326| /mod_log_sql/CHANGELOG | 424481 | 107 |
2327\layout LyX-Code
2328
2329| /mod_log_sql/README | 796072 | 97 |
2330\layout LyX-Code
2331
2332| /mod_log_sql/directives-old.html | 42480 | 6 |
2333\layout LyX-Code
2334
2335| /mod_log_sql/index.html | 9531 | 3 |
2336\layout LyX-Code
2337
2338+-----------------------------------+---------+---------+
2339\layout Standard
2340
2341Or maybe you want to see who's linking to you? Do this:
2342\layout LyX-Code
2343
2344select count(referer) as num,referer from acc_log_tbl where request_uri='/mod_lo
2345g_sql/' group by referer order by num desc;
2346\layout LyX-Code
2347
2348+-----+-------------------------------------------------------------------------
2349------+
2350\layout LyX-Code
2351
2352| num | referer
2353 |
2354\layout LyX-Code
2355
2356+-----+-------------------------------------------------------------------------
2357------+
2358\layout LyX-Code
2359
2360| 271 | http://freshmeat.net/projects/mod_log_sql/
2361 |
2362\layout LyX-Code
2363
2364| 96 | http://modules.apache.org/search?id=339
2365 |
2366\layout LyX-Code
2367
2368| 48 | http://freshmeat.net/
2369 |
2370\layout LyX-Code
2371
2372| 8 | http://freshmeat.net
2373 |
2374\layout LyX-Code
2375
2376| 7 | http://freshmeat.net/daily/2001/11/30/
2377 |
2378\layout LyX-Code
2379
2380| 6 | http://freshmeat.net/daily/2001/11/20/
2381 |
2382\layout LyX-Code
2383
2384+-----+-------------------------------------------------------------------------
2385------+
2386\layout Standard
2387
2388As you can see, there are myriad possibilities that can be constructed with
2389 the wonderful SQL SELECT statement.
2390 Logging to an SQL database can be really quite useful!
2391\layout Subsection
2392
2393Why use MySQL? Are there alternatives?
2394\layout Standard
2395
2396MySQL is a robust, free, and very powerful production-quality database engine.
2397 It is well supported and comes with detailed documentation.
2398 Many 3rd-party software pacakges (e.g.
2399 Slashcode, the engine that powers Slashdot) run exclusively with MySQL.
2400 In other words, you will belong to a very robust and well-supported community
2401 by choosing MySQL.
2402\layout Standard
2403
2404That being said, there are alternatives.
2405 PostgreSQL is probably MySQL's leading "competitor" in the free database
2406 world.
2407 There is also an excellent module available for Apache to permit logging
2408 to a PostgreSQL database, called
2409\begin_inset LatexCommand \url[pgLOGd]{(http://www.digitalstratum.com/pglogd/)}
2410
2411\end_inset
2412
2413.
2414\layout Subsection
2415
2416Is this code production-ready?
2417\layout Standard
2418
2419By all accounts it is.
2420 It is known to work without a problem on many-thousands-of-hits-per-day
2421 webservers.
2422 Does that mean it is 100% bug free? Well, no software is.
2423 But it is well-tested and /believed/ to be fully compatible with production
2424 environments.
2425 (The usual disclaimers apply.
2426 This software is provided without warranty of any kind.)
2427\layout Subsection
2428
2429How well does it perform?
2430\layout Standard
2431
2432mod_log_sql scales to very high loads.
2433 Apache 1.3.22 + mod_log_sql was benchmarked using the "ab" (Apache Bench)
2434 program that comes with the Apache distribution; here are the results.
2435\layout Standard
2436
2437Overall configuration:
2438\layout Itemize
2439
2440Machine A: Apache webserver
2441\layout Itemize
2442
2443Machine B: MySQL server
2444\layout Itemize
2445
2446Machines A and B connected with 100Mbps Ethernet
2447\layout Standard
2448
2449Webserver configuration:
2450\layout Itemize
2451
2452Celeron 400 128 MB RAM IDE storage
2453\layout Standard
2454
2455Apache configuration:
2456\layout LyX-Code
2457
2458Timeout 300
2459\layout LyX-Code
2460
2461KeepAlive On
2462\layout LyX-Code
2463
2464MaxKeepAliveRequests 100
2465\layout LyX-Code
2466
2467KeepAliveTimeout 15
2468\layout LyX-Code
2469
2470MinSpareServers 5
2471\layout LyX-Code
2472
2473StartServers 10
2474\layout LyX-Code
2475
2476MaxSpareServers 15
2477\layout LyX-Code
2478
2479MaxClients 256
2480\layout LyX-Code
2481
2482MaxRequestsPerChild 5000
2483\layout LyX-Code
2484
2485LogSQLTransferLogFormat AbHhmRSsTUuvc
2486\layout LyX-Code
2487
2488LogSQLWhichCookie Clicks
2489\layout LyX-Code
2490
2491CookieTracking on
2492\layout LyX-Code
2493
2494CookieName Clicks
2495\layout Standard
2496
2497"ab" commandline:
2498\layout LyX-Code
2499
2500./ab -c 10 -t 20 -v 2 -C Clicks=ab_run http://www.hostname.com/target
2501\layout Standard
2502
2503( 10 concurrent requests; 20 second test; setting a cookie "Clicks=ab_run";
2504 target = the mod_log_sql homepage.
2505 )
2506\layout Standard
2507
2508Ten total ab runs were conducted: five with MySQL logging enabled, and five
2509 with all MySQL directives commented out of httpd.conf.
2510 Then each five were averaged.
2511 The results:
2512\layout Itemize
2513
2514Average of five runs employing MySQL
2515\emph on
2516and
2517\emph default
2518 standard text logging: 139.01 requests per second, zero errors.
2519\layout Itemize
2520
2521Average of five runs employing
2522\emph on
2523only
2524\emph default
2525 standard text logging: 139.96 requests per second, zero errors.
2526\layout Standard
2527
2528In other words, any rate-limiting effects on this particular hardware setup
2529 are not caused by MySQL.
2530 Note that although this very simple webserver setup is hardly cutting-edge
2531 -- it is, after all, a fairly small machine -- 139 requests per second
2532 equal over twelve million hits per day
2533\emph on
2534.
2535\layout Standard
2536
2537If you run this benchmark yourself, take note of three things:
2538\layout Enumerate
2539
2540Use a target URL that is on your own webserver :-).
2541
2542\layout Enumerate
2543
2544Wait until all your connections are closed out between runs; after several
2545 thousand requests your TCP/IP stack will be filled with hundreds of connections
2546 in TIME_WAIT that need to close.
2547 Do a "netstat -t|wc -l" on the webserver to see.
2548 If you don't wait, you can expect to see a lot of messages like "ip_conntrack:
2549 table full, dropping packet" in your logs.
2550 (This has nothing to do with mod_log_sql, this is simply the nature of
2551 the TCP/IP stack in the Linux kernel.)
2552\layout Enumerate
2553
2554When done with your runs, clean these many thousands of requests out of
2555 your database:
2556\layout LyX-Code
2557
2558mysql> delete from access_log where agent like 'ApacheBench%'; mysql> optimize
2559 table access_log;
2560\layout Subsection
2561
2562Who's using mod_log_sql?
2563\layout Standard
2564
2565Good question! It would be great to find out! If you are a production-level
2566 mod_log_sql user, please contact
2567\begin_inset LatexCommand \url[the maintainer, Chris Powell]{chris@grubbybaby.com}
2568
2569\end_inset
2570
2571so that you can be mentioned here.
2572\layout Subsection
2573
2574How do I extract the data in a format that my analysis tool can understand?
2575\layout Standard
2576
2577mod_log_sql would be virtually useless if there weren't a way for you to
2578 extract the data from your database in a somewhat meaningful fashion.
2579 To that end there's a Perl script enclosed with the distribution.
2580 That script (make_combined_log.pl) is designed to extract N-many days worth
2581 of access logs and provide them in a Combined Log Format output.
2582 You can use this very tool right in /etc/crontab to extract logs on a regular
2583 basis so that your favorite web analysis tool can read them.
2584 Or you can examine the Perl code to construct your own custom tool.
2585\layout Standard
2586
2587For example, let's say that you want your web statistics updated once per
2588 day in the wee hours of the morning.
2589 A good way to accomplish that would be the following entries in /etc/crontab:
2590\layout LyX-Code
2591
2592# Generate the temporary apache logs from the MySQL database (for webalizer)
2593
2594\layout LyX-Code
2595
259605 04 * * * root /usr/local/sbin/make_combined_log.pl 1 www.grubbybaby.com
2597 > /var/log/httpd/mysql-grubbybaby
2598\layout LyX-Code
2599
2600# Run webalizer on httpd log
2601\layout LyX-Code
2602
260330 04 * * * root /usr/local/bin/webalizer -c /etc/webalizer.conf; rm -f /var/log/
2604httpd/mysql-grubbybaby
2605\layout Standard
2606
2607Or if you have a newer system that puts files in /etc/cron.daily etc., create
2608 a file called
2609\begin_inset Quotes sld
2610\end_inset
2611
2612webalizer
2613\begin_inset Quotes srd
2614\end_inset
2615
2616 in the cron.____ subdir of your choice.
2617 Use the following as the contents of your file, and make sure to chmod
2618 755 it when done.
2619\layout LyX-Code
2620
2621#!/bin/sh
2622\layout LyX-Code
2623
2624/usr/local/sbin/make_combined_log.pl 1 www.yourdomain.com > /var/log/httpd/templog
2625\layout LyX-Code
2626
2627/usr/local/bin/webalizer -q -c /etc/webalizer.conf
2628\layout LyX-Code
2629
2630rm -f /var/log/httpd/templog
2631\layout Standard
2632
2633See? Easy.
2634\layout Subsection
2635
2636Why doesn't the module also replace the Apache ErrorLog?
2637\layout Standard
2638
2639There are circumstances when that would be quite unwise -- for example,
2640 if Apache could not reach the MySQL server for some reason and needed to
2641 log that fact.
2642 Without a text-based error log you'd never know anything was wrong, because
2643 Apache would be trying to log a database connection error to the database...
2644 you get the point.
2645\layout Standard
2646
2647Error logs are usually not very high-traffic and are really best left as
2648 text files on a web server machine.
2649\layout Subsection
2650
2651
2652\begin_inset LatexCommand \label{sec:cookie}
2653
2654\end_inset
2655
2656How can I log mod_usertrack cookies?
2657\layout Standard
2658
2659A number of people like to log mod_usertrack cookies in their Apache TransferLog
2660 to aid in understanding their visitors' clickstreams.
2661 This is accomplished, for example, with a statement as follows:
2662\layout LyX-Code
2663
2664LogFormat "%h %l %u %t
2665\backslash
2666"%r
2667\backslash
2668" %s %b
2669\backslash
2670"%{Referer}i
2671\backslash
2672"
2673\backslash
2674"%{User-Agent}i
2675\backslash
2676""
2677\backslash
2678"%{cookie}n
2679\backslash
2680""
2681\layout Standard
2682
2683Naturally it would be nice for mod_log_sql to permit the admin to log the
2684 cookie data as well, so as of version 1.10 you can do this.
2685 You need to have already compiled mod_usertrack into httpd -- it's one
2686 of the standard Apache modules.
2687\layout Standard
2688
2689First make sure you have a column called "cookie" in the MySQL database
2690 to hold the cookies, which can be done as follows if you already have a
2691 working database:
2692\layout LyX-Code
2693
2694alter table acc_log_tbl add column cookie varchar(255);
2695\layout Standard
2696
2697Next configure your server to set usertracking cookies as follows, and make
2698 sure you include the new 'c' directive in your LogSQLTransferLogFormat,
2699 which activates cookie logging.
2700 Here's an example:
2701\layout LyX-Code
2702
2703<VirtualHost 1.2.3.4>
2704\layout LyX-Code
2705
2706 CookieTracking on
2707\layout LyX-Code
2708
2709 CookieStyle Cookie
2710\layout LyX-Code
2711
2712 CookieName Foobar
2713\layout LyX-Code
2714
2715 LogSQLTransferLogFormat huSUsbTvRAc
2716\layout LyX-Code
2717
2718 LogSQLWhichCookie Foobar
2719\layout LyX-Code
2720
2721</VirtualHost>
2722\layout Standard
2723
2724The first three lines configure mod_usertrack to create a COOKIE (RFC 2109)
2725 format cookie called Foobar.
2726 The last two lines tell mod_log_sql to log cookies named Foobar.
2727 You have to choose which cookie to log because more than one cookie can/will
2728 be sent to the server by the client.
2729\layout Standard
2730
2731FYI, you are advised NOT to use CookieStyle Cookie2 -- it seems that even
2732 newer browsers (IE 5.5, etc.) have trouble with the new COOKIE2 (RFC 2965)
2733 format.
2734 Just stick with the standard COOKIE format and you'll be fine.
2735\layout Standard
2736
2737Perform some hits on your server and run a select:
2738\layout LyX-Code
2739
2740mysql> select request_uri,cookie from access_log where cookie is not null;
2741\layout LyX-Code
2742
2743+--------------------------------------------+----------------------------------
2744------------------+
2745\layout LyX-Code
2746
2747| request_uri |
2748 cookie |
2749\layout LyX-Code
2750
2751+--------------------------------------------+----------------------------------
2752------------------+
2753\layout LyX-Code
2754
2755| /mod_log_sql/ | ool-18e4.dyn.optonline.net.1300510071
275602700823 |
2757\layout LyX-Code
2758
2759| /mod_log_sql/usa.gif | ool-18e4.dyn.optonline.net.13005100710
27602700823 |
2761\layout LyX-Code
2762
2763| /mod_log_sql/style_1.css | ool-18e4.dyn.optonline.net.13005100710
27642700823 |
2765\layout LyX-Code
2766
2767...etc...
2768\layout Subsection
2769
2770What if I want to log more than one cookie?
2771\layout Standard
2772
2773No problem.
2774 As of version 1.17, you have a choice.
2775 If you are just interested in a single cookie, follow the instructions
2776 in section
2777\begin_inset LatexCommand \ref{sec:cookie}
2778
2779\end_inset
2780
2781 above.
2782 That cookie will be logged to a column in the regular access_log table.
2783\layout Standard
2784
2785However, if you need to log multiple cookies, you'll employ the LogSQLWhichCooki
2786es (note the plural) directive.
2787 The cookies you specify will be logged to a separate table, and entries
2788 in that table will be linked to the regular access_log entries via the
2789 unique ID that is supplied by mod_unique_id.
2790 Without mod_unique_id the information will still be logged but you will
2791 be unable to correlate which cookies go with which access-requests.
2792\layout Standard
2793
2794LogSQLWhichCookie and LogSQLWhichCookies can coexist without conflict, but
2795 you're better off choosing the one you need.
2796\layout Subsection
2797
2798What are the SSL logging features, and how do I activate them?
2799\layout Standard
2800
2801If you run an SSL-enabled server you may benefit from logging some SSL details.
2802 mod_log_sql now supports this ability.
2803 By adding certain characters to your LogSQLTransferLogFormat string you
2804 can tell mod_log_sql to log the SSL cipher, the SSL keysize of the connection,
2805 and the Max-keysize that was available.
2806 This would let you tell, for example, which clients were using only export-grad
2807e security to access your secure software area.
2808\layout Standard
2809
2810You can compile mod_log_sql with SSL logging support if you have the right
2811 packages installed.
2812 If you already have an SSL-enabled Apache then you by definition have the
2813 correct packages already installed: OpenSSL and mod_ssl.
2814\layout Standard
2815
2816You need to ensure that your database is set up to log the SSL data.
2817 Issue the following commands to MySQL once you have your basic access_log
2818 table built:
2819\layout LyX-Code
2820
2821alter table access_log add column ssl_cipher varchar(25);
2822\layout LyX-Code
2823
2824alter table access_log add column ssl_keysize smallint unsigned;
2825\layout LyX-Code
2826
2827alter table access_log add column ssl_maxkeysize smallint unsigned;
2828\layout Standard
2829
2830Finally configure httpd.conf to activate the SSL fields.
2831 Note that this is only meaningful in a VirtualHost that is set up for SSL.
2832\layout LyX-Code
2833
2834<VirtualHost 1.2.3.4:443>
2835\layout LyX-Code
2836
2837 LogSQLTransferLogFormat AbHhmRSsTUuvcQqz
2838\layout LyX-Code
2839
2840</VirtualHost>
2841\layout Standard
2842
2843The last three characters (Qqz) in the directive are the SSL ones; see the
2844 directives documentation for details.
2845\layout Standard
2846
2847Perform some hits on your server and run a select:
2848\layout LyX-Code
2849
2850mysql> select remote_host,request_uri,ssl_cipher,ssl_keysize,ssl_maxkeysize
2851 from access_log where ssl_cipher is not null;
2852\layout LyX-Code
2853
2854+--------------------------+----------------------------------------------------
2855+------------+-------------+----------------+
2856\layout LyX-Code
2857
2858| remote_host | request_uri
2859 | ssl_cipher | ssl_keysize | ssl_maxkeysize |
2860\layout LyX-Code
2861
2862+--------------------------+----------------------------------------------------
2863+------------+-------------+----------------+
2864\layout LyX-Code
2865
2866| 216.190.52.4 | /dir/somefile.html
2867 | RC4-MD5 | 128 | 128 |
2868\layout LyX-Code
2869
2870| 216.190.52.4 | /dir/somefile.gif
2871 | RC4-MD5 | 128 | 128 |
2872\layout LyX-Code
2873
2874| 216.190.52.4 | /dir/somefile.jpg
2875 | RC4-MD5 | 128 | 128 |
2876\layout LyX-Code
2877
2878...etc...
2879\layout Subsection
2880
2881Does mod_log_sql connect to MySQL via TCP/IP or a socket?
2882\layout Standard
2883
2884It depends! Actually this isn't determined by mod_log_sql.
2885 mod_log_sql relies on a connection command that is supplied in the MySQL
2886 API, and that command is somewhat intelligent.
2887 When mod_log_sql issues the connect command to MySQL, this intelligent
2888 connect command uses sockets to communicate with MySQL if the specified
2889 MySQL database is on the same machine (because sockets are more efficient
2890 than TCP/IP).
2891 However, if the specified MySQL db is on a different machine, mod_log_sql
2892 connects using TCP/IP.
2893 You don't have any control of which methodology is used.
2894\layout Standard
2895
2896You do have control over where mod_log_sql looks for the socket.
2897 The LogSQLSocketFile runtime configuration directive overrides the default
2898 of "/var/lib/mysql/mysql.sock" to whatever you wish.
2899 (Applies to mod_log_sql 1.16 or later only.)
2900\layout Subsection
2901
2902Why do I occasionally see a "connection lost, attempting reconnect" message
2903 in my error-log?
2904\layout Standard
2905
2906This message may appear every now and then in your Apache error log, especially
2907 on very lightly loaded servers.
2908 This doesn't mean that anything is necessarily wrong.
2909 Within each httpd child process, mod_log_sql will open (and keep open)
2910 a connection to the MySQL server.
2911 MySQL, however, will close connections that haven't been used in a while;
2912 the default timeout is 8 hours.
2913 When this occurs, mod_log_sql will notice and re-open the connection.
2914 That event is what is being logged, and looks like this:
2915\layout LyX-Code
2916
2917[Thu Dec 13 05:42:18 2001] [error] mod_log_sql: connection lost, attempting
2918 reconnect
2919\layout LyX-Code
2920
2921[Thu Dec 13 05:42:18 2001] [error] mod_log_sql: reconnect successful
2922\layout Standard
2923
2924Reference:
2925\begin_inset LatexCommand \url[MySQL documentation]{http://www.mysql.com/documentation/mysql/bychapter/manual_Problems.html#Gone_away}
2926
2927\end_inset
2928
2929
2930\layout Subsection
2931
2932Does mod_log_sql work with Apache 2.x?
2933\layout Standard
2934
2935As of this writing, no.
2936 The Apache Group significantly altered the module API with the release
2937 of Apache 2.0.
2938 All modules written for 1.3, including mod_log_sql, will not work with 2.0.
2939\layout Standard
2940
2941mod_log_sql will eventually be ported to Apache 2.x, but not immediately.
2942 It is going to take some time, and there are other features that have higher
2943 priority.
2944 Please sign up for the announcements list (on the main website) or monitor
2945 the website for updates to learn when the port (and other releases) are
2946 available.
2947\layout Standard
2948
2949<OPINION>If you're a *NIX user, stick with Apache 1.3.x for now.
2950 Major modules like mod_ssl and PHP are not even ready for 2.0 yet, and the
2951 main benefits in 2.0 are for Win32 users anyway.
2952 Apache 1.3.x is rock-stable and performs equally well on *NIX as 2.0.</OPINION>
2953\layout Subsection
2954
2955I have discovered a bug.
2956 Who can I contact?
2957\layout Standard
2958
2959Please contact
2960\begin_inset LatexCommand \url[the maintainer]{chris@grubbybaby.com}
2961
2962\end_inset
2963
2964! Your comments, suggestions, bugfixes, bug catches, and usage testimonials
2965 are always welcome.
2966 As free software, mod_log_sql is intended to be a community effort -- any
2967 code contributions or other ideas will be fully and openly credited, of
2968 course.
2969\the_end
diff --git a/Documentation/documentation.tex b/Documentation/documentation.tex
new file mode 100644
index 0000000..0eb6359
--- /dev/null
+++ b/Documentation/documentation.tex
@@ -0,0 +1,1534 @@
1%% LyX 1.1 created this file. For more info, see http://www.lyx.org/.
2%% Do not edit unless you really know what you are doing.
3\documentclass[10pt,english]{article}
4\usepackage[T1]{fontenc}
5\usepackage{geometry}
6\geometry{verbose,letterpaper,tmargin=0.5in,bmargin=1in,lmargin=1in,rmargin=1in}
7\usepackage{babel}
8\IfFileExists{url.sty}{\usepackage{url}}
9 {\newcommand{\url}{\texttt}}
10
11\makeatletter
12
13%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% LyX specific LaTeX commands.
14\providecommand{\LyX}{L\kern-.1667em\lower.25em\hbox{Y}\kern-.125emX\@}
15
16%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Textclass specific LaTeX commands.
17 \newenvironment{lyxcode}
18 {\begin{list}{}{
19 \setlength{\rightmargin}{\leftmargin}
20 \raggedright
21 \setlength{\itemsep}{0pt}
22 \setlength{\parsep}{0pt}
23 \normalfont\ttfamily}%
24 \item[]}
25 {\end{list}}
26
27\makeatother
28\begin{document}
29
30\vfill{}
31\title{Installing and Running mod\_log\_sql}
32\vfill{}
33
34
35\author{Christopher Powell }
36
37
38\date{11/13/02}
39
40\maketitle
41\tableofcontents{}
42\newpage
43
44
45\section{Introduction}
46
47
48\subsection{Homepage }
49
50\begin{lyxcode}
51http://www.grubbybaby.com/mod\_log\_sql/
52\end{lyxcode}
53
54\subsection{Summary}
55
56This Apache module will permit you to log Apache accesses (and a lot
57of related information) to a SQL database. Unlike logging to a flat
58text file (which is standard in Apache), there are a lot of powerful
59advantages to logging to SQL. This module can either replace or happily
60coexist with Apache's text file logging facility.
61
62
63\subsection{Approach}
64
65This project was formerly known as mod\_log\_mysql. It has been renamed
66to mod\_log\_sql in order to reflect the project goal of database-inspecificity.
67The module currently supports MySQL, and development for other database
68backends is underway.
69
70In order to save speed and overhead, links are kept alive in between
71queries. This module uses one SQL link per httpd child. Among other
72things, this means that this module supports logging into only one
73MySQL server, and for now, also, only one SQL database. But that's
74a small tradeoff compared to the blinding speed of this module.
75
76Virtual hosts are supported in the same manner they are in the regular
77logging modules. You define some basic 'global' directives in the
78main server config, then you define more specific 'local' directives
79inside each virtualhost stanza.
80
81SQL links are opened by each child process when it is born. Error
82reporting is robust throughout and will let you know about database
83issues in the standard Apache error-log for the server or virtual
84server.
85
86A robust \char`\"{}preserve\char`\"{} capability has now been implemented.
87This permits the module to preserve any failed INSERT commands to
88a local file on its machine. In any situation that the database is
89unavailable -- e.g. the network fails, you reboot the db host, etc.
90-- mod\_log\_sql will note this in the error log and begin appending
91its log entries to the preserve file (which is created with the user
92\& group ID of the running Apache process, e.g. \char`\"{}nobody\char`\"{}
93on many Linux installations). When your database becomes available
94again, mod\_log\_sql seamlessly resumes logging to it. When convenient
95for the sysadmin, he/she can easily import the preserve file into
96the database because it is simply a series of SQL insert statements:
97
98\begin{lyxcode}
99\#~mysql~-uadminuser~-p~mydbname~<~/tmp/mysql-preserve
100\end{lyxcode}
101
102\subsection{Supported directives}
103
104Please see the web-based documentation for full explanation of all
105supported run-time directives.
106
107http://www.grubbybaby.com/mod\_log\_sql/directives.html
108
109See the FAQ for some handy examples:
110
111http://www.grubbybaby.com/mod\_log\_sql/faq.html
112
113
114\subsection{What gets logged by default? }
115
116All the data that would be contained in the \char`\"{}Combined Log
117Format\char`\"{} is logged by default, plus a little extra. Your best
118bet is to begin by accepting this default, then later customize the
119log configuration based on your needs.
120
121The online documentation of the run-time directives includes a full
122explanation of what you can log, including examples.
123
124
125\subsection{Minor Notes}
126
127\begin{itemize}
128\item Note which directives go in the 'main server config' and which directives
129apply to the 'virtual host config'. This is made clear in the directive
130documentation.
131\item The 'time\_stamp' field is stored in an UNSIGNED INTEGER column, in
132the standard unix \char`\"{}seconds since 1/1/1970 12:00:00\char`\"{}
133format. This is superior to storing the access time as a string due
134to size requirements: an UNSIGNED INT type fits in 4 bytes, whereas
135the Apache date string (e.g. \char`\"{}18/Nov/2001:13:59:52 -0800\char`\"{})
136requires 26 bytes -- significantly larger, and those extra 22 bytes
137will add up over the thousands of accesses that a busy server will
138experience. Besides, an INT type is far more flexible for comparisons,
139etc.
140
141
142In MySQL 3.21 and above you can easily convert this to a human readable
143format using from\_unixtime(), e.g.:
144
145\begin{lyxcode}
146select~remote\_host,request\_uri,from\_unixtime(time\_stamp)~from~access\_log;
147\end{lyxcode}
148The enclosed perl program ''make\_combined\_log.pl'' shows how you
149can extract your access records in a format that is completely Combined
150Log Format compliant. You can then feed this to your favorite web
151log analysis tool.
152
153\item The table's string values can be CHAR or VARCHAR, at a length of your
154choice. VARCHAR is superior because it truncates long strings; CHAR
155types are fixed-length and will be padded with spaces. Just like the
156time\_stamp described above, that kind of space waste will add up
157over thousands of records.
158\item Be careful not to go overboard setting fields to NOT NULL. If a field
159is marked NOT NULL then it must contain data in the INSERT or the
160INSERT will fail, sometimes in a really mysterious way to the frustrated
161sysad.
162\item Apache normally logs numeric fields with a '-' character to mean \char`\"{}not
163applicable,\char`\"{} e.g. bytes\_sent on a request with a 304 response
164code. Since '-' is an illegal character in an SQL numeric field, such
165fields are assigned the value 0 instead of '-' which, of course, makes
166perfect sense anyway.
167\end{itemize}
168
169\subsection{Author / Maintainer}
170
171The actual logging code was taken from the already existing flat file
172text modules, so all that credit goes to the Apache Server group.
173
174The MySQL routines and directives were added by Zeev Suraski <bourbon@netvision.net.il>.
175
176All changes from 1.06+ and the new documentation were added by Chris
177Powell <chris@grubbybaby.com>. It seems that the module had fallen
178into the \char`\"{}unmaintained\char`\"{} category -- it hadn't been
179updated since 1998 -- so Chris adopted it as the new maintainer.
180
181
182\section{Installation}
183
184
185\subsection{Requirements}
186
187\begin{itemize}
188\item A compatible system. I have run mod\_log\_sql on Red Hat based systems
189(Red Hat, Mandrake). These instructions should easily adapt to any
190modern distro.
191\item Apache 1.2 or 1.3 installed. (I run 1.3.22 and it works fine). You
192should have already successfully compiled Apache and know what you're
193doing there.
194\item The MySQL development headers. This is called different things on
195different distros. For example, Red Hat 6.x called this RPM \char`\"{}MySQL-devel\char`\"{}
196whereas Mandrake calls it \char`\"{}libmysql10-devel\char`\"{}.
197\item MySQL >= 3.23.15 configured, installed and running on either localhost
198or an accessible networked machine. You should already have a basic
199understanding of MySQL and how it functions.
200\item Again, basic administrative skills with Apache and MySQL. I try to
201make things as easy as possible in this file, but its purpose is not
202to be an administrative tutorial.
203\item Additionally, if you want to be able to log SSL information such as
204keysize or cipher, you need OpenSSL and glibc-devel installed. Both
205are available as RPMs.
206\end{itemize}
207
208\subsection{Do I want a DSO?}
209
210You need to know the answer to this question before you proceed. The
211answer is pretty straightforward: what have you done in the past?
212If you like all your Apache modules to be dynamic, then you should
213keep doing that. If you're more of an old-school type and prefer to
214compile the modules right into apache, do that. Both methods work
215equally well.
216
217FWIW, the DSO method is more modern and increasing in popularity because
218apxs takes care of a lot of dirty little details for you. As you'll
219see below, the static-module method is a little more complex.
220
221
222\subsection{Installation as an Apache DSO (Preferred) }
223
224\begin{enumerate}
225\item Perform all the following steps as root so that you have install privs,
226etc. Unpack the archive into a working directory.
227
228\begin{lyxcode}
229\#~tar~zxf~mod\_log\_sql.tar.gz~-C~/usr/local/src~\#~cd~/usr/local/src/mod\_log\_sql
230\end{lyxcode}
231\item Edit Makefile for your system.\\
232
233
234
235NECESSARY:
236
237\begin{itemize}
238\item The location where you installed Apache -- usually /usr/local/apache,
239'locate apxs' can help you find it.
240\item The location of your MySQL libraries, find using 'locate libmysqlclient'
241\item The location of your MySQL header files, find using 'locate mysql.h'
242\end{itemize}
243OPTIONAL if you have included mod\_ssl in Apache and want to log SSL
244data such as keysize and cipher type:
245
246\begin{itemize}
247\item The location of your SSL header files, find using 'locate mod\_ssl.h'
248\end{itemize}
249Now that you know these things, edit Makefile and replace the stock
250values with your own.
251
252IMPORTANT: If you are not logging SSL info, comment out MODSSLHDRS
253by putting a \# character in front of it:
254
255\begin{lyxcode}
256\#MODSSLHDRS=/usr/include/...
257\end{lyxcode}
258\item Instruct apxs to compile the module as a DSO.
259
260\begin{lyxcode}
261\#~make~dso
262\end{lyxcode}
263\item You should see output similar to the following:
264
265\begin{lyxcode}
266/usr/local/Apache/bin/apxs~-Wc,-O2~-Wc,-Wall~-Wc,-DEAPI~-c~-I/usr/include/mysql~-I/usr/local/src/apache\_1.3.27-dso/src/modules/ssl~-L/usr/lib~-lmysqlclient~-lz~mod\_log\_sql.c~
267
268gcc~-DLINUX=22~-DNO\_DBM\_REWRITEMAP~-DMOD\_SSL=208111~-DUSE\_HSREGEX~-DEAPI~-DUSE\_EXPAT~-I../lib/expat-lite~-fpic~-DSHARED\_CORE~-DSHARED\_MODULE~-I/usr/local/Apache/include~-O2~-Wall~-DEAPI~-I/usr/include/mysql~-I/usr/local/src/apache\_1.3.27-dso/src/modules/ssl~-c~mod\_log\_sql.c~
269
270gcc~-shared~-o~mod\_log\_sql.so~mod\_log\_sql.o~-Wc,-O2~-Wc,-Wall~-Wc,-DEAPI~-L/usr/lib~-lmysqlclient~-lz~-lm~-lcrypt~-ldb
271\end{lyxcode}
272You should see no errors and have a file called \char`\"{}mod\_log\_sql.so\char`\"{}
273in your directory.
274
275\item Instruct apxs to install the DSO.
276
277\begin{lyxcode}
278\#~make~dsoinstall
279\end{lyxcode}
280You should see output similar to the following:
281
282\begin{lyxcode}
283/usr/local/Apache/bin/apxs~-i~mod\_log\_sql.so
284
285cp~mod\_log\_sql.so~/usr/local/Apache/libexec/mod\_log\_sql.so
286
287chmod~755~/usr/local/Apache/libexec/mod\_log\_sql.so
288\end{lyxcode}
289\item Module ordering within httpd.conf is important. If you are logging
290SSL, you must make sure that
291
292\begin{lyxcode}
293LoadModule~ssl\_module~libexec/libssl.so
294\end{lyxcode}
295comes before
296
297\begin{lyxcode}
298LoadModule~sql\_log\_module~libexec/mod\_log\_sql.so
299\end{lyxcode}
300If you don't, you will get this error when you start Apache:
301
302\begin{lyxcode}
303/usr/local/apache/libexec/mod\_log\_mysql.so:~undefined~symbol:~ssl\_var\_lookup
304
305/usr/local/apache/bin/apachectl~startssl:~httpd~could~not~be~started
306\end{lyxcode}
307(Because mod\_log\_sql doesn't yet have the required symbols that
308mod\_ssl provides.)
309
310Now skip below to the \char`\"{}Configuration\char`\"{} section.
311
312\end{enumerate}
313
314\subsection{Installation as a static module compiled into httpd}
315
316\begin{enumerate}
317\item Perform all the following steps as root so that you have install privs,
318etc.
319\item Unpack the archive into a working directory.
320
321\begin{lyxcode}
322\#~tar~zxf~mod\_log\_sql.tar.gz~-C~/usr/local/src~\#~cd~/usr/local/src/mod\_log\_sql
323\end{lyxcode}
324\item \label{step:editMF}Edit Makefile for your system.\\
325
326
327
328NECESSARY:
329
330\begin{itemize}
331\item The location where you installed Apache -- usually /usr/local/apache,
332'locate apxs' can help you find it.
333\item The location of your Apache {*}sources{*}, find using 'locate ABOUT\_APACHE'
334\item The location of your MySQL header files, find using 'locate mysql.h'
335\item The location of your MySQL libraries, find using 'locate libmysqlclient'
336\end{itemize}
337OPTIONAL if you have included mod\_ssl in Apache and want to log SSL
338data such as keysize and cipher type:
339
340\begin{itemize}
341\item The location of your mod\_ssl header files, find using 'locate mod\_ssl.h'
342\item The location of your OpenSSL header files, find using 'locate x509.h'
343\item The location of your db1 header files, find using 'locate mpool.h'
344\end{itemize}
345Now that you know these things, edit Makefile and replace the stock
346values with your own.
347
348IMPORTANT: If you are not logging SSL info, comment out MODSSLHDRS,
349OPNSSLHDRS and DB1HDRS by putting a \# character in front of each
350one, e.g. \#OPNSSLHDRS=/usr/include/...
351
352\item \# make static
353\item \# make statinstall
354\item Change to your Apache source dir.
355
356\begin{lyxcode}
357\#~cd~/usr/local/src/apache-1.3.22/src
358\end{lyxcode}
359\item Re-make your httpd binary as follows.
360
361\begin{enumerate}
362\item Edit Configuration.apaci as follows...
363
364\begin{itemize}
365\item Append the following string to the EXTRA\_LIBS= line. (\char`\"{}/usr/lib/mysql\char`\"{}
366is from step \ref{step:editMF}, where your MySQL libraries live):
367\end{itemize}
368\begin{lyxcode}
369-L/usr/lib/mysql~-lmysqlclient~-lm~-lz
370\end{lyxcode}
371\begin{itemize}
372\item Find the mod\_log\_config.o line, and add this line immediately after
373it:
374\end{itemize}
375\begin{lyxcode}
376AddModule~modules/sql/mod\_log\_sql.o
377\end{lyxcode}
378\item \# cp Configuration.apaci Configuration
379\item \# ./Configure
380\item \# make
381\item \# strip httpd
382\end{enumerate}
383\item Test your new apache binary:
384
385\begin{lyxcode}
386\#~./httpd~-l
387\end{lyxcode}
388\item You should see something like:
389
390\begin{lyxcode}
391Compiled-in~modules:~
392
393http\_core.c
394
395mod\_log\_sql.c~<-{}-~That's~the~line~you're~looking~for.
396
397mod\_env.c~
398
399mod\_log\_config.c~
400
401mod\_mime.c~
402
403mod\_negotiation.c~...
404
405etc...
406\end{lyxcode}
407\item Install your httpd binary. Copy it over your old httpd binary, wherever
408it lives. You can and should rename your old httpd first so that you
409can easily revert to that working version in case of bugs with the
410new version.
411
412\begin{lyxcode}
413\#~/etc/rc.d/init.d/httpd~stop~
414
415\#~mv~/usr/local/Apache/bin/httpd~\textasciitilde{}/httpd-save~
416
417\#~cp~-f~./httpd~/usr/local/Apache/bin/
418\end{lyxcode}
419\end{enumerate}
420
421\section{Configuration}
422
423
424\subsection{Preparing MySQL}
425
426You have to prepare the database to receive data from mod\_log\_sql,
427and set up run-time directives in httpd.conf to control how and what
428mod\_log\_sql logs.
429
430This section will discuss how to get started with a basic config.
431Full documentation of the run-time directives is available here: http://www.grubbybaby.com/mod\_log\_sql/directives.html
432
433\begin{enumerate}
434\item mod\_log\_sql can make its own tables on-the-fly, or you can pre-make
435the tables by hand. The advantage of letting the module make the tables
436is ease-of-use, but for raw performance you will want to pre-make
437the tables in order to save overhead. In this basic setup we'll let
438the module create tables for us.
439\item We still need to have a logging database created and ready, so run
440the MySQL command line client and create a database:
441
442\begin{lyxcode}
443\#~mysql~-uadmin~-pmypassword~mysql>~create~database~apachelogs;
444\end{lyxcode}
445\item If you want to hand-create the tables, run the enclosed 'create-tables'
446SQL script as follows:
447
448\begin{lyxcode}
449mysql>~source~create\_tables.sql
450\end{lyxcode}
451\item Create a specific MySQL userid that httpd will use to authenticate
452and enter data. This userid need not be an actual Unix user. It is
453a userid internal to MySQL with specific privileges. In the following
454example command, \char`\"{}apachelogs\char`\"{} is the database, \char`\"{}loguser\char`\"{}
455is the userid to create, \char`\"{}my.apachemachine.com\char`\"{}
456is the name of the Apache machine, and \char`\"{}l0gger\char`\"{}
457is the password to assign. Choose values that are different from these
458examples.
459
460\begin{lyxcode}
461mysql>~grant~insert,create~on~apachelogs.{*}~to~loguser@my.apachemachine.com~identified~by~'l0gger';
462\end{lyxcode}
463\item You may be especially security-paranoid and not want \char`\"{}loguser\char`\"{}
464to have \char`\"{}create\char`\"{} capability within the \char`\"{}apachelogs\char`\"{}
465databse. You can disable that but the cost is that you cannot use
466the module's automatic-table-creation feature. If that's an acceptable
467cost, hand-create the tables as described in step 1 and use the following
468GRANT statement instead of the one above:
469
470\begin{lyxcode}
471mysql>~grant~insert~on~apachelogs.{*}~to~loguser@my.apachemachine.com~identified~by~'l0gger';
472\end{lyxcode}
473\item Enable full logging of your MySQL daemon (at least temporarily for
474debugging purposes) if you don't do this already. Edit /etc/my.cnf
475and add the following line to your {[}mysqld{]} section:
476
477\begin{lyxcode}
478log=/var/log/mysql-messages
479\end{lyxcode}
480Then restart MySQL.
481
482\begin{lyxcode}
483\#~/etc/rc.d/init.d/mysql~restart
484\end{lyxcode}
485\end{enumerate}
486
487\subsection{Preparing Apache}
488
489\begin{enumerate}
490\item Tell the module what database to use and the appropriate authentication
491information.
492
493\begin{description}
494\item [EXAMPLE:]Use the MySQL database called \char`\"{}apachelogs\char`\"{}
495running on \char`\"{}dbmachine.foo.com\char`\"{}. The module uses
496username \char`\"{}loguser\char`\"{} and password \char`\"{}l0gger\char`\"{}
497to authenticate to the database. The log entries will be INSERTed
498into the table called \char`\"{}access\_log\char`\"{}.
499\end{description}
500So, edit httpd.conf and insert the following lines somewhere AFTER
501any LoadModule / AddModule statements. Make sure these statements
502are \char`\"{}global,\char`\"{} i.e. not inside any VirtualHost stanza.
503
504\begin{lyxcode}
505LogSQLDatabase~apachelogs
506
507LogSQLLoginInfo~dbmachine.foo.com~loguser~l0gger~
508
509LogSQLCreateTables~on
510\end{lyxcode}
511\item If your database resides on localhost instead of another host, specify
512the MySQL server's socket file as follows:
513
514\begin{lyxcode}
515LogSQLSocketFile~/your/path/to/mysql.sock
516\end{lyxcode}
517\item The actual logging is set up on a virtual-host-by-host basis. So,
518skip down to the virtual host you want to set up. Instruct this virtual
519host to log entries to the table ''access\_log'' by inserting a
520LogSQLTransferLogTable directive. (The LogSQLTransferLogTable directive
521is the minimum required to log -- other directives simply tune the
522module's behavior.)
523
524\begin{lyxcode}
525<VirtualHost~1.2.3.4>
526
527{[}snip{]}
528
529LogSQLTransferLogTable~access\_log
530
531{[}snip{]}
532
533</VirtualHost>
534\end{lyxcode}
535\item Restart apache.
536
537\begin{lyxcode}
538\#~/etc/rc.d/init.d/httpd~start
539\end{lyxcode}
540\end{enumerate}
541
542\subsection{Testing the module}
543
544\begin{enumerate}
545\item Load your web site in a browser to trigger some hits, then confirm
546that the entries are being successfully logged:
547
548\begin{lyxcode}
549\#~mysql~-hmysql.host.com~-umysqladmin~-p~-e~\char`\"{}select~{*}~from~access\_log\char`\"{}~apachelogs~
550
551Enter~password:
552
553(Several~lines~of~output~should~follow,~corresponding~to~your~hits~on~the~site.)
554\end{lyxcode}
555You now have basic functionality. Don't disable your regular Apache
556logs until you feel comfortable that the database is behaving as you'd
557like and that things are going well.
558
559\item If you do not see any entries in the access\_log, then something is
560preventing the inserts from happening. This problem could be caused
561by several things:
562
563\begin{itemize}
564\item Improper privileges set up in the MySQL database
565\item You aren't hitting a VirtualHost that has a LogSQLTransferLogTable
566entry
567\item You didn't specify the right host
568\end{itemize}
569If you have confirmed your LogSQL{*} directives and know them to be
570correct, you should examine the httpd server logs for mod\_log\_sql
571messages; the module will offer hints as to why it cannot connect,
572etc. Also examine the MySQL log that you established in step 3. Ensure
573that the INSERTs are not being rejected because of a malformed table
574entry or other clerical error. If you see no INSERT attempts in the
575log, the module isn't successfully connecting to the database.
576
577The next thing to do is recompile the module with debugging output
578activated. change the \char`\"{}\#undef DEBUG\char`\"{} on line 8
579of mod\_log\_sql.c to \char`\"{}\#define DEBUG\char`\"{} and recompile/reinstall.
580The module will now output copious notes about what it is doing, and
581this will help you (and the maintainer) solve the problem.
582
583\end{enumerate}
584You can now activate the advanced features of mod\_log\_sql. These
585are all described in the next section.
586
587
588\subsection{Configuration directive reference}
589
590
591\subsubsection{LogSQLLoginInfo }
592
593\begin{lyxcode}
594\textbf{MANDATORY}~
595
596Syntax:~LogSQLLoginInfo~host~user~password
597
598Example:~LogSQLLoginInfo~foobar.baz.com~logwriter~passw0rd~
599
600Context:~server~config
601\end{lyxcode}
602\begin{quote}
603Defines the general parameters of the MySQL host to which you will
604be logging. host is the hostname or IP address of the MySQL machine.
605user is the MySQL userid (not a Unix userid!) with INSERT privileges
606on the table defined in LogSQLTransferLogTable. password is that user's
607password. This is defined only once in the httpd.conf file.
608\end{quote}
609
610\subsubsection{LogSQLDatabase }
611
612\begin{lyxcode}
613\textbf{MANDATORY}
614
615Syntax:~LogSQLDatabase~database~
616
617Example:~LogSQLDatabase~loggingdb~
618
619Context:~server~config
620\end{lyxcode}
621\begin{quote}
622Defines the database that is used for logging. database must be operating
623on the MySQL host defined in LogSQLLoginInfo. This is defined only
624once in the httpd.conf file.
625\end{quote}
626
627\subsubsection{LogSQLTransferLogTable}
628
629\begin{lyxcode}
630\textbf{MANDATORY~}
631
632Syntax:~LogSQLTransferLogTable~table-name~
633
634Example:~LogSQLTransferLogTable~access\_log\_table~
635
636Context:~virtual~host
637\end{lyxcode}
638\begin{quote}
639Defines which table is used for logging of Apache's transfers; this
640is analogous to Apache's TransferLog directive. table-name must be
641a valid table within the database defined in LogSQLDatabase.
642
643This directive is not necessary if you declare LogSQLMassVirtualHosting
644On, since that directive activates dynamically-named tables. If you
645attempt to use LogSQLTransferLogTable at the same time a warning will
646be logged and it will be ignored, since LogSQLMassVirtualHosting takes
647priority.
648\end{quote}
649
650\subsubsection{LogSQLRequestIgnore}
651
652\begin{lyxcode}
653Syntax:~LogSQLRequestIgnore~req1~req2~req3~...~reqN~
654
655Example:~LogSQLRequestIgnore~root.exe~cmd.exe~default.ida~favicon.ico~
656
657Context:~virtual~host
658\end{lyxcode}
659\begin{quote}
660Lists a series of strings that, if present in the URI, will cause
661that request NOT to be logged. This directive is useful for cutting
662down on log clutter when you KNOW that you do not want to log requests
663for certain objects. (The example above is a genuinely useful one;
664it will prevent logging of many common Microsoft-based worm intrusion
665attempts, as well as those ridiculous requests for the favicon.)
666
667Each string is separated by a space, and NO regular expressions or
668globbing are allowed. Each string is evaluated as a substring of the
669URI using strstr().
670\end{quote}
671
672\subsubsection{LogSQLRemhostIgnore}
673
674\begin{lyxcode}
675Syntax:~LogSQLRemhostIgnore~host1~host2~host3~...~hostN~
676
677Example:~LogSQLRemhostIgnore~localnet.com~
678
679Context:~virtual~host
680\end{lyxcode}
681\begin{quote}
682Lists a series of strings that, if present in the REMOTE\_HOST, will
683cause that request NOT to be logged. This directive is useful for
684cutting down on log clutter when you KNOW that you do not want to
685log requests from certain hosts, such as your own internal network
686machines.
687
688Each string is separated by a space, and NO regular expressions or
689globbing are allowed. Each string is evaluated as a substring of the
690REMOTE\_HOST using strstr().
691\end{quote}
692
693\subsubsection{LogSQLRefererIgnore}
694
695\begin{lyxcode}
696Syntax:~LogSQLRefererIgnore~ref1~ref2~ref3~...~refN~
697
698Example:~LogSQLRefererIgnore~google.com~
699
700Context:~virtual~host
701\end{lyxcode}
702\begin{quote}
703Lists a series of strings that, if present in the HTTP\_REFERER, will
704cause that request NOT to be logged. This directive is useful for
705cutting down on log clutter when you know that you do not want to
706log requests from certain referers.
707
708Each string is separated by a space, and NO regular expressions or
709globbing are allowed. Each string is evaluated as a substring of the
710HTTP\_REFERER using strstr().
711\end{quote}
712
713\subsubsection{LogSQLWhichCookie}
714
715\begin{lyxcode}
716Syntax:~LogSQLWhichCookie~cookiename~
717
718Example:~LogSQLWhichCookie~Clicks
719
720Default:~None.~You~must~set~this~if~you~wish~to~capture~cookies.
721
722Context:~virtual~host
723\end{lyxcode}
724\begin{quote}
725In HTTP, cookies have names to distinguish them from each other. Using
726mod\_usertrack, for example, you can give your user-tracking cookies
727a name with the CookieName directive.
728
729If you have activated cookie logging in LogSQLTransferLogFormat, then
730LogSQLWhichCookie tells mod\_log\_sql which cookie to log. This is
731useful because many times you will be setting and receiving more than
732one cookie from a client; without this directive you'd be unable to
733choose which cookie is your mod\_usertrack cookie.
734
735Note: although this was intended for people who are using mod\_usertrack
736to set user-tracking cookies, you aren't restricted in any way. You
737can choose which cookie you wish to log to the database, and it doesn't
738necessarily have to have anything to do with mod\_usertrack.
739\end{quote}
740
741\subsubsection{LogSQLCreateTables}
742
743\begin{lyxcode}
744Syntax:~LogSQLCreateTables~flag
745
746Example:~LogSQLCreateTables~On~
747
748Default:~Off~
749
750Context:~server~config
751\end{lyxcode}
752\begin{quote}
753mod\_log\_sql now has the ability to create its tables on-the-fly.
754The advantage to this is convenience: you don't have to execute any
755SQL by hand to prepare the table. This is especially helpful for people
756with lots of virtual hosts (who should also see the LogSQLMassVirtualHosting
757directive).
758
759There is a slight disadvantage: if you wish to activate this feature,
760then the user specified by LogSQLLoginInfo must have CREATE privileges
761on the database. In an absolutely paranoid, locked-down situation
762you may only want to grant your mod\_log\_sql user INSERT privileges
763on the database; in that situation you are unable to take advantage
764of LogSQLCreateTables. But most people -- even the very security-conscious
765-- will find that granting CREATE on the logging database is reasonable.
766
767This is defined only once in the httpd.conf file.
768\end{quote}
769
770\subsubsection{LogSQLMassVirtualHosting}
771
772\begin{lyxcode}
773Syntax:~LogSQLMassVirtualHosting~flag~
774
775Example:~LogSQLMassVirtualHosting~On~
776
777Default:~Off~
778
779Context:~server~config
780\end{lyxcode}
781\begin{quote}
782If you administer a site hosting many, many virtual hosts then this
783option will appeal to you. If you activate LogSQLMassVirtualHosting
784then several things happen:
785\begin{itemize}
786\item the on-the-fly table creation feature is activated automatically
787\item the transfer log table name is dynamically set from the virtual host's
788name (example: a virtual host www.grubbybaby.com gets logged to table
789access\_www\_grubbybaby\_com)
790\item which, in turn, means that each virtual host logs to its own segregated
791table. Because there is no data shared between virtual servers you
792can grant your users access to the tables they need; they will be
793unable to view others' data.
794\end{itemize}
795This is a huge boost in convenience for sites with many virtual servers.
796Activating LogSQLMassVirtualHosting obviates the need to create every
797virtual server's table and provides more granular security possibilities.
798
799This is defined only once in the httpd.conf file.
800\end{quote}
801
802\subsubsection{LogSQLPreserveFile}
803
804\begin{lyxcode}
805Syntax:~LogSQLPreserveFile~filename~
806
807Example:~LogSQLPreserveFile~offline-preserve~
808
809Default:~mysql-preserve~(in~/tmp)~
810
811Context:~virtual~host
812\end{lyxcode}
813\begin{quote}
814mod\_log\_sql writes queries to this local preserve file in the event
815that it cannot reach the database, and thus ensures that your high-availability
816web frontend does not lose logs during a temporary database outage.
817This could happen for a number of reasons: the database goes offline,
818the network breaks, etc. You will not lose entries since the module
819has this backup. The file consists of a series of SQL statements that
820can be imported into your database at your convenience; furthermore,
821because the SQL queries contain the access timestamps you do not need
822to worry about out-of-order data after the import.
823
824For security purposes the name you supply will be prepended with \char`\"{}/tmp/\char`\"{}
825to force creation of the file in /tmp.
826
827If you do not define LogSQLPreserveFile then all virtual servers will
828log to the same default preserve file (/tmp/mysql-preserve). You can
829redefine this on a virtual-host basis in order to segregate your preserve
830files if you desire. Note that segregation is not really necessary,
831as the SQL statements that are written to the preserve file already
832distinguish between different virtual hosts.
833
834The module will log to error-log if/when it notices a database outage,
835and upon database return. You will therefore know when the preserve
836file is being used, although it is your responsibility to import the
837file.
838
839The file does not need to be created in advance. It is safe to remove
840or rename the file without interrupting Apache, as the module closes
841the filehandle immediately after completing the write. The file is
842created with the user \& group ID of the running Apache process (e.g.
843'nobody' on many Linux distributions).
844\end{quote}
845
846\subsubsection{LogSQLSocketFile }
847
848\begin{lyxcode}
849Syntax:~LogSQLSocketFile~filename~
850
851Example:~LogSQLSocketFile~/tmp/mysql.sock~
852
853Default:~/var/lib/mysql/mysql.sock~
854
855Context:~server~config
856\end{lyxcode}
857\begin{quote}
858At Apache runtime you can specify the MySQL socket file to use. Set
859this once in your main server config to override the default value.
860This value is irrelevant if your database resides on a separate machine.
861
862mod\_log\_sql will automatically employ the socket for db communications
863if the database resides on the local host. If the db resides on a
864separate host the module will automatically use TCP/IP. This is a
865function of the MySQL API and is not user-configurable.
866\end{quote}
867
868\subsubsection{LogSQLTransferLogFormat }
869
870\begin{lyxcode}
871Syntax:~LogSQLTransferLogFormat~format-string~
872
873Example:~LogSQLTransferLogFormat~huSUTv~
874
875Default:~AbHhmRSsTUuv~
876
877Context:~virtual~host
878\end{lyxcode}
879\begin{quote}
880Each character in the format-string defines an attribute of the request
881that you wish to log. The default logs the information required to
882create Combined Log Format logs, plus several extras. Here is the
883full list of allowable keys, which sometimes resemble their Apache
884counterparts, but do not always:
885
886\begin{tabular}{|c|l|l|l|l|}
887\hline
888\textbf{Character}&
889\textbf{What is this?}&
890\textbf{MySQL DB field}&
891\textbf{Recommended column type}&
892\textbf{Example}\\
893\hline
894\hline
895A&
896User agent&
897agent&
898varchar(255)&
899Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0)\\
900\hline
901b&
902Bytes transfered&
903bytes\_sent&
904int unsigned&
90532561\\
906\hline
907c&
908Text of cookie&
909cookie&
910varchar(255)&
911Apache=sdyn.fooonline.net.130051007102700823\\
912\hline
913f&
914&
915request\_file&
916varchar(255)&
917\\
918\hline
919H&
920HTTP request protocol&
921request\_protocol&
922varchar(10)&
923HTTP/1.1\\
924\hline
925h&
926Name of remote host&
927remote\_host&
928varchar(50)&
929blah.foobar.com\\
930\hline
931I&
932Ident user info&
933remote\_logname&
934varchar(50)&
935bobby\\
936\hline
937m&
938HTTP request method&
939request\_method&
940varchar(6)&
941GET\\
942\hline
943P&
944httpd child PID&
945child\_pid&
946smallint unsigned&
9473215\\
948\hline
949p&
950httpd port&
951server\_port&
952smallint unsigned&
95380\\
954\hline
955R&
956Referer&
957referer&
958varchar(255)&
959http://www.biglinkstoyou.com/linkpage.html\\
960\hline
961r&
962Request in full form&
963request\_line&
964varchar(255)&
965GET /books-cycroad.html HTTP/1.1\\
966\hline
967S&
968Time of request in UNIX format&
969time\_stamp&
970int unsigned&
9711005598029\\
972\hline
973s&
974HTTP status of request&
975status&
976smallint unsigned&
977404\\
978\hline
979T&
980Seconds to service request&
981request\_duration&
982smallint unsigned&
9832\\
984\hline
985t&
986Time of request in human format&
987request\_time&
988char(28)&
989{[}02/Dec/2001:15:01:26 -0800{]}\\
990\hline
991U&
992Request in simple form&
993request\_uri&
994varchar(255)&
995/books-cycroad.html\\
996\hline
997u&
998User info from HTTP authentication&
999remote\_user&
1000varchar(50)&
1001bobby\\
1002\hline
1003v&
1004Virtual host servicing the request&
1005virtual\_host&
1006varchar(50)&
1007www.foobar.com\\
1008\hline
1009\end{tabular}
1010
1011If you have compiled mod\_log\_sql with WANT\_SSL\_LOGGING, you also
1012get these:
1013
1014\begin{tabular}{|c|l|l|l|}
1015\hline
1016\textbf{Character}&
1017\textbf{MySQL DB field it activates}&
1018\textbf{MySQL DB field it activatesRecommended column type}&
1019\textbf{Example}\\
1020\hline
1021\hline
1022z&
1023ssl\_cipher&
1024varchar(25)&
1025RC4-MD5\\
1026\hline
1027q&
1028ssl\_keysize&
1029smallint unsigned&
103056\\
1031\hline
1032Q&
1033ssl\_maxkeysize&
1034smallint unsigned&
1035128\\
1036\hline
1037\end{tabular}
1038\end{quote}
1039
1040\section{FAQ}
1041
1042
1043\subsection{Why log to an SQL database?}
1044
1045To begin with, let's get it out of the way: logging to a database
1046is not a panacea. But while there are complexities with this solution,
1047the benefit can be substantial for certain classes of administrator
1048or people with advanced requirements:
1049
1050\begin{itemize}
1051\item Chores like log rotation go away, as you can DELETE records from the
1052SQL database once they are no longer useful. For example, the excellent
1053and popular log-analysis tool Webalizer (http://www.webalizer.com/)
1054does not need historic logs after it has processed them, enabling
1055you to delete older logs.
1056\item People with clusters of web servers (for high availability) will benefit
1057the most -- all their webservers can log to a single SQL database.
1058This obviates the need to collate/interleave the many separate logfiles,
1059which can be / highly/ problematic.
1060\item People acquainted with the power of SQL SELECT statements will know
1061the flexibility of the extraction possibilities at their fingertips.
1062\end{itemize}
1063For example, do you want to see all your 404's? Do this:
1064
1065\begin{lyxcode}
1066select~remote\_host,status,request\_uri,bytes\_sent,from\_unixtime(time\_stamp)~from~acc\_log\_tbl~where~status=404~order~by~time\_stamp;
1067
1068+-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-+-{}-{}-{}-{}-{}-{}-{}-+-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-+-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-+-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-
1069
1070+~~~~~~~~~~~~~~~~~~~~~~~remote\_host~|~status~|~request\_uri~~~~~~~~~~~~~~|~bytes\_sent~|~from\_unixtime(time\_stamp)|
1071
1072+-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-+-{}-{}-{}-{}-{}-{}-{}-+-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-+-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-+-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-
1073
1074|~marge.mmm.co.uk~~~~~~~~~~~~~~~~~~~|~404~~~~|~/favicon.ico~~~~~~~~~~~~~|~321~~~~~~~~|~2001-11-20~02:30:56~~~~~~|
1075
1076|~62.180.239.251~~~~~~~~~~~~~~~~~~~~|~404~~~~|~/favicon.ico~~~~~~~~~~~~~|~333~~~~~~~~|~2001-11-20~02:45:25~~~~~~|
1077
1078|~212.234.12.66~~~~~~~~~~~~~~~~~~~~~|~404~~~~|~/favicon.ico~~~~~~~~~~~~~|~321~~~~~~~~|~2001-11-20~03:01:00~~~~~~|~
1079
1080|~212.210.78.254~~~~~~~~~~~~~~~~~~~~|~404~~~~|~/favicon.ico~~~~~~~~~~~~~|~333~~~~~~~~|~2001-11-20~03:26:05~~~~~~|~
1081
1082+-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-+-{}-{}-{}-{}-{}-{}-{}-+-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-+-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-+-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-+
1083\end{lyxcode}
1084Or do you want to see how many bytes you've sent within a certain
1085directory or site? Do this:
1086
1087\begin{lyxcode}
1088select~request\_uri,sum(bytes\_sent)~as~bytes,count(request\_uri)~as~howmany~from~acc\_log\_tbl~where~request\_uri~like~'\%mod\_log\_sql\%'~group~by~request\_uri~order~by~howmany~desc;~
1089
1090+-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-+-{}-{}-{}-{}-{}-{}-{}-{}-+-{}-{}-{}-{}-{}-{}-{}-{}-+~
1091
1092|~request\_uri~~~~~~~~~~~~~~~~~~~~~~~|~bytes~~~|~howmany~|~
1093
1094+-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-+-{}-{}-{}-{}-{}-{}-{}-{}-+-{}-{}-{}-{}-{}-{}-{}-{}-+~
1095
1096|~/mod\_log\_sql/style\_1.css~~~~~~~~~~|~157396~~|~~~~1288~|~
1097
1098|~/mod\_log\_sql/~~~~~~~~~~~~~~~~~~~~~|~2514337~|~~~~~801~|~
1099
1100|~/mod\_log\_sql/mod\_log\_sql.tar.gz~~~|~9769312~|~~~~~456~|~
1101
1102|~/mod\_log\_sql/faq.html~~~~~~~~~~~~~|~5038728~|~~~~~436~|~
1103
1104|~/mod\_log\_sql/INSTALL~~~~~~~~~~~~~~|~1196161~|~~~~~202~|~
1105
1106|~/mod\_log\_sql/directives.html~~~~~~|~1096821~|~~~~~171~|~
1107
1108|~/mod\_log\_sql/CHANGELOG~~~~~~~~~~~~|~424481~~|~~~~~107~|~
1109
1110|~/mod\_log\_sql/README~~~~~~~~~~~~~~~|~796072~~|~~~~~~97~|~
1111
1112|~/mod\_log\_sql/directives-old.html~~|~42480~~~|~~~~~~~6~|
1113
1114|~/mod\_log\_sql/index.html~~~~~~~~~~~|~9531~~~~|~~~~~~~3~|~
1115
1116+-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-+-{}-{}-{}-{}-{}-{}-{}-{}-+-{}-{}-{}-{}-{}-{}-{}-{}-+
1117\end{lyxcode}
1118Or maybe you want to see who's linking to you? Do this:
1119
1120\begin{lyxcode}
1121select~count(referer)~as~num,referer~from~acc\_log\_tbl~where~request\_uri='/mod\_log\_sql/'~group~by~referer~order~by~num~desc;
1122
1123+-{}-{}-{}-{}-+-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-+
1124
1125|~num~|~referer~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|~
1126
1127+-{}-{}-{}-{}-+-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-+
1128
1129|~271~|~http://freshmeat.net/projects/mod\_log\_sql/~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|~
1130
1131|~96~~|~http://modules.apache.org/search?id=339~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|~
1132
1133|~48~~|~http://freshmeat.net/~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|~
1134
1135|~8~~~|~http://freshmeat.net~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|
1136
1137|~7~~~|~http://freshmeat.net/daily/2001/11/30/~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|~
1138
1139|~6~~~|~http://freshmeat.net/daily/2001/11/20/~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|
1140
1141+-{}-{}-{}-{}-+-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-+
1142\end{lyxcode}
1143As you can see, there are myriad possibilities that can be constructed
1144with the wonderful SQL SELECT statement. Logging to an SQL database
1145can be really quite useful!
1146
1147
1148\subsection{Why use MySQL? Are there alternatives?}
1149
1150MySQL is a robust, free, and very powerful production-quality database
1151engine. It is well supported and comes with detailed documentation.
1152Many 3rd-party software pacakges (e.g. Slashcode, the engine that
1153powers Slashdot) run exclusively with MySQL. In other words, you will
1154belong to a very robust and well-supported community by choosing MySQL.
1155
1156That being said, there are alternatives. PostgreSQL is probably MySQL's
1157leading \char`\"{}competitor\char`\"{} in the free database world.
1158There is also an excellent module available for Apache to permit logging
1159to a PostgreSQL database, called pgLOGd \url{(http://www.digitalstratum.com/pglogd/)}.
1160
1161
1162\subsection{Is this code production-ready?}
1163
1164By all accounts it is. It is known to work without a problem on many-thousands-of-hits-per-day
1165webservers. Does that mean it is 100\% bug free? Well, no software
1166is. But it is well-tested and /believed/ to be fully compatible with
1167production environments. (The usual disclaimers apply. This software
1168is provided without warranty of any kind.)
1169
1170
1171\subsection{How well does it perform?}
1172
1173mod\_log\_sql scales to very high loads. Apache 1.3.22 + mod\_log\_sql
1174was benchmarked using the \char`\"{}ab\char`\"{} (Apache Bench) program
1175that comes with the Apache distribution; here are the results.
1176
1177Overall configuration:
1178
1179\begin{itemize}
1180\item Machine A: Apache webserver
1181\item Machine B: MySQL server
1182\item Machines A and B connected with 100Mbps Ethernet
1183\end{itemize}
1184Webserver configuration:
1185
1186\begin{itemize}
1187\item Celeron 400 128 MB RAM IDE storage
1188\end{itemize}
1189Apache configuration:
1190
1191\begin{lyxcode}
1192Timeout~300~
1193
1194KeepAlive~On~
1195
1196MaxKeepAliveRequests~100~
1197
1198KeepAliveTimeout~15~
1199
1200MinSpareServers~5~
1201
1202StartServers~10~
1203
1204MaxSpareServers~15~
1205
1206MaxClients~256~
1207
1208MaxRequestsPerChild~5000~
1209
1210LogSQLTransferLogFormat~AbHhmRSsTUuvc~
1211
1212LogSQLWhichCookie~Clicks~
1213
1214CookieTracking~on~
1215
1216CookieName~Clicks
1217\end{lyxcode}
1218\char`\"{}ab\char`\"{} commandline:
1219
1220\begin{lyxcode}
1221./ab~-c~10~-t~20~-v~2~-C~Clicks=ab\_run~http://www.hostname.com/target~
1222\end{lyxcode}
1223( 10 concurrent requests; 20 second test; setting a cookie \char`\"{}Clicks=ab\_run\char`\"{};
1224target = the mod\_log\_sql homepage. )
1225
1226Ten total ab runs were conducted: five with MySQL logging enabled,
1227and five with all MySQL directives commented out of httpd.conf. Then
1228each five were averaged. The results:
1229
1230\begin{itemize}
1231\item Average of five runs employing MySQL \emph{and} standard text logging:
1232139.01 requests per second, zero errors.
1233\item Average of five runs employing \emph{only} standard text logging:
1234139.96 requests per second, zero errors.
1235\end{itemize}
1236In other words, any rate-limiting effects on this particular hardware
1237setup are not caused by MySQL. Note that although this very simple
1238webserver setup is hardly cutting-edge -- it is, after all, a fairly
1239small machine -- 139 requests per second equal over twelve million
1240hits per day\emph{.}
1241
1242If you run this benchmark yourself, take note of three things:
1243
1244\begin{enumerate}
1245\item Use a target URL that is on your own webserver :-).
1246\item Wait until all your connections are closed out between runs; after
1247several thousand requests your TCP/IP stack will be filled with hundreds
1248of connections in TIME\_WAIT that need to close. Do a \char`\"{}netstat
1249-t|wc -l\char`\"{} on the webserver to see. If you don't wait, you
1250can expect to see a lot of messages like \char`\"{}ip\_conntrack:
1251table full, dropping packet\char`\"{} in your logs. (This has nothing
1252to do with mod\_log\_sql, this is simply the nature of the TCP/IP
1253stack in the Linux kernel.)
1254\item When done with your runs, clean these many thousands of requests out
1255of your database:
1256\end{enumerate}
1257\begin{lyxcode}
1258mysql>~delete~from~access\_log~where~agent~like~'ApacheBench\%';~mysql>~optimize~table~access\_log;~
1259\end{lyxcode}
1260
1261\subsection{Who's using mod\_log\_sql?}
1262
1263Good question! It would be great to find out! If you are a production-level
1264mod\_log\_sql user, please contact the maintainer, Chris Powell \url{chris@grubbybaby.com}so
1265that you can be mentioned here.
1266
1267
1268\subsection{How do I extract the data in a format that my analysis tool can understand?}
1269
1270mod\_log\_sql would be virtually useless if there weren't a way for
1271you to extract the data from your database in a somewhat meaningful
1272fashion. To that end there's a Perl script enclosed with the distribution.
1273That script (make\_combined\_log.pl) is designed to extract N-many
1274days worth of access logs and provide them in a Combined Log Format
1275output. You can use this very tool right in /etc/crontab to extract
1276logs on a regular basis so that your favorite web analysis tool can
1277read them. Or you can examine the Perl code to construct your own
1278custom tool.
1279
1280For example, let's say that you want your web statistics updated once
1281per day in the wee hours of the morning. A good way to accomplish
1282that would be the following entries in /etc/crontab:
1283
1284\begin{lyxcode}
1285\#~Generate~the~temporary~apache~logs~from~the~MySQL~database~(for~webalizer)~
1286
128705~04~{*}~{*}~{*}~root~/usr/local/sbin/make\_combined\_log.pl~1~www.grubbybaby.com~>~/var/log/httpd/mysql-grubbybaby
1288
1289\#~Run~webalizer~on~httpd~log~
1290
129130~04~{*}~{*}~{*}~root~/usr/local/bin/webalizer~-c~/etc/webalizer.conf;~rm~-f~/var/log/httpd/mysql-grubbybaby
1292\end{lyxcode}
1293Or if you have a newer system that puts files in /etc/cron.daily etc.,
1294create a file called ''webalizer'' in the cron.\_\_\_\_ subdir of
1295your choice. Use the following as the contents of your file, and make
1296sure to chmod 755 it when done.
1297
1298\begin{lyxcode}
1299\#!/bin/sh
1300
1301/usr/local/sbin/make\_combined\_log.pl~1~www.yourdomain.com~>~/var/log/httpd/templog
1302
1303/usr/local/bin/webalizer~-q~-c~/etc/webalizer.conf~
1304
1305rm~-f~/var/log/httpd/templog
1306\end{lyxcode}
1307See? Easy.
1308
1309
1310\subsection{Why doesn't the module also replace the Apache ErrorLog?}
1311
1312There are circumstances when that would be quite unwise -- for example,
1313if Apache could not reach the MySQL server for some reason and needed
1314to log that fact. Without a text-based error log you'd never know
1315anything was wrong, because Apache would be trying to log a database
1316connection error to the database... you get the point.
1317
1318Error logs are usually not very high-traffic and are really best left
1319as text files on a web server machine.
1320
1321
1322\subsection{\label{sec:cookie}How can I log mod\_usertrack cookies?}
1323
1324A number of people like to log mod\_usertrack cookies in their Apache
1325TransferLog to aid in understanding their visitors' clickstreams.
1326This is accomplished, for example, with a statement as follows:
1327
1328\begin{lyxcode}
1329LogFormat~\char`\"{}\%h~\%l~\%u~\%t~\textbackslash{}\char`\"{}\%r\textbackslash{}\char`\"{}~\%s~\%b~\textbackslash{}\char`\"{}\%\{Referer\}i\textbackslash{}\char`\"{}~\textbackslash{}\char`\"{}\%\{User-Agent\}i\textbackslash{}\char`\"{}\char`\"{}~\textbackslash{}\char`\"{}\%\{cookie\}n\textbackslash{}\char`\"{}\char`\"{}
1330\end{lyxcode}
1331Naturally it would be nice for mod\_log\_sql to permit the admin to
1332log the cookie data as well, so as of version 1.10 you can do this.
1333You need to have already compiled mod\_usertrack into httpd -- it's
1334one of the standard Apache modules.
1335
1336First make sure you have a column called \char`\"{}cookie\char`\"{}
1337in the MySQL database to hold the cookies, which can be done as follows
1338if you already have a working database:
1339
1340\begin{lyxcode}
1341alter~table~acc\_log\_tbl~add~column~cookie~varchar(255);
1342\end{lyxcode}
1343Next configure your server to set usertracking cookies as follows,
1344and make sure you include the new 'c' directive in your LogSQLTransferLogFormat,
1345which activates cookie logging. Here's an example:
1346
1347\begin{lyxcode}
1348<VirtualHost~1.2.3.4>~
1349
1350~CookieTracking~on~
1351
1352~CookieStyle~Cookie~
1353
1354~CookieName~Foobar~
1355
1356~LogSQLTransferLogFormat~huSUsbTvRAc~
1357
1358~LogSQLWhichCookie~Foobar~
1359
1360</VirtualHost>
1361\end{lyxcode}
1362The first three lines configure mod\_usertrack to create a COOKIE
1363(RFC 2109) format cookie called Foobar. The last two lines tell mod\_log\_sql
1364to log cookies named Foobar. You have to choose which cookie to log
1365because more than one cookie can/will be sent to the server by the
1366client.
1367
1368FYI, you are advised NOT to use CookieStyle Cookie2 -- it seems that
1369even newer browsers (IE 5.5, etc.) have trouble with the new COOKIE2
1370(RFC 2965) format. Just stick with the standard COOKIE format and
1371you'll be fine.
1372
1373Perform some hits on your server and run a select:
1374
1375\begin{lyxcode}
1376mysql>~select~request\_uri,cookie~from~access\_log~where~cookie~is~not~null;
1377
1378+-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-+-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-+
1379
1380|~request\_uri~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~cookie~|~
1381
1382+-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-+-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-+~
1383
1384|~/mod\_log\_sql/~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|~ool-18e4.dyn.optonline.net.130051007102700823~~~~~~|~
1385
1386|~/mod\_log\_sql/usa.gif~~~~~~~~~~~~~~~~~~~~~~~|~ool-18e4.dyn.optonline.net.130051007102700823~~~~~~|~
1387
1388|~/mod\_log\_sql/style\_1.css~~~~~~~~~~~~~~~~~~~|~ool-18e4.dyn.optonline.net.130051007102700823~~~~~~|~
1389
1390...etc...
1391\end{lyxcode}
1392
1393\subsection{What if I want to log more than one cookie?}
1394
1395No problem. As of version 1.17, you have a choice. If you are just
1396interested in a single cookie, follow the instructions in section
1397\ref{sec:cookie} above. That cookie will be logged to a column in
1398the regular access\_log table.
1399
1400However, if you need to log multiple cookies, you'll employ the LogSQLWhichCookies
1401(note the plural) directive. The cookies you specify will be logged
1402to a separate table, and entries in that table will be linked to the
1403regular access\_log entries via the unique ID that is supplied by
1404mod\_unique\_id. Without mod\_unique\_id the information will still
1405be logged but you will be unable to correlate which cookies go with
1406which access-requests.
1407
1408LogSQLWhichCookie and LogSQLWhichCookies can coexist without conflict,
1409but you're better off choosing the one you need.
1410
1411
1412\subsection{What are the SSL logging features, and how do I activate them?}
1413
1414If you run an SSL-enabled server you may benefit from logging some
1415SSL details. mod\_log\_sql now supports this ability. By adding certain
1416characters to your LogSQLTransferLogFormat string you can tell mod\_log\_sql
1417to log the SSL cipher, the SSL keysize of the connection, and the
1418Max-keysize that was available. This would let you tell, for example,
1419which clients were using only export-grade security to access your
1420secure software area.
1421
1422You can compile mod\_log\_sql with SSL logging support if you have
1423the right packages installed. If you already have an SSL-enabled Apache
1424then you by definition have the correct packages already installed:
1425OpenSSL and mod\_ssl.
1426
1427You need to ensure that your database is set up to log the SSL data.
1428Issue the following commands to MySQL once you have your basic access\_log
1429table built:
1430
1431\begin{lyxcode}
1432alter~table~access\_log~add~column~ssl\_cipher~varchar(25);
1433
1434alter~table~access\_log~add~column~ssl\_keysize~smallint~unsigned;
1435
1436alter~table~access\_log~add~column~ssl\_maxkeysize~smallint~unsigned;
1437\end{lyxcode}
1438Finally configure httpd.conf to activate the SSL fields. Note that
1439this is only meaningful in a VirtualHost that is set up for SSL.
1440
1441\begin{lyxcode}
1442<VirtualHost~1.2.3.4:443>~
1443
1444~LogSQLTransferLogFormat~AbHhmRSsTUuvcQqz~
1445
1446</VirtualHost>
1447\end{lyxcode}
1448The last three characters (Qqz) in the directive are the SSL ones;
1449see the directives documentation for details.
1450
1451Perform some hits on your server and run a select:
1452
1453\begin{lyxcode}
1454mysql>~select~remote\_host,request\_uri,ssl\_cipher,ssl\_keysize,ssl\_maxkeysize~from~access\_log~where~ssl\_cipher~is~not~null;
1455
1456+-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-+-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-+-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-+-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-+-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-+~
1457
1458|~remote\_host~~~~~~~~~~~~~~|~request\_uri~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|~ssl\_cipher~|~ssl\_keysize~|~ssl\_maxkeysize~|
1459
1460+-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-+-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-+-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-+-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-+-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-+~
1461
1462|~216.190.52.4~~~~~~~~~~~~~|~/dir/somefile.html~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|~RC4-MD5~~~~|~128~~~~~~~~~|~128~~~~~~~~~~~~|~
1463
1464|~216.190.52.4~~~~~~~~~~~~~|~/dir/somefile.gif~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|~RC4-MD5~~~~|~128~~~~~~~~~|~128~~~~~~~~~~~~|~
1465
1466|~216.190.52.4~~~~~~~~~~~~~|~/dir/somefile.jpg~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|~RC4-MD5~~~~|~128~~~~~~~~~|~128~~~~~~~~~~~~|~
1467
1468...etc...
1469\end{lyxcode}
1470
1471\subsection{Does mod\_log\_sql connect to MySQL via TCP/IP or a socket?}
1472
1473It depends! Actually this isn't determined by mod\_log\_sql. mod\_log\_sql
1474relies on a connection command that is supplied in the MySQL API,
1475and that command is somewhat intelligent. When mod\_log\_sql issues
1476the connect command to MySQL, this intelligent connect command uses
1477sockets to communicate with MySQL if the specified MySQL database
1478is on the same machine (because sockets are more efficient than TCP/IP).
1479However, if the specified MySQL db is on a different machine, mod\_log\_sql
1480connects using TCP/IP. You don't have any control of which methodology
1481is used.
1482
1483You do have control over where mod\_log\_sql looks for the socket.
1484The LogSQLSocketFile runtime configuration directive overrides the
1485default of \char`\"{}/var/lib/mysql/mysql.sock\char`\"{} to whatever
1486you wish. (Applies to mod\_log\_sql 1.16 or later only.)
1487
1488
1489\subsection{Why do I occasionally see a \char`\"{}connection lost, attempting
1490reconnect\char`\"{} message in my error-log?}
1491
1492This message may appear every now and then in your Apache error log,
1493especially on very lightly loaded servers. This doesn't mean that
1494anything is necessarily wrong. Within each httpd child process, mod\_log\_sql
1495will open (and keep open) a connection to the MySQL server. MySQL,
1496however, will close connections that haven't been used in a while;
1497the default timeout is 8 hours. When this occurs, mod\_log\_sql will
1498notice and re-open the connection. That event is what is being logged,
1499and looks like this:
1500
1501\begin{lyxcode}
1502{[}Thu~Dec~13~05:42:18~2001{]}~{[}error{]}~mod\_log\_sql:~connection~lost,~attempting~reconnect
1503
1504{[}Thu~Dec~13~05:42:18~2001{]}~{[}error{]}~mod\_log\_sql:~reconnect~successful
1505\end{lyxcode}
1506Reference: MySQL documentation \url{http://www.mysql.com/documentation/mysql/bychapter/manual_Problems.html#Gone_away}
1507
1508
1509\subsection{Does mod\_log\_sql work with Apache 2.x?}
1510
1511As of this writing, no. The Apache Group significantly altered the
1512module API with the release of Apache 2.0. All modules written for
15131.3, including mod\_log\_sql, will not work with 2.0.
1514
1515mod\_log\_sql will eventually be ported to Apache 2.x, but not immediately.
1516It is going to take some time, and there are other features that have
1517higher priority. Please sign up for the announcements list (on the
1518main website) or monitor the website for updates to learn when the
1519port (and other releases) are available.
1520
1521<OPINION>If you're a {*}NIX user, stick with Apache 1.3.x for now.
1522Major modules like mod\_ssl and PHP are not even ready for 2.0 yet,
1523and the main benefits in 2.0 are for Win32 users anyway. Apache 1.3.x
1524is rock-stable and performs equally well on {*}NIX as 2.0.</OPINION>
1525
1526
1527\subsection{I have discovered a bug. Who can I contact?}
1528
1529Please contact the maintainer \url{chris@grubbybaby.com}! Your comments,
1530suggestions, bugfixes, bug catches, and usage testimonials are always
1531welcome. As free software, mod\_log\_sql is intended to be a community
1532effort -- any code contributions or other ideas will be fully and
1533openly credited, of course.
1534\end{document}
diff --git a/INSTALL b/INSTALL
index 7c48c21..20a4035 100644
--- a/INSTALL
+++ b/INSTALL
@@ -1,26 +1,27 @@
1$Id: INSTALL,v 1.9 2002/06/27 20:09:17 helios Exp $ 1$Id: INSTALL,v 1.10 2002/11/14 03:51:34 helios Exp $
2 2
3 3
4Requirements 4Requirements
5============ 5============
6 6
7* I run a Red Hat 6.2 system, but these instructions should easily 7* A compatible system. I have run mod_log_sql on Red Hat based systems
8 adapt to any modern distro. 8 (Red Hat, Mandrake). These instructions should easily adapt to any
9 modern distro.
9 10
10* Apache 1.2 or 1.3 installed. (I run 1.3.22 and it works fine). 11* Apache 1.2 or 1.3 installed. (I run 1.3.22 and it works fine).
11 You should have already successfully compiled Apache and know what 12 You should have already successfully compiled Apache and know what
12 you're doing there. In fact, you should already have any other 13 you're doing there.
13 modules and add-ons like mod_ssl or PHP configured and installed
14 before you start this process.
15 14
16* The MySQL development headers. (I run MySQL-devel-3.23.44-1.i386.rpm). 15* The MySQL development headers. This is called different things on
16 different distros. For example, Red Hat 6.x called this RPM
17 "MySQL-devel" whereas Mandrake calls it "libmysql10-devel".
17 18
18* MySQL >= 3.23.15 configured, installed and running on either 19* MySQL >= 3.23.15 configured, installed and running on either
19 localhost or an accessible networked machine. You should already 20 localhost or an accessible networked machine. You should already
20 have a basic understanding of MySQL and how it functions. 21 have a basic understanding of MySQL and how it functions.
21 22
22* Again, basic administrative skills with Apache and MySQL. I try to 23* Again, basic administrative skills with Apache and MySQL. I try to
23 make things as easy as possible in this README, but its purpose is 24 make things as easy as possible in this file, but its purpose is
24 not to be an administrative tutorial. 25 not to be an administrative tutorial.
25 26
26* Additionally, if you want to be able to log SSL information such as 27* Additionally, if you want to be able to log SSL information such as
@@ -37,9 +38,13 @@ doing that. If you're more of an old-school type and prefer to compile
37the modules right into apache, do that. Both methods work equally 38the modules right into apache, do that. Both methods work equally
38well. 39well.
39 40
41FWIW, the DSO method is more modern and increasing in popularity because
42apxs takes care of a lot of dirty little details for you. As you'll
43see below, the static-module method is a little more complex.
40 44
41Installation (as an Apache DSO) 45
42=============================== 46Installation as an Apache DSO (Preferred)
47=========================================
43 48
44For folks interested in using this module as an Apache DSO: 49For folks interested in using this module as an Apache DSO:
45 50
@@ -51,41 +56,68 @@ For folks interested in using this module as an Apache DSO:
51 # tar zxf mod_log_sql.tar.gz -C /usr/local/src 56 # tar zxf mod_log_sql.tar.gz -C /usr/local/src
52 # cd /usr/local/src/mod_log_sql 57 # cd /usr/local/src/mod_log_sql
53 58
542) Edit Makefile and make any adjustments for your system. These are 592) Edit Makefile for your system.
55 fully explained in the Makefile.
56 60
573) Instruct apxs to compile and install the module as a DSO. You need 61 NECESSARY:
58 to know two things before you run apxs: 62 - The location where you installed Apache -- usually /usr/local/apache,
59 - The location of the apxs binary, find using 'locate apxs' 63 'locate apxs' can help you find it.
60 - The location of your MySQL libraries, find using 'locate libmysqlclient' 64 - The location of your MySQL libraries, find using 'locate libmysqlclient'
65 - The location of your MySQL header files, find using 'locate mysql.h'
66
67 OPTIONAL if you have included mod_ssl in Apache and want to log SSL data
68 such as keysize and cipher type:
69 - The location of your SSL header files, find using 'locate mod_ssl.h'
70
71 Now that you know these things, edit Makefile and replace the stock
72 values with your own.
73
74 IMPORTANT: If you are not logging SSL info, comment out MODSSLHDRS by putting
75 a # character in front of it, e.g. #MODSSLHDRS=/usr/include/...
76
773) Instruct apxs to compile the module as a DSO.
78
79 # make dso
61 80
62 FORMAT: 81 You should see output similar to the following:
63 # <path>/apxs -i -c -L/path/to/mysqllibs -lmysqlclient -lz mod_log_sql.c
64 82
65 EXAMPLE: 83 /usr/local/Apache/bin/apxs -Wc,-O2 -Wc,-Wall -Wc,-DEAPI -c -I/usr/include/mysql -I/usr/local/src/apache_1.3.27-dso/src/modules/ssl -L/usr/lib -lmysqlclient -lz mod_log_sql.c
66 # /usr/sbin/apxs -i -c -L/usr/lib/mysql -lmysqlclient -lz mod_log_sql.c 84 gcc -DLINUX=22 -DNO_DBM_REWRITEMAP -DMOD_SSL=208111 -DUSE_HSREGEX -DEAPI -DUSE_EXPAT -I../lib/expat-lite -fpic -DSHARED_CORE -DSHARED_MODULE -I/usr/local/Apache/include -O2 -Wall -DEAPI -I/usr/include/mysql -I/usr/local/src/apache_1.3.27-dso/src/modules/ssl -c mod_log_sql.c
85 gcc -shared -o mod_log_sql.so mod_log_sql.o -Wc,-O2 -Wc,-Wall -Wc,-DEAPI -L/usr/lib -lmysqlclient -lz -lm -lcrypt -ldb
67 86
68 You should see something similar to this: 87 You should see no errors and have a file called "mod_log_sql.so" in your
88 directory.
69 89
70 gcc -fpic -DSHARED_MODULE -I/usr/local/apache/include -c mod_log_mysql.c 904) Instruct apxs to install the DSO.
71 gcc -shared -o mod_log_mysql.so mod_log_mysql.o -L/usr/local/lib/mysql/ -lmysqlclient -lz
72 cp mod_log_mysql.so /usr/local/apache/libexec/mod_log_mysql.so
73 chmod 755 /usr/local/apache/libexec/mod_log_mysql.so
74 91
754) Add the following lines to your httpd.conf file. Put the second line 92 # make dsoinstall
76 somewhere after the ClearModuleList directive.
77 93
78 LoadModule mysql_log_module libexec/mod_log_sql.so 94 You should see output similar to the following:
79 95
80 AddModule mod_log_sql.c 96 /usr/local/Apache/bin/apxs -i mod_log_sql.so
97 cp mod_log_sql.so /usr/local/Apache/libexec/mod_log_sql.so
98 chmod 755 /usr/local/Apache/libexec/mod_log_sql.so
81 99
825) Now go to step (9) in the instructions below to configure httpd.conf... 1005) Module ordering within httpd.conf is important. If you are logging
101 SSL, you must make sure that
83 102
103 LoadModule ssl_module libexec/libssl.so
84 104
85Installation (as a static module compiled into httpd) 105 comes before
86=====================================================
87 106
88[This is what I do, FYI.] 107 LoadModule sql_log_module libexec/mod_log_sql.so
108
109 If you don't, you will get this error when you start Apache:
110 /usr/local/apache/libexec/mod_log_mysql.so: undefined symbol: ssl_var_lookup
111 /usr/local/apache/bin/apachectl startssl: httpd could not be started
112
113 (Because mod_log_sql doesn't yet have the required symbols that mod_ssl
114 provides.)
115
1166) Now skip below to the "Configuration" section.
117
118
119Installation as a static module compiled into httpd
120===================================================
89 121
900) Perform all the following steps as root so that you have install 1220) Perform all the following steps as root so that you have install
91 privs, etc. 123 privs, etc.
@@ -95,17 +127,31 @@ Installation (as a static module compiled into httpd)
95 # tar zxf mod_log_sql.tar.gz -C /usr/local/src 127 # tar zxf mod_log_sql.tar.gz -C /usr/local/src
96 # cd /usr/local/src/mod_log_sql 128 # cd /usr/local/src/mod_log_sql
97 129
982) Examine the DEFINEs at the top of mod_log_sql.c and alter any that 1302) Edit Makefile for your system.
99 you choose. Edit Makefile and make any adjustments for your system.
100 These are fully explained in the Makefile.
101 131
1023) # make all 132 NECESSARY:
103 (You should receive NO warnings or errors of any kind. 133 - The location where you installed Apache -- usually /usr/local/apache,
104 If you see messages like this: "mod_log_sql.c:69: httpd.h: No such 134 'locate apxs' can help you find it.
105 file or directory" then you do not have your CFLAGS correctly 135 - The location of your Apache *sources*, find using 'locate ABOUT_APACHE'
106 pointing to the right include directory.) 136 - The location of your MySQL header files, find using 'locate mysql.h'
137 - The location of your MySQL libraries, find using 'locate libmysqlclient'
107 138
1084) # make install 139 OPTIONAL if you have included mod_ssl in Apache and want to log SSL data
140 such as keysize and cipher type:
141 - The location of your mod_ssl header files, find using 'locate mod_ssl.h'
142 - The location of your OpenSSL header files, find using 'locate x509.h'
143 - The location of your db1 header files, find using 'locate mpool.h'
144
145 Now that you know these things, edit Makefile and replace the stock
146 values with your own.
147
148 IMPORTANT: If you are not logging SSL info, comment out MODSSLHDRS,
149 OPNSSLHDRS and DB1HDRS by putting a # character in front of each one,
150 e.g. #OPNSSLHDRS=/usr/include/...
151
1523) # make static
153
1544) # make statinstall
109 155
1105) Change to your Apache source dir. 1565) Change to your Apache source dir.
111 157
@@ -115,11 +161,14 @@ Installation (as a static module compiled into httpd)
115 161
116 6a) Edit Configuration.apaci as follows... 162 6a) Edit Configuration.apaci as follows...
117 163
118 * Append the following string to the EXTRA_LIBS= line. (/usr/lib/mysql is where your libmysqlclient.a file lives): 164 * Append the following string to the EXTRA_LIBS= line. ("/usr/lib/mysql"
119 -L/usr/lib/mysql -lmysqlclient -lm -lz 165 is from step 2, where your MySQL libraries live):
166
167 -L/usr/lib/mysql -lmysqlclient -lm -lz
120 168
121 * Find the mod_log_config.o line, and add this line immediately after it: 169 * Find the mod_log_config.o line, and add this line immediately after it:
122 AddModule modules/sql/mod_log_sql.o 170
171 AddModule modules/sql/mod_log_sql.o
123 172
124 6b) # cp Configuration.apaci Configuration 173 6b) # cp Configuration.apaci Configuration
125 174
@@ -146,100 +195,113 @@ Installation (as a static module compiled into httpd)
146 195
1478) Install your httpd binary. Copy it over your old httpd binary, 1968) Install your httpd binary. Copy it over your old httpd binary,
148 wherever it lives. You can and should rename your old httpd first so 197 wherever it lives. You can and should rename your old httpd first so
149 that you can easily revert to that working version in case of bugs or 198 that you can easily revert to that working version in case of bugs
150 whatever. 199 with the new version.
151 200
152 # /etc/rc.d/init.d/httpd stop 201 # /etc/rc.d/init.d/httpd stop
202 # mv /usr/local/Apache/bin/httpd ~/httpd-save
153 # cp -f ./httpd /usr/local/Apache/bin/ 203 # cp -f ./httpd /usr/local/Apache/bin/
154 204
1559) Configure your apache daemon to log to your database. Here's a very
156 basic set of config lines to start you off. Full documentation is
157 available here: http://www.grubbybaby.com/mod_log_sql/directives.html
158 205
159 EXAMPLE: Connect to the MySQL database called "apache" running 206Configuration
160 on "dbmachine.foo.com". The module uses username "loguser" and 207=============
161 password "l0gger" to authenticate to the database; this user must,
162 of course, exist in the MySQL user table and have the proper
163 permissions -- more on that in step 11. The log entries will be
164 INSERTed into the table called "access_log".
165 208
209You have to prepare the database to receive data from mod_log_sql, and
210set up run-time directives in httpd.conf to control how and what mod_log_sql
211logs.
166 212
167 MySQLLoginInfo dbmachine.foo.com loguser l0gger 213This section will discuss how to get started with a basic config. Full
168 MySQLDatabase apache 214documentation of the run-time directives is available here:
215http://www.grubbybaby.com/mod_log_sql/directives.html
169 216
170 <VirtualHost 1.2.3.4> 2171) mod_log_sql can make its own tables on-the-fly, or you can pre-make
171 [snip] 218 the tables by hand. The advantage of letting the module make the
219 tables is ease-of-use, but for raw performance you will want to
220 pre-make the tables in order to save overhead.
172 221
173 MySQLTransferLogTable access_log 222 In this basic setup we'll let the module create tables for us.
174 MySQLTransferLogFormat huSUsbTvRA
175 223
176 [snip] 224 We still need to have a logging database created and ready, so
177 </VirtualHost> 225 run the MySQL command line client and create a database:
178 226
227 # mysql -uadmin -pmypassword
228 mysql> create database apachelogs;
179 229
180 9a) Special step for users who have a DSO-enabled httpd: 230 If you want to hand-create the tables, run the enclosed 'create-tables'
231 SQL script as follows:
181 232
182 If you you are building mod_log_sql as a static module BUT 233 mysql> source create_tables.sql
183 your httpd is enabled for DSOs, add the following line to your
184 httpd.conf:
185 234
186 AddModule mod_log_sql.c 2352) Create a specific MySQL userid that httpd will use to authenticate
236 and enter data. This userid need not be an actual Unix user. It
237 is a userid internal to MySQL with specific privileges.
187 238
239 In the following example command, "apachelogs" is the database, "loguser"
240 is the userid to create, "my.apachemachine.com" is the name of the Apache
241 machine, and "l0gger" is the password to assign. Choose values that are
242 different from these examples.
188 243
18910) If you compiled mod_log_sql with the ability to make its own tables 244 mysql> grant insert,create on apachelogs.* to loguser@my.apachemachine.com identified by 'l0gger';
190 then you can skip this step. Otherwise you need to do it by hand:
191 245
192 Create a database and table to hold the new log data. I log the 246 You may be especially security-paranoid and not want "loguser" to have
193 same data as the regular "combined log" plus a little extra information 247 "create" capability within the "apachelogs" databse. You can disable that
194 that can be useful. 248 but the cost is that you cannot use the module's automatic-table-creation
249 feature. If that's an acceptable cost, hand-create the tables as described
250 in step 1 and use the following GRANT statement instead of the one above:
195 251
196 The order that the fields appear in the table is irrelevant 252 mysql> grant insert on apachelogs.* to loguser@my.apachemachine.com identified by 'l0gger';
197 because you can SELECT them in any order you choose. To create
198 this table I first created a new database called "apache":
199 253
200 # mysql -uadmin -pmypassword 2543) Enable full logging of your MySQL daemon (at least temporarily
201 mysql> create database apache; 255 for debugging purposes) if you don't do this already:
202 256
203 Then create the table called "access_log". I enclosed an SQL file 257 Edit /etc/my.cnf and add the following line to your [mysqld] section:
204 that will create every column type that mod_log_sql supports.
205 Unless you're just testing or playing around, this is probably NOT
206 what you want, so edit the file first and delete the lines that
207 don't pertain to you. Then:
208 258
209 mysql> source access_log.sql 259 log=/var/log/mysql-messages
210 260
261 Then restart MySQL.
211 262
21211) Create a specific MySQL userid that httpd will use to authenticate 2634) Tell the module what database to use and the appropriate authentication
213 and enter data. This userid need not be an actual Unix user. It 264 information.
214 is a userid internal to MySQL with specific privileges.
215
216 mysql> grant insert,create on apache.* to loguser@my.apachemachine.com identified by 'l0gger';
217
218 Security is a very real concern. mod_log_sql by default is
219 set up to create the SQL tables it needs. If you have deactivated
220 this capability, then create a user called "loguser" with the password
221 "l0gger" with only the capability of INSERT to "access_log":
222 265
223 mysql> grant insert on apache.access_log to loguser@my.apachemachine.com identified by 'l0gger'; 266 OUR EXAMPLE: use the MySQL database called "apachelogs" running
267 on "dbmachine.foo.com". The module uses username "loguser" and
268 password "l0gger" to authenticate to the database. The log entries
269 will be INSERTed into the table called "access_log".
224 270
271 So, edit httpd.conf and insert the following lines somewhere AFTER any
272 LoadModule / AddModule statements. Make sure these statements are
273 "global," i.e. not inside any VirtualHost stanza.
225 274
22612) Enable full logging of your MySQL daemon (at least temporarily 275 LogSQLDatabase apachelogs
227 for debugging purposes) if you don't do this already: 276 LogSQLLoginInfo dbmachine.foo.com loguser l0gger
277 LogSQLCreateTables on
228 278
229 Edit /etc/my.cnf and add the following line to your [mysqld] section: 279 If your database resides on localhost instead of another host, specify
280 the MySQL server's socket file as follows:
230 281
231 log=/var/log/mysql-messages 282 LogSQLSocketFile /your/path/to/mysql.sock
232 283
233 Then restart MySQL. 2845) The actual logging is set up on a virtual-host-by-host basis. So,
285 skip down to the virtual host you want to set up. The LogSQLTransferLogTable
286 directive is the minimum required to log -- other directives simply
287 tune the module's behavior.
234 288
23513) Restart apache. 289 <VirtualHost 1.2.3.4>
290 [snip]
291
292 LogSQLTransferLogTable access_log
293
294 [snip]
295 </VirtualHost>
296
2976) Restart apache.
236 298
237 # /etc/rc.d/init.d/httpd start 299 # /etc/rc.d/init.d/httpd start
238 300
23913) Load your web site in a browser to trigger some hits, then confirm that 3017) Load your web site in a browser to trigger some hits, then confirm that
240 the entries are being successfully logged: 302 the entries are being successfully logged:
241 303
242 # mysql -hmysql.host.com -umysqladmin -p -e "select * from access_log" apache; 304 # mysql -hmysql.host.com -umysqladmin -p -e "select * from access_log" apachelogs
243 Enter password: 305 Enter password:
244 306
245 +---------------------------------------------------+-------------+-------------+------------------+------------------+------------+--------+------------+------------------------------------+ 307 +---------------------------------------------------+-------------+-------------+------------------+------------------+------------+--------+------------+------------------------------------+
@@ -251,10 +313,29 @@ Installation (as a static module compiled into httpd)
251 . 313 .
252 +---------------------------------------------------+-------------+-------------+------------------+------------------+------------+--------+------------+------------------------------------+ 314 +---------------------------------------------------+-------------+-------------+------------------+------------------+------------+--------+------------+------------------------------------+
253 315
25414) You have basic functionality. Don't disable your regular Apache logs until 316 You have basic functionality. Don't disable your regular Apache logs until
255 you feel comfortable that the database is behaving as you'd like and that 317 you feel comfortable that the database is behaving as you'd like and that
256 things are going well. 318 things are going well.
257 319
258 3208) If you do not see any entries in the access_log, then something is preventing
259 321 the inserts from happening. This problem could be caused by several things:
260 322 - Improper privileges set up in the MySQL database
323 - You aren't hitting a VirtualHost that has a LogSQLTransferLogTable entry
324 - You didn't specify the right host
325
326 If you have confirmed your LogSQL* directives and know them to be correct,
327 you should examine the httpd server logs for mod_log_sql messages; the module
328 will offer hints as to why it cannot connect, etc. Also examine the MySQL
329 log that you established in step 3. Ensure that the INSERTs are not being
330 rejected because of a malformed table entry or other clerical error. If you
331 see no INSERT attempts in the log, the module isn't successfully connecting
332 to the database.
333
334 The next thing to do is recompile the module with debugging output activated.
335 change the "#undef DEBUG" on line 8 of mod_log_sql.c to "#define DEBUG" and
336 recompile/reinstall. The module will now output copious notes about what
337 it is doing, and this will help you (and the maintainer) solve the problem.
338
3399) You can now activate the advanced features of mod_log_sql. These are all
340 described in the online directive documentation:
341 http://www.grubbybaby.com/mod_log_sql/directives.html
diff --git a/Makefile b/Makefile
index ed31430..8c654a6 100644
--- a/Makefile
+++ b/Makefile
@@ -1,88 +1,71 @@
1# $Id: Makefile,v 1.11 2002/09/04 18:46:00 helios Exp $ 1# $Id: Makefile,v 1.12 2002/11/14 03:51:34 helios Exp $
2MLMVERS = 1.17 2
3 3#####################################
4# Where you unpacked your Apache tarball -- the source. 4# Important:
5APACHESOURCE = /usr/local/src/apache_1.3.26 5# Adjust these values as outlined in the INSTALL file.
6 6# Not all are needed at all times.
7# Where Apache [got|will get] installed 7
8APACHEINST = /usr/local/Apache 8APACHEINST = /usr/local/Apache
9 9MYSQLLIBS = /usr/lib
10# Do you want to log SSL information? 10MYSQLHDRS = /usr/include/mysql
11# Yes? 11#MODSSLHDRS = /usr/local/src/apache_1.3.27-dso/src/modules/ssl
12# - #define WANT_SSL_LOGGING in mod_log_sql.c 12
13# - pick (A) below 13APACHESOURCE = /usr/local/src/apache_1.3.27-dso
14# No? 14OPNSSLHDRS = /usr/include/openssl
15# - #undef WANT_SSL_LOGGING in mod_log_sql.c 15DB1HDRS = /usr/include/db1
16# - pick (B) below 16
17 17
18 18#####################################
19# (A) 19# Shouldn't have to touch below here.
20# 20
21# Modify "/usr/include/mysql" to where YOUR mysql.h can be found, 21MLMVERS = 1.17
22# Modify "/usr/local/ssl/include" to where YOUR openssl/*.h files are, 22APXS = $(APACHEINST)/bin/apxs
23# Modify "/usr/include/db1" to where YOUR ndbm.h can be found, 23#APXSGDB = -Wc,-g
24# Modify "/usr/local/src/apache_1.3.22/src/modules/ssl" to where YOUR mod_ssl.h can be found. 24APXSOPTS = -Wc,-O2 -Wc,-Wall -Wc,-DEAPI
25# 25CC = gcc
26# How to find your directories: 26INSTALL = /usr/bin/install -m 664
27# 27RM = /bin/rm
28# $ locate mysql.h 28
29# /usr/include/mysql/mysql.h 29ifdef MODSSLHDRS
30# ^^^^^^^^^^^^^^^^^^ 30 SSLDEF = -DWANT_SSL_LOGGING
31# 31 CFLAGS = -fPIC -O2 -Wall -I$(APACHEINST)/include -I$(MYSQLHDRS) -I$(MODSSLHDRS) -I$(OPNSSLHDRS) $(SSLDEF) -I$(DB1HDRS)
32# $ locate x509.h 32else
33# /usr/local/ssl/include/openssl/x509.h 33 CFLAGS = -fPIC -O2 -Wall -I$(APACHEINST)/include -I$(MYSQLHDRS)
34# ^^^^^^^^^^^^^^^^^^^^^^ 34endif
35# 35
36# $ locate ndbm.h 36all:
37# /usr/include/db1/ndbm.h 37 @echo "You can choose to make mod_log_sql as a static or dynamic module."
38# ^^^^^^^^^^^^^^^^ 38 @echo "Either 'make dso' or 'make static'."
39# 39 @echo
40# $ locate mod_ssl.h 40 @echo "Please read the INSTALL file carefully!"
41# /usr/local/src/apache_1.3.22/src/modules/ssl/mod_ssl.h 41
42# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 42dso: mod_log_sql.so
43# Now uncomment this CFLAGS and comment out the one further down: 43
44 44static: mod_log_sql.o
45CFLAGS = -fpic -O2 -Wall -I${APACHEINST}/include -I/usr/include/mysql -I/usr/local/ssl/include -I/usr/include/db1 -I${APACHESOURCE}/src/modules/ssl 45
46 46mod_log_sql.so: mod_log_sql.c Makefile
47# (B) 47 $(APXS) $(APXSGDB) $(APXOPTS) -c -I$(MYSQLHDRS) -I$(MODSSLHDRS) $(SSLDEF) -L$(MYSQLLIBS) -lmysqlclient -lz mod_log_sql.c
48#
49# Modify "/usr/include/mysql" to where YOUR mysql.h can be found,
50#
51# How to find your directories:
52#
53# $ locate mysql.h
54# /usr/include/mysql/mysql.h
55# ^^^^^^^^^^^^^^^^^^
56#
57# Comment out CFLAGS above and uncomment CFLAGS below:
58
59#CFLAGS = -fpic -O2 -Wall -I${APACHEINST}/include -I/usr/include/mysql
60
61
62# ---------------------------------------------------------
63# You shouldn't have to touch below here.
64
65CC = gcc
66INSTALL = /usr/bin/install -m 664
67
68all: mod_log_sql.o
69 48
70mod_log_sql.o: mod_log_sql.c Makefile 49mod_log_sql.o: mod_log_sql.c Makefile
71 $(CC) ${CFLAGS} -c mod_log_sql.c 50 $(CC) ${CFLAGS} -c mod_log_sql.c
72
73install: all
74 $(INSTALL) -d -m 755 ${APACHESOURCE}/src/modules/sql
75 $(INSTALL) mod_log_sql.c ${APACHESOURCE}/src/modules/sql/mod_log_sql.c
76 $(INSTALL) Makefile ${APACHESOURCE}/src/modules/sql/Makefile
77 $(INSTALL) mod_log_sql.o ${APACHESOURCE}/src/modules/sql/mod_log_sql.o
78 51
79distro: all 52dsoinstall: dso
80 cp -f INSTALL ${APACHEINST}/html/mod_log_sql/ 53 $(APXS) -i mod_log_sql.so
81 cp -f README ${APACHEINST}/html/mod_log_sql/ 54
82 cp -f CHANGELOG ${APACHEINST}/html/mod_log_sql/ 55statinstall: static
83 cd ..; tar zcf mod_log_sql-${MLMVERS}.tar.gz --exclude mod_log_sql/CVS mod_log_sql/; $(INSTALL) mod_log_sql-${MLMVERS}.tar.gz ${APACHEINST}/html/mod_log_sql/; rm -f mod_log_sql-${MLMVERS}.tar.gz 56 $(INSTALL) -d -m 755 $(APACHESOURCE)/src/modules/sql
84 rm -f ${APACHEINST}/html/mod_log_sql/mod_log_sql.tar.gz 57 $(INSTALL) mod_log_sql.c $(APACHESOURCE)/src/modules/sql/mod_log_sql.c
85 ln -s mod_log_sql-${MLMVERS}.tar.gz ${APACHEINST}/html/mod_log_sql/mod_log_sql.tar.gz 58 $(INSTALL) Makefile $(APACHESOURCE)/src/modules/sql/Makefile
59 $(INSTALL) mod_log_sql.o $(APACHESOURCE)/src/modules/sql/mod_log_sql.o
86 60
87clean: 61clean:
88 rm -f *.o *~ 62 $(RM) -rf *.o *.so
63
64distro: all
65 cp -f INSTALL $(APACHEINST)/html/mod_log_sql/
66 cp -f README $(APACHEINST)/html/mod_log_sql/
67 cp -f CHANGELOG $(APACHEINST)/html/mod_log_sql/
68 cd ..; tar zcf mod_log_sql-$(MLMVERS).tar.gz --exclude mod_log_sql/CVS mod_log_sql/; $(INSTALL) mod_log_sql-$(MLMVERS).tar.gz $(APACHEINST)/html/mod_log_sql/; rm -f mod_log_sql-$(MLMVERS).tar.gz
69 rm -f $(APACHEINST)/html/mod_log_sql/mod_log_sql.tar.gz
70 ln -s mod_log_sql-$(MLMVERS).tar.gz $(APACHEINST)/html/mod_log_sql/mod_log_sql.tar.gz
71
diff --git a/README b/README
index 077b6c4..fd1cdc7 100644
--- a/README
+++ b/README
@@ -1,130 +1,5 @@
1$Id: README,v 1.6 2002/05/14 21:47:15 helios Exp $ 1$Id: README,v 1.7 2002/11/14 03:51:34 helios Exp $
2
3
4Homepage
5--------
6http://www.grubbybaby.com/mod_log_sql/
7
8
9Approach
10--------
11This project was formerly known as mod_log_mysql. It has been renamed
12to mod_log_sql in order to reflect the project goal of
13database-inspecificity. The module currently supports MySQL, and
14development for other database backends is underway.
15
16In order to save speed and overhead, links are kept alive in between
17queries. This module uses one SQL link per httpd process. Among other
18things, this means that this module supports logging into only one
19MySQL server, and for now, also, only one SQL database. But that's a
20small tradeoff compared to the blinding speed of this module.
21
22Virtual hosts are supported in the same manner they are in the regular
23logging modules. You define some basic 'global' directives in the
24main server config, then you define more specific 'local' directives
25inside each virtualhost stanza.
26
27SQL links are opened by each child process when it is born. Error reporting
28is robust throughout and will let you know about database issues
29in the standard Apache error-log for the server or virtual server.
30
31A robust "preserve" capability has now been implemented. This permits
32the module to preserve any failed INSERT commands to a local file on
33its machine. In any situation that the database is unavailable -- e.g.
34the network fails, you reboot the db host, etc. -- mod_log_sql will
35note this in the error log and begin appending its log entries to the
36preserve file (which is created with the user & group ID of the running
37Apache process, e.g. "nobody" on many Linux installations). At the time
38that your MySQL server returns to service, each of these preserve files
39is easily imported because it is simply a series of SQL insert statements:
40
41 # mysql -uadminuser -p mydbname < /tmp/mysql-preserve
42
43
44
45Supported directives
46--------------------
47
48Please see the web-based documentation for full explanation of all
49supported run-time directives.
50
51 http://www.grubbybaby.com/mod_log_sql/directives.html
52
53See the FAQ for some handy examples:
54
55 http://www.grubbybaby.com/mod_log_sql/faq.html
56
57
58What gets logged by default?
59----------------------------
60
61All the data that would be contained in the "Combined Log Format"
62is logged by default, plus a little extra. Your best bet is to
63begin by accepting this default, then later customize the log
64configuration based on your needs.
65
66The online documentation of the run-time directives includes a full
67explanation of what you can log, including examples.
68
69
70Notes
71-----
72
73* You will customarily set most of your run-time configuration directives
74 on a per-virtualserver basis, with only MySQLMassVirtualHosting,
75 MySQLLoginInfo, MySQLDatabase, MySQLSocketFile, MySQLCreateTables,
76 and MySQLMassVirtualHosting 'outside' in the main server config. Any
77 directives other than those in the main config do NOT get inherited
78 by the virutal servers.
79
80* The 'time_stamp' field is stored in an UNSIGNED INTEGER column, in the
81 standard unix "seconds since 1/1/1970 12:00:00" format. This is
82 superior to storing the access time as a string due to size
83 requirements: an UNSIGNED INT type fits in 4 bytes, whereas the Apache date
84 string (e.g. "18/Nov/2001:13:59:52 -0800") requires 26 bytes --
85 significantly larger, and those extra 22 bytes will add up over the
86 thousands of accesses that a busy server will experience. Besides,
87 an INT type is far more flexible for comparisons, etc.
88
89 In MySQL 3.21 and above you can easily convert this to a human
90 readable format using from_unixtime(), e.g.:
91
92 select remote_host,request_uri,from_unixtime(time_stamp) from access_log;
93
94 The enclosed perl program make_combined_log.pl shows how you can
95 extract your access records in a format that is completely Combined
96 Log Format compliant. You can then feed this to your favorite web
97 log analysis tool.
98
99* The table's string values can be CHAR or VARCHAR, at a length of your choice.
100 VARCHAR is superior because it truncates long strings; CHAR types are
101 fixed-length and will be padded with spaces. Just like the
102 time_stamp described above, that kind of space waste will add up over
103 thousands of records.
104
105* Be careful not to go overboard setting fields to NOT NULL. If a field is
106 marked NOT NULL then it must contain data in the INSERT or the INSERT
107 will fail.
108
109* Apache normally logs numeric fields with a '-' character to mean "not
110 applicable," e.g. bytes_sent on a request with a 304 response code.
111 Since '-' is an illegal character in an SQL numeric field, such
112 fields are assigned the value 0 instead of '-' which, of course,
113 makes perfect sense anyway.
114
115
116
117Author / Maintainer
118-------------------
119
120The actual logging code was taken from the already existing flat file
121text modules, so all that credit goes to the Apache Server group.
122
123The MySQL routines and directives were added by Zeev Suraski
124<bourbon@netvision.net.il>.
125
126All changes from 1.06+ and the new documentation were added by
127Chris Powell <chris@grubbybaby.com>. It seems that the module had fallen
128into the "unmaintained" category -- it hadn't been updated since 1998 --
129so Chris adopted it as the new maintainer.
130 2
3This document has been superseded by the new documentation
4in the Documentation/ directory. There you will find
5PS, plaintext, and HTML versions of the documentation.
diff --git a/access_log.sql b/access_log.sql
deleted file mode 100644
index 4966c62..0000000
--- a/access_log.sql
+++ /dev/null
@@ -1,25 +0,0 @@
1create table access_log (
2 agent varchar(255) ,
3 bytes_sent int ,
4 child_pid smallint unsigned,
5 cookie varchar(255),
6 request_file varchar(255),
7 referer varchar(255) ,
8 remote_host varchar(50) ,
9 remote_logname varchar(50) ,
10 remote_user varchar(50) ,
11 request_duration smallint ,
12 request_line varchar(255),
13 request_method varchar(6) ,
14 request_protocol varchar(10) ,
15 request_time char(28),
16 request_uri varchar(50) ,
17 server_port smallint unsigned,
18 ssl_cipher varchar(25),
19 ssl_keysize smallint unsigned,
20 ssl_maxkeysize smallint unsigned,
21 status smallint ,
22 time_stamp int unsigned ,
23 virtual_host varchar(50)
24)
25
diff --git a/create_tables.sql b/create_tables.sql
new file mode 100644
index 0000000..430d1a7
--- /dev/null
+++ b/create_tables.sql
@@ -0,0 +1,50 @@
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(50) ,
19 server_port smallint unsigned,
20 ssl_cipher varchar(25),
21 ssl_keysize smallint unsigned,
22 ssl_maxkeysize smallint unsigned,
23 status smallint unsigned ,
24 time_stamp int unsigned ,
25 virtual_host varchar(50)
26);
27
28create table notes (
29 id char(19),
30 item varchar(80),
31 val varchar(80)
32);
33
34create table headers_in (
35 id char(19),
36 item varchar(80),
37 val varchar(80)
38);
39
40create table headers_out (
41 id char(19),
42 item varchar(80),
43 val varchar(80)
44);
45
46create table cookies (
47 id char(19),
48 item varchar(80),
49 val varchar(80)
50); \ No newline at end of file
diff --git a/make_combined_log.pl b/make_combined_log.pl
index cefc728..1741dbf 100755
--- a/make_combined_log.pl
+++ b/make_combined_log.pl
@@ -1,6 +1,6 @@
1#!/usr/bin/perl 1#!/usr/bin/perl
2 2
3# $Id: make_combined_log.pl,v 1.4 2002/01/02 20:47:44 helios Exp $ 3# $Id: make_combined_log.pl,v 1.5 2002/11/14 03:51:34 helios Exp $
4# 4#
5# make_combined_log.pl 5# make_combined_log.pl
6# 6#
@@ -69,7 +69,7 @@ if (not $dbh) {
69 die "Unable to connect to the database. Please check your connection variables. (Bad password? Incorrect perms?)"; 69 die "Unable to connect to the database. Please check your connection variables. (Bad password? Incorrect perms?)";
70} 70}
71 71
72$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"); 72$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");
73$records->execute; 73$records->execute;
74if (not $records) { 74if (not $records) {
75 die "No such table or the select returned no records." 75 die "No such table or the select returned no records."
diff --git a/mod_log_sql.c b/mod_log_sql.c
index a0cceb2..ba60089 100644
--- a/mod_log_sql.c
+++ b/mod_log_sql.c
@@ -1,21 +1,19 @@
1/* $Id: mod_log_sql.c,v 1.16 2002/09/04 18:46:00 helios Exp $ */ 1/* $Id: mod_log_sql.c,v 1.17 2002/11/14 03:51:35 helios Exp $ */
2 2
3/* --------* 3/* --------*
4 * DEFINES * 4 * DEFINES *
5 * --------*/ 5 * --------*/
6 6
7/* The enduser probably won't modify these */ 7/* The enduser may wish to modify this */
8#undef DEBUG
9
10/* The enduser won't modify these */
8#define MYSQL_ERROR(mysql) ((mysql)?(mysql_error(mysql)):"MySQL server has gone away") 11#define MYSQL_ERROR(mysql) ((mysql)?(mysql_error(mysql)):"MySQL server has gone away")
9#define ERRLEVEL APLOG_ERR|APLOG_NOERRNO 12#define ERRLEVEL APLOG_ERR|APLOG_NOERRNO
10#define WARNINGLEVEL APLOG_WARNING|APLOG_NOERRNO 13#define WARNINGLEVEL APLOG_WARNING|APLOG_NOERRNO
11#define NOTICELEVEL APLOG_NOTICE|APLOG_NOERRNO 14#define NOTICELEVEL APLOG_NOTICE|APLOG_NOERRNO
12#define DEBUGLEVEL APLOG_DEBUG|APLOG_NOERRNO 15#define DEBUGLEVEL APLOG_DEBUG|APLOG_NOERRNO
13 16
14/* The enduser may wish to modify these */
15#define WANT_SSL_LOGGING
16#undef DEBUG
17
18
19/* ---------* 17/* ---------*
20 * INCLUDES * 18 * INCLUDES *
21 * ---------*/ 19 * ---------*/
@@ -41,7 +39,7 @@
41 * -------------*/ 39 * -------------*/
42 40
43/* Declare ourselves so the configuration routines can find and know us. */ 41/* Declare ourselves so the configuration routines can find and know us. */
44module mysql_log_module; 42module sql_log_module;
45 43
46/* The contents of these are known 'Apache wide' and are not variable 44/* The contents of these are known 'Apache wide' and are not variable
47 * on a per-virtual-server basis. Every virtual server 'knows' the 45 * on a per-virtual-server basis. Every virtual server 'knows' the
@@ -51,18 +49,21 @@ MYSQL sql_server, *mysql_log = NULL;
51 49
52int massvirtual = 0; 50int massvirtual = 0;
53int create_tables = 0; 51int create_tables = 0;
52int force_preserve = 0;
54char *db_name = NULL; 53char *db_name = NULL;
55char *db_host = NULL; 54char *db_host = NULL;
56char *db_user = NULL; 55char *db_user = NULL;
57char *db_pwd = NULL; 56char *db_pwd = NULL;
57char *mach_id = NULL;
58char *socket_file = "/tmp/mysql.sock"; 58char *socket_file = "/tmp/mysql.sock";
59unsigned int tcp_port = 3306;
59 60
60typedef const char *(*item_key_func) (request_rec *, char *); 61typedef const char *(*item_key_func) (request_rec *, char *);
61 62
62/* But the contents of this structure will vary by virtual server. 63/* But the contents of this structure will vary by virtual server.
63 * This permits each virtual server to vary its configuration slightly 64 * This permits each virtual server to vary its configuration slightly
64 * for per-server customization. 65 * for per-server customization.
65 * 66 *
66 * Each child process has its own segregated copy of this structure. 67 * Each child process has its own segregated copy of this structure.
67 */ 68 */
68typedef struct { 69typedef struct {
@@ -73,9 +74,11 @@ typedef struct {
73 array_header *notes_list; 74 array_header *notes_list;
74 array_header *hout_list; 75 array_header *hout_list;
75 array_header *hin_list; 76 array_header *hin_list;
77 array_header *cookie_list;
76 char *notes_table_name; 78 char *notes_table_name;
77 char *hout_table_name; 79 char *hout_table_name;
78 char *hin_table_name; 80 char *hin_table_name;
81 char *cookie_table_name;
79 char *transfer_table_name; 82 char *transfer_table_name;
80 char *transfer_log_format; 83 char *transfer_log_format;
81 char *preserve_file; 84 char *preserve_file;
@@ -133,7 +136,7 @@ static const char *extract_remote_user(request_rec *r, char *a)
133static const char *extract_ssl_keysize(request_rec *r, char *a) 136static const char *extract_ssl_keysize(request_rec *r, char *a)
134{ 137{
135 char *result = NULL; 138 char *result = NULL;
136 139
137 if (ap_ctx_get(r->connection->client->ctx, "ssl") != NULL) { 140 if (ap_ctx_get(r->connection->client->ctx, "ssl") != NULL) {
138 result = ssl_var_lookup(r->pool, r->server, r->connection, r, "SSL_CIPHER_USEKEYSIZE"); 141 result = ssl_var_lookup(r->pool, r->server, r->connection, r, "SSL_CIPHER_USEKEYSIZE");
139 #ifdef DEBUG 142 #ifdef DEBUG
@@ -150,7 +153,7 @@ static const char *extract_ssl_keysize(request_rec *r, char *a)
150static const char *extract_ssl_maxkeysize(request_rec *r, char *a) 153static const char *extract_ssl_maxkeysize(request_rec *r, char *a)
151{ 154{
152 char *result = NULL; 155 char *result = NULL;
153 156
154 if (ap_ctx_get(r->connection->client->ctx, "ssl") != NULL) { 157 if (ap_ctx_get(r->connection->client->ctx, "ssl") != NULL) {
155 result = ssl_var_lookup(r->pool, r->server, r->connection, r, "SSL_CIPHER_ALGKEYSIZE"); 158 result = ssl_var_lookup(r->pool, r->server, r->connection, r, "SSL_CIPHER_ALGKEYSIZE");
156 #ifdef DEBUG 159 #ifdef DEBUG
@@ -167,7 +170,7 @@ static const char *extract_ssl_maxkeysize(request_rec *r, char *a)
167static const char *extract_ssl_cipher(request_rec *r, char *a) 170static const char *extract_ssl_cipher(request_rec *r, char *a)
168{ 171{
169 char *result = NULL; 172 char *result = NULL;
170 173
171 if (ap_ctx_get(r->connection->client->ctx, "ssl") != NULL) { 174 if (ap_ctx_get(r->connection->client->ctx, "ssl") != NULL) {
172 result = ssl_var_lookup(r->pool, r->server, r->connection, r, "SSL_CIPHER"); 175 result = ssl_var_lookup(r->pool, r->server, r->connection, r, "SSL_CIPHER");
173 #ifdef DEBUG 176 #ifdef DEBUG
@@ -225,6 +228,7 @@ static const char *extract_bytes_sent(request_rec *r, char *a)
225 } 228 }
226} 229}
227 230
231/*
228static const char *extract_header_in(request_rec *r, char *a) 232static const char *extract_header_in(request_rec *r, char *a)
229{ 233{
230 return table_get(r->headers_in, a); 234 return table_get(r->headers_in, a);
@@ -241,6 +245,7 @@ static const char *extract_header_out(request_rec *r, char *a)
241 } 245 }
242 return table_get(r->err_headers_out, a); 246 return table_get(r->err_headers_out, a);
243} 247}
248*/
244 249
245static const char *extract_request_time(request_rec *r, char *a) 250static const char *extract_request_time(request_rec *r, char *a)
246{ 251{
@@ -278,6 +283,14 @@ static const char *extract_virtual_host(request_rec *r, char *a)
278 return ap_get_server_name(r); 283 return ap_get_server_name(r);
279} 284}
280 285
286static const char *extract_machine_id(request_rec *r, char *a)
287{
288 if (!mach_id)
289 return "-";
290 else
291 return mach_id;
292}
293
281static const char *extract_server_port(request_rec *r, char *a) 294static const char *extract_server_port(request_rec *r, char *a)
282{ 295{
283 char portnum[22]; 296 char portnum[22];
@@ -309,7 +322,7 @@ static const char *extract_referer(request_rec *r, char *a)
309static const char *extract_agent(request_rec *r, char *a) 322static const char *extract_agent(request_rec *r, char *a)
310{ 323{
311 const char *tempag; 324 const char *tempag;
312 325
313 tempag = table_get(r->headers_in, "User-Agent"); 326 tempag = table_get(r->headers_in, "User-Agent");
314 if (!tempag) 327 if (!tempag)
315 { 328 {
@@ -325,14 +338,14 @@ static const char *extract_cookie(request_rec *r, char *a)
325 char *cookieend; 338 char *cookieend;
326 char *isvalid; 339 char *isvalid;
327 char *cookiebuf; 340 char *cookiebuf;
328 341
329 log_sql_state *cls = get_module_config(r->server->module_config, &mysql_log_module); 342 log_sql_state *cls = get_module_config(r->server->module_config, &sql_log_module);
330 343
331 if (cls->cookie_name != NULL) { 344 if (cls->cookie_name != NULL) {
332 #ifdef DEBUG 345 #ifdef DEBUG
333 ap_log_error(APLOG_MARK,DEBUGLEVEL,r->server,"watching for cookie '%s'", cls->cookie_name); 346 ap_log_error(APLOG_MARK,DEBUGLEVEL,r->server,"watching for cookie '%s'", cls->cookie_name);
334 #endif 347 #endif
335 348
336 /* Fetch out the cookie header */ 349 /* Fetch out the cookie header */
337 cookiestr = (char *)table_get(r->headers_in, "cookie2"); 350 cookiestr = (char *)table_get(r->headers_in, "cookie2");
338 if (cookiestr != NULL) { 351 if (cookiestr != NULL) {
@@ -346,7 +359,7 @@ static const char *extract_cookie(request_rec *r, char *a)
346 isvalid += strlen(cls->cookie_name) + 1; 359 isvalid += strlen(cls->cookie_name) + 1;
347 /* Duplicate it into the pool */ 360 /* Duplicate it into the pool */
348 cookiebuf = ap_pstrdup(r->pool, isvalid); 361 cookiebuf = ap_pstrdup(r->pool, isvalid);
349 /* Segregate just this cookie out of the string 362 /* Segregate just this cookie out of the string
350 * with a terminating nul at the first semicolon */ 363 * with a terminating nul at the first semicolon */
351 cookieend = strchr(cookiebuf, ';'); 364 cookieend = strchr(cookiebuf, ';');
352 if (cookieend != NULL) 365 if (cookieend != NULL)
@@ -354,7 +367,7 @@ static const char *extract_cookie(request_rec *r, char *a)
354 return cookiebuf; 367 return cookiebuf;
355 } 368 }
356 } 369 }
357 370
358 cookiestr = (char *)table_get(r->headers_in, "cookie"); 371 cookiestr = (char *)table_get(r->headers_in, "cookie");
359 if (cookiestr != NULL) { 372 if (cookiestr != NULL) {
360 #ifdef DEBUG 373 #ifdef DEBUG
@@ -370,7 +383,7 @@ static const char *extract_cookie(request_rec *r, char *a)
370 return cookiebuf; 383 return cookiebuf;
371 } 384 }
372 } 385 }
373 386
374 cookiestr = table_get(r->headers_out, "set-cookie"); 387 cookiestr = table_get(r->headers_out, "set-cookie");
375 if (cookiestr != NULL) { 388 if (cookiestr != NULL) {
376 #ifdef DEBUG 389 #ifdef DEBUG
@@ -387,10 +400,81 @@ static const char *extract_cookie(request_rec *r, char *a)
387 } 400 }
388 } 401 }
389 } 402 }
390 403
391 return "-"; 404 return "-";
392} 405}
393 406
407static const char *extract_specific_cookie(request_rec *r, char *a)
408{
409 const char *cookiestr;
410 char *cookieend;
411 char *isvalid;
412 char *cookiebuf;
413
414 if (a != NULL) {
415 #ifdef DEBUG
416 ap_log_error(APLOG_MARK,DEBUGLEVEL,r->server,"watching for cookie '%s'", a);
417 #endif
418
419 /* Fetch out the cookie header */
420 cookiestr = (char *)table_get(r->headers_in, "cookie2");
421 if (cookiestr != NULL) {
422 #ifdef DEBUG
423 ap_log_error(APLOG_MARK,DEBUGLEVEL,r->server,"Cookie2: [%s]", cookiestr);
424 #endif
425 /* Does the cookie string contain one with our name? */
426 isvalid = strstr(cookiestr, a);
427 if (isvalid != NULL) {
428 /* Move past the cookie name and equal sign */
429 isvalid += strlen(a) + 1;
430 /* Duplicate it into the pool */
431 cookiebuf = ap_pstrdup(r->pool, isvalid);
432 /* Segregate just this cookie out of the string
433 * with a terminating nul at the first semicolon */
434 cookieend = strchr(cookiebuf, ';');
435 if (cookieend != NULL)
436 *cookieend = '\0';
437 return cookiebuf;
438 }
439 }
440
441 cookiestr = (char *)table_get(r->headers_in, "cookie");
442 if (cookiestr != NULL) {
443 #ifdef DEBUG
444 ap_log_error(APLOG_MARK,DEBUGLEVEL,r->server,"Cookie: [%s]", cookiestr);
445 #endif
446 isvalid = strstr(cookiestr, a);
447 if (isvalid != NULL) {
448 isvalid += strlen(a) + 1;
449 cookiebuf = ap_pstrdup(r->pool, isvalid);
450 cookieend = strchr(cookiebuf, ';');
451 if (cookieend != NULL)
452 *cookieend = '\0';
453 return cookiebuf;
454 }
455 }
456
457 cookiestr = table_get(r->headers_out, "set-cookie");
458 if (cookiestr != NULL) {
459 #ifdef DEBUG
460 ap_log_error(APLOG_MARK,DEBUGLEVEL,r->server,"Set-Cookie: [%s]", cookiestr);
461 #endif
462 isvalid = strstr(cookiestr, a);
463 if (isvalid != NULL) {
464 isvalid += strlen(a) + 1;
465 cookiebuf = ap_pstrdup(r->pool, isvalid);
466 cookieend = strchr(cookiebuf, ';');
467 if (cookieend != NULL)
468 *cookieend = '\0';
469 return cookiebuf;
470 }
471 }
472 }
473
474 return "-";
475}
476
477
394static const char *extract_request_timestamp(request_rec *r, char *a) 478static const char *extract_request_timestamp(request_rec *r, char *a)
395{ 479{
396 char tstr[32]; 480 char tstr[32];
@@ -399,13 +483,13 @@ static const char *extract_request_timestamp(request_rec *r, char *a)
399 return pstrdup(r->pool, tstr); 483 return pstrdup(r->pool, tstr);
400} 484}
401 485
486/*
402static const char *extract_note(request_rec *r, char *a) 487static const char *extract_note(request_rec *r, char *a)
403{ 488{
404 return ap_table_get(r->notes, a); 489 return ap_table_get(r->notes, a);
405 490
406 /*ap_table_do(extract_table, r, r->notes, NULL);*/
407
408} 491}
492*/
409 493
410static const char *extract_env_var(request_rec *r, char *a) 494static const char *extract_env_var(request_rec *r, char *a)
411{ 495{
@@ -415,7 +499,7 @@ static const char *extract_env_var(request_rec *r, char *a)
415static const char *extract_unique_id(request_rec *r, char *a) 499static const char *extract_unique_id(request_rec *r, char *a)
416{ 500{
417 const char *tempid; 501 const char *tempid;
418 502
419 tempid = ap_table_get(r->subprocess_env, "UNIQUE_ID"); 503 tempid = ap_table_get(r->subprocess_env, "UNIQUE_ID");
420 if (!tempid) 504 if (!tempid)
421 return "-"; 505 return "-";
@@ -437,32 +521,30 @@ struct log_sql_item_list {
437 521
438 { 'A', extract_agent, "agent", 1, 1 }, 522 { 'A', extract_agent, "agent", 1, 1 },
439 { 'b', extract_bytes_sent, "bytes_sent", 0, 0 }, 523 { 'b', extract_bytes_sent, "bytes_sent", 0, 0 },
440 { 'c', extract_cookie, "cookie", 0, 1 }, 524 { 'c', extract_cookie, "cookie", 0, 1 },
441 { 'e', extract_env_var, "env_var", 0, 1 }, 525 { 'e', extract_env_var, "env_var", 0, 1 },
442 { 'f', extract_request_file, "request_file", 0, 1 }, 526 { 'f', extract_request_file, "request_file", 0, 1 },
443 { 'H', extract_request_protocol, "request_protocol", 0, 1 }, 527 { 'H', extract_request_protocol, "request_protocol", 0, 1 },
444 { 'h', extract_remote_host, "remote_host", 0, 1 }, 528 { 'h', extract_remote_host, "remote_host", 0, 1 },
445 { 'i', extract_header_in, "header_in", 0, 1 },
446 { 'I', extract_unique_id, "id", 0, 1 }, 529 { 'I', extract_unique_id, "id", 0, 1 },
447 { 'l', extract_remote_logname, "remote_logname", 0, 1 }, 530 { 'l', extract_remote_logname, "remote_logname", 0, 1 },
448 { 'm', extract_request_method, "request_method", 0, 1 }, 531 { 'm', extract_request_method, "request_method", 0, 1 },
449 { 'n', extract_note, "note", 0, 1 }, 532 { 'M', extract_machine_id, "machine_id", 0, 1 },
450 { 'o', extract_header_out, "header_out", 0, 1 }, 533 { 'P', extract_child_pid, "child_pid", 0, 0 },
451 { 'P', extract_child_pid, "child_pid", 0, 0 }, 534 { 'p', extract_server_port, "server_port", 0, 0 },
452 { 'p', extract_server_port, "server_port", 0, 0 }, 535 { 'R', extract_referer, "referer", 1, 1 },
453 { 'R', extract_referer, "referer", 1, 1 }, 536 { 'r', extract_request_line, "request_line", 1, 1 },
454 { 'r', extract_request_line, "request_line", 1, 1 }, 537 { 'S', extract_request_timestamp, "time_stamp", 0, 0 },
455 { 'S', extract_request_timestamp, "time_stamp", 0, 0 }, 538 { 's', extract_status, "status", 1, 0 },
456 { 's', extract_status, "status", 1, 0 }, 539 { 'T', extract_request_duration, "request_duration", 1, 0 },
457 { 'T', extract_request_duration, "request_duration", 1, 0 }, 540 { 't', extract_request_time, "request_time", 0, 1 },
458 { 't', extract_request_time, "request_time", 0, 1 }, 541 { 'u', extract_remote_user, "remote_user", 0, 1 },
459 { 'u', extract_remote_user, "remote_user", 0, 1 }, 542 { 'U', extract_request_uri, "request_uri", 1, 1 },
460 { 'U', extract_request_uri, "request_uri", 1, 1 }, 543 { 'v', extract_virtual_host, "virtual_host", 0, 1 },
461 { 'v', extract_virtual_host, "virtual_host", 0, 1 },
462 #ifdef WANT_SSL_LOGGING 544 #ifdef WANT_SSL_LOGGING
463 { 'q', extract_ssl_keysize, "ssl_keysize", 0, 1 }, 545 { 'q', extract_ssl_keysize, "ssl_keysize", 0, 1 },
464 { 'Q', extract_ssl_maxkeysize, "ssl_maxkeysize", 0, 1 }, 546 { 'Q', extract_ssl_maxkeysize, "ssl_maxkeysize", 0, 1 },
465 { 'z', extract_ssl_cipher, "ssl_cipher", 0, 1 }, 547 { 'z', extract_ssl_cipher, "ssl_cipher", 0, 1 },
466 #endif 548 #endif
467 {'\0'} 549 {'\0'}
468}; 550};
@@ -479,7 +561,7 @@ const char *escape_query(const char *from_str, pool *p)
479 char *to_str; 561 char *to_str;
480 unsigned long length = strlen(from_str); 562 unsigned long length = strlen(from_str);
481 unsigned long retval; 563 unsigned long retval;
482 564
483 /* Pre-allocate a new string that could hold twice the original, which would only 565 /* Pre-allocate a new string that could hold twice the original, which would only
484 * happen if the whole original string was 'dangerous' characters. 566 * happen if the whole original string was 'dangerous' characters.
485 */ 567 */
@@ -487,20 +569,20 @@ const char *escape_query(const char *from_str, pool *p)
487 if (!to_str) { 569 if (!to_str) {
488 return from_str; 570 return from_str;
489 } 571 }
490 572
491 if (!mysql_log) { 573 if (!mysql_log) {
492 /* Well, I would have liked to use the current database charset. mysql is 574 /* Well, I would have liked to use the current database charset. mysql is
493 * unavailable, however, so I fall back to the slightly less respectful 575 * unavailable, however, so I fall back to the slightly less respectful
494 * mysql_escape_string() function that uses the default charset. 576 * mysql_escape_string() function that uses the default charset.
495 */ 577 */
496 retval = mysql_escape_string(to_str, from_str, length); 578 retval = mysql_escape_string(to_str, from_str, length);
497 } else { 579 } else {
498 /* MySQL is available, so I'll go ahead and respect the current charset when 580 /* MySQL is available, so I'll go ahead and respect the current charset when
499 * I perform the escape. 581 * I perform the escape.
500 */ 582 */
501 retval = mysql_real_escape_string(mysql_log, to_str, from_str, length); 583 retval = mysql_real_escape_string(mysql_log, to_str, from_str, length);
502 } 584 }
503 585
504 if (retval) 586 if (retval)
505 return to_str; 587 return to_str;
506 else 588 else
@@ -508,24 +590,37 @@ const char *escape_query(const char *from_str, pool *p)
508 } 590 }
509} 591}
510 592
511int open_logdb_link() 593int open_logdb_link(server_rec* s)
512{ 594{
513 /* Returns 2 if already connected, 1 if successful, 0 if unsuccessful */ 595 /* Returns:
514 596 3 if preserve forced
515 if (mysql_log != NULL) { 597 2 if already connected
598 1 if successful
599 0 if unsuccessful
600 */
601
602 if (force_preserve)
603 return 3;
604
605 if (mysql_log != NULL)
516 return 2; 606 return 2;
517 }
518 607
519 if (db_name) { 608 if (db_name) {
520 mysql_init(&sql_server); 609 mysql_init(&sql_server);
521 mysql_log = mysql_real_connect(&sql_server, db_host, db_user, db_pwd, db_name, 0, socket_file, 0); 610 mysql_log = mysql_real_connect(&sql_server, db_host, db_user, db_pwd, db_name, tcp_port, socket_file, 0);
522 611
523 if (mysql_log != NULL) { 612 if (mysql_log) {
524 return 1; 613 return 1;
525 } else { 614 } else {
615 #ifdef DEBUG
616 ap_log_error(APLOG_MARK,DEBUGLEVEL,s,"mod_log_sql: database connection error: %s",MYSQL_ERROR(&sql_server));
617 ap_log_error(APLOG_MARK,DEBUGLEVEL,s,"HOST: '%s' PORT: '%d' DB: '%s' USER: '%s' SOCKET: '%s'",
618 db_host, tcp_port, db_name, db_user, socket_file);
619 #endif
526 return 0; 620 return 0;
527 } 621 }
528 } 622 }
623
529 return 0; 624 return 0;
530} 625}
531 626
@@ -536,13 +631,13 @@ static int trace(void *data, const char *key, const char *val)
536 request_rec *r = (request_rec *)data; 631 request_rec *r = (request_rec *)data;
537 632
538 fp = pfopen(r->pool, "/tmp/trace", "a"); 633 fp = pfopen(r->pool, "/tmp/trace", "a");
539 634
540 if (fp) { 635 if (fp) {
541 fprintf(fp, "Field '%s' == '%s'\n", key, val); 636 fprintf(fp, "Field '%s' == '%s'\n", key, val);
542 } 637 }
543 638
544 pfclose(r->pool, fp); 639 pfclose(r->pool, fp);
545 640
546 return TRUE; 641 return TRUE;
547} 642}
548#endif 643#endif
@@ -557,8 +652,8 @@ const char *extract_table(void *data, const char *key, const char *val)
557void preserve_entry(request_rec *r, const char *query) 652void preserve_entry(request_rec *r, const char *query)
558{ 653{
559 FILE *fp; 654 FILE *fp;
560 log_sql_state *cls = get_module_config(r->server->module_config, &mysql_log_module); 655 log_sql_state *cls = get_module_config(r->server->module_config, &sql_log_module);
561 656
562 fp = pfopen(r->pool, cls->preserve_file, "a"); 657 fp = pfopen(r->pool, cls->preserve_file, "a");
563 if (fp == NULL) 658 if (fp == NULL)
564 ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"mod_log_sql: attempted append of local preserve file but failed."); 659 ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"mod_log_sql: attempted append of local preserve file but failed.");
@@ -567,7 +662,7 @@ void preserve_entry(request_rec *r, const char *query)
567 pfclose(r->pool, fp); 662 pfclose(r->pool, fp);
568 #ifdef DEBUG 663 #ifdef DEBUG
569 ap_log_error(APLOG_MARK,DEBUGLEVEL,r->server,"mod_log_sql: entry preserved in %s", cls->preserve_file); 664 ap_log_error(APLOG_MARK,DEBUGLEVEL,r->server,"mod_log_sql: entry preserved in %s", cls->preserve_file);
570 #endif 665 #endif
571 } 666 }
572} 667}
573 668
@@ -588,32 +683,32 @@ unsigned int safe_mysql_query(request_rec *r, const char *query)
588 struct timespec delay, remainder; 683 struct timespec delay, remainder;
589 int ret; 684 int ret;
590 void (*handler) (int); 685 void (*handler) (int);
591 686
592 687
593 /* A failed mysql_query() may send a SIGPIPE, so we ignore that signal momentarily. */ 688 /* A failed mysql_query() may send a SIGPIPE, so we ignore that signal momentarily. */
594 handler = signal(SIGPIPE, SIG_IGN); 689 handler = signal(SIGPIPE, SIG_IGN);
595 690
596 /* First attempt for the query */ 691 /* First attempt for the query */
597 if (mysql_log != NULL) 692 if (mysql_log != NULL)
598 retval = mysql_query(mysql_log, query); 693 retval = mysql_query(mysql_log, query);
599 else 694 else
600 return 1; 695 return 1;
601 696
602 if ( retval != 0 ) 697 if ( retval != 0 )
603 { 698 {
604 /* If we ran the query and it returned an error, try to be robust. 699 /* If we ran the query and it returned an error, try to be robust.
605 * (After all, the module thought it had a valid mysql_log connection but the query 700 * (After all, the module thought it had a valid mysql_log connection but the query
606 * could have failed for a number of reasons, so we have to be extra-safe and check.) */ 701 * could have failed for a number of reasons, so we have to be extra-safe and check.) */
607 702
608 log_sql_state *cls = get_module_config(r->server->module_config, &mysql_log_module); 703 log_sql_state *cls = get_module_config(r->server->module_config, &sql_log_module);
609 704
610 real_error = mysql_errno(mysql_log); /* What really happened? */ 705 real_error = mysql_errno(mysql_log); /* What really happened? */
611 706
612 /* Something went wrong, so start by trying to restart the db link. */ 707 /* Something went wrong, so start by trying to restart the db link. */
613 ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"mod_log_sql: first attempt failed, API said: error %d, %s", real_error, MYSQL_ERROR(mysql_log)); 708 ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"mod_log_sql: first attempt failed, API said: error %d, %s", real_error, MYSQL_ERROR(mysql_log));
614 mysql_close(mysql_log); 709 mysql_close(mysql_log);
615 mysql_log = NULL; 710 mysql_log = NULL;
616 open_logdb_link(); 711 open_logdb_link(r->server);
617 712
618 if (mysql_log == NULL) { /* still unable to link */ 713 if (mysql_log == NULL) { /* still unable to link */
619 signal(SIGPIPE, handler); 714 signal(SIGPIPE, handler);
@@ -639,13 +734,13 @@ unsigned int safe_mysql_query(request_rec *r, const char *query)
639 real_error = mysql_errno(mysql_log); 734 real_error = mysql_errno(mysql_log);
640 ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"mod_log_sql: second attempt failed, API said: error %d, %s", real_error, MYSQL_ERROR(mysql_log)); 735 ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"mod_log_sql: second attempt failed, API said: error %d, %s", real_error, MYSQL_ERROR(mysql_log));
641 retval = real_error; 736 retval = real_error;
642 } else 737 } else
643 ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"mod_log_sql: second attempt successful"); 738 ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"mod_log_sql: second attempt successful");
644 } 739 }
645 740
646 /* Restore SIGPIPE to its original handler function */ 741 /* Restore SIGPIPE to its original handler function */
647 signal(SIGPIPE, handler); 742 signal(SIGPIPE, handler);
648 743
649 return retval; 744 return retval;
650} 745}
651 746
@@ -661,18 +756,20 @@ int safe_create_tables(log_sql_state *cls, request_rec *r)
661{ 756{
662 int retval; 757 int retval;
663 unsigned int create_results; 758 unsigned int create_results;
664 char *create_access = NULL; 759 char *create_access = NULL;
665 char *create_notes = NULL; 760 char *create_notes = NULL;
666 char *create_hout = NULL; 761 char *create_hout = NULL;
667 char *create_hin = NULL; 762 char *create_hin = NULL;
668 763 char *create_cookies = NULL;
669 char *createprefix = "create table if not exists "; 764
765 char *createprefix = "create table if not exists `";
670 char *access_suffix = 766 char *access_suffix =
671 " (id char(19),\ 767 "` (id char(19),\
672 agent varchar(255),\ 768 agent varchar(255),\
673 bytes_sent int unsigned,\ 769 bytes_sent int unsigned,\
674 child_pid smallint unsigned,\ 770 child_pid smallint unsigned,\
675 cookie varchar(255),\ 771 cookie varchar(255),\
772 machine_id varchar(25),\
676 request_file varchar(255),\ 773 request_file varchar(255),\
677 referer varchar(255),\ 774 referer varchar(255),\
678 remote_host varchar(50),\ 775 remote_host varchar(50),\
@@ -680,7 +777,7 @@ int safe_create_tables(log_sql_state *cls, request_rec *r)
680 remote_user varchar(50),\ 777 remote_user varchar(50),\
681 request_duration smallint unsigned,\ 778 request_duration smallint unsigned,\
682 request_line varchar(255),\ 779 request_line varchar(255),\
683 request_method varchar(6),\ 780 request_method varchar(10),\
684 request_protocol varchar(10),\ 781 request_protocol varchar(10),\
685 request_time char(28),\ 782 request_time char(28),\
686 request_uri varchar(50),\ 783 request_uri varchar(50),\
@@ -691,58 +788,71 @@ int safe_create_tables(log_sql_state *cls, request_rec *r)
691 status smallint unsigned,\ 788 status smallint unsigned,\
692 time_stamp int unsigned,\ 789 time_stamp int unsigned,\
693 virtual_host varchar(50))"; 790 virtual_host varchar(50))";
694 791
695 char *notes_suffix = 792 char *notes_suffix =
696 " (id char(19),\ 793 "` (id char(19),\
697 item varchar(80),\ 794 item varchar(80),\
698 val varchar(80))"; 795 val varchar(80))";
699 796
700 char *headers_suffix = 797 char *headers_suffix =
701 " (id char(19),\ 798 "` (id char(19),\
702 item varchar(80),\ 799 item varchar(80),\
703 val varchar(80))"; 800 val varchar(80))";
704 801
802 char *cookies_suffix =
803 "` (id char(19),\
804 item varchar(80),\
805 val varchar(80))";
806
705 /* Find memory long enough to hold the whole CREATE string + \0 */ 807 /* Find memory long enough to hold the whole CREATE string + \0 */
706 create_access = ap_pstrcat(r->pool, createprefix, cls->transfer_table_name, access_suffix, NULL); 808 create_access = ap_pstrcat(r->pool, createprefix, cls->transfer_table_name, access_suffix, NULL);
707 create_notes = ap_pstrcat(r->pool, createprefix, cls->notes_table_name, notes_suffix, NULL); 809 create_notes = ap_pstrcat(r->pool, createprefix, cls->notes_table_name, notes_suffix, NULL);
708 create_hout = ap_pstrcat(r->pool, createprefix, cls->hout_table_name, headers_suffix, NULL); 810 create_hout = ap_pstrcat(r->pool, createprefix, cls->hout_table_name, headers_suffix, NULL);
709 create_hin = ap_pstrcat(r->pool, createprefix, cls->hin_table_name, headers_suffix, NULL); 811 create_hin = ap_pstrcat(r->pool, createprefix, cls->hin_table_name, headers_suffix, NULL);
710 812 create_cookies= ap_pstrcat(r->pool, createprefix, cls->cookie_table_name, cookies_suffix, NULL);
813
711 #ifdef DEBUG 814 #ifdef DEBUG
712 ap_log_error(APLOG_MARK,DEBUGLEVEL,r->server,"mod_log_sql: create string: %s", create_access); 815 ap_log_error(APLOG_MARK,DEBUGLEVEL,r->server,"mod_log_sql: create string: %s", create_access);
713 ap_log_error(APLOG_MARK,DEBUGLEVEL,r->server,"mod_log_sql: create string: %s", create_notes); 816 ap_log_error(APLOG_MARK,DEBUGLEVEL,r->server,"mod_log_sql: create string: %s", create_notes);
714 ap_log_error(APLOG_MARK,DEBUGLEVEL,r->server,"mod_log_sql: create string: %s", create_hout); 817 ap_log_error(APLOG_MARK,DEBUGLEVEL,r->server,"mod_log_sql: create string: %s", create_hout);
715 ap_log_error(APLOG_MARK,DEBUGLEVEL,r->server,"mod_log_sql: create string: %s", create_hin); 818 ap_log_error(APLOG_MARK,DEBUGLEVEL,r->server,"mod_log_sql: create string: %s", create_hin);
819 ap_log_error(APLOG_MARK,DEBUGLEVEL,r->server,"mod_log_sql: create string: %s", create_cookies);
716 #endif 820 #endif
717 821
718 /* Assume that things worked unless told otherwise */ 822 /* Assume that things worked unless told otherwise */
719 cls->table_made = 1; 823 cls->table_made = 1;
720 retval = 0; 824 retval = 0;
721 825
722 if ((create_results = safe_mysql_query(r, create_access)) != 0) { 826 if ((create_results = safe_mysql_query(r, create_access)) != 0) {
723 cls->table_made = 0; 827 cls->table_made = 0;
724 ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"mod_log_sql: failed to create access table"); 828 ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"mod_log_sql: failed to create access table");
725 retval = create_results; 829 retval = create_results;
726 } 830 }
727 831
728 if ((create_results = safe_mysql_query(r, create_notes)) != 0) { 832 if ((create_results = safe_mysql_query(r, create_notes)) != 0) {
729 cls->table_made = 0; 833 cls->table_made = 0;
730 ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"mod_log_sql: failed to create notes table"); 834 ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"mod_log_sql: failed to create notes table");
731 retval = create_results; 835 retval = create_results;
732 } 836 }
733 837
734 if ((create_results = safe_mysql_query(r, create_hin)) != 0) { 838 if ((create_results = safe_mysql_query(r, create_hin)) != 0) {
735 cls->table_made = 0; 839 cls->table_made = 0;
736 ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"mod_log_sql: failed to create header_out table"); 840 ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"mod_log_sql: failed to create header_out table");
737 retval = create_results; 841 retval = create_results;
738 } 842 }
739 843
740 if ((create_results = safe_mysql_query(r, create_hout)) != 0) { 844 if ((create_results = safe_mysql_query(r, create_hout)) != 0) {
741 cls->table_made = 0; 845 cls->table_made = 0;
742 ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"mod_log_sql: failed to create header_in table"); 846 ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"mod_log_sql: failed to create header_in table");
743 retval = create_results; 847 retval = create_results;
744 } 848 }
745 849
850 if ((create_results = safe_mysql_query(r, create_cookies)) != 0) {
851 cls->table_made = 0;
852 ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"mod_log_sql: failed to create cookies table");
853 retval = create_results;
854 }
855
746 return retval; 856 return retval;
747} 857}
748 858
@@ -757,6 +867,18 @@ const char *set_log_sql_massvirtual(cmd_parms *parms, void *dummy, int flag)
757 return NULL; 867 return NULL;
758} 868}
759 869
870const char *set_log_sql_force_preserve(cmd_parms *parms, void *dummy, int flag)
871{
872 force_preserve = ( flag ? 1 : 0);
873 return NULL;
874}
875
876const char *set_log_sql_machine_id(cmd_parms *parms, void *dummy, char *arg)
877{
878 mach_id = arg;
879 return NULL;
880}
881
760const char *set_log_sql_create(cmd_parms *parms, void *dummy, int flag) 882const char *set_log_sql_create(cmd_parms *parms, void *dummy, int flag)
761{ 883{
762 if (massvirtual != 0) 884 if (massvirtual != 0)
@@ -774,7 +896,7 @@ const char *set_log_sql_db(cmd_parms *parms, void *dummy, char *arg)
774 896
775const char *set_log_sql_cookie(cmd_parms *parms, void *dummy, char *arg) 897const char *set_log_sql_cookie(cmd_parms *parms, void *dummy, char *arg)
776{ 898{
777 log_sql_state *cls = get_module_config(parms->server->module_config, &mysql_log_module); 899 log_sql_state *cls = get_module_config(parms->server->module_config, &sql_log_module);
778 900
779 cls->cookie_name = arg; 901 cls->cookie_name = arg;
780 return NULL; 902 return NULL;
@@ -783,7 +905,7 @@ const char *set_log_sql_cookie(cmd_parms *parms, void *dummy, char *arg)
783const char *set_log_sql_preserve_file(cmd_parms *parms, void *dummy, char *arg) 905const char *set_log_sql_preserve_file(cmd_parms *parms, void *dummy, char *arg)
784{ 906{
785 /* char *pfile; */ 907 /* char *pfile; */
786 log_sql_state *cls = get_module_config(parms->server->module_config, &mysql_log_module); 908 log_sql_state *cls = get_module_config(parms->server->module_config, &sql_log_module);
787 909
788 /* pfile = ap_pstrcat(parms->pool, "/tmp/", arg, NULL); */ 910 /* pfile = ap_pstrcat(parms->pool, "/tmp/", arg, NULL); */
789 cls->preserve_file = arg; 911 cls->preserve_file = arg;
@@ -806,7 +928,7 @@ const char *set_log_sql_info(cmd_parms *parms, void *dummy, char *host, char *us
806 928
807const char *set_log_sql_transfer_table(cmd_parms *parms, void *dummy, char *arg) 929const char *set_log_sql_transfer_table(cmd_parms *parms, void *dummy, char *arg)
808{ 930{
809 log_sql_state *cls = get_module_config(parms->server->module_config, &mysql_log_module); 931 log_sql_state *cls = get_module_config(parms->server->module_config, &sql_log_module);
810 932
811 if (massvirtual != 0) 933 if (massvirtual != 0)
812 ap_log_error(APLOG_MARK,WARNINGLEVEL,parms->server,"mod_log_sql: do not set LogSQLTransferLogTable when LogSQLMassVirtualHosting is On. Ignoring."); 934 ap_log_error(APLOG_MARK,WARNINGLEVEL,parms->server,"mod_log_sql: do not set LogSQLTransferLogTable when LogSQLMassVirtualHosting is On. Ignoring.");
@@ -815,9 +937,20 @@ const char *set_log_sql_transfer_table(cmd_parms *parms, void *dummy, char *arg)
815 return NULL; 937 return NULL;
816} 938}
817 939
940const char *set_log_sql_cookie_table(cmd_parms *parms, void *dummy, char *arg)
941{
942 log_sql_state *cls = get_module_config(parms->server->module_config, &sql_log_module);
943
944 if (massvirtual != 0)
945 ap_log_error(APLOG_MARK,WARNINGLEVEL,parms->server,"mod_log_sql: do not set LogSQLCookieLogTable when LogSQLMassVirtualHosting is On. Ignoring.");
946 else
947 cls->cookie_table_name = arg;
948 return NULL;
949}
950
818const char *set_log_sql_notes_table(cmd_parms *parms, void *dummy, char *arg) 951const char *set_log_sql_notes_table(cmd_parms *parms, void *dummy, char *arg)
819{ 952{
820 log_sql_state *cls = get_module_config(parms->server->module_config, &mysql_log_module); 953 log_sql_state *cls = get_module_config(parms->server->module_config, &sql_log_module);
821 954
822 if (massvirtual != 0) 955 if (massvirtual != 0)
823 ap_log_error(APLOG_MARK,WARNINGLEVEL,parms->server,"mod_log_sql: do not set LogSQLNotesLogTable when LogSQLMassVirtualHosting is On. Ignoring."); 956 ap_log_error(APLOG_MARK,WARNINGLEVEL,parms->server,"mod_log_sql: do not set LogSQLNotesLogTable when LogSQLMassVirtualHosting is On. Ignoring.");
@@ -828,7 +961,7 @@ const char *set_log_sql_notes_table(cmd_parms *parms, void *dummy, char *arg)
828 961
829const char *set_log_sql_hin_table(cmd_parms *parms, void *dummy, char *arg) 962const char *set_log_sql_hin_table(cmd_parms *parms, void *dummy, char *arg)
830{ 963{
831 log_sql_state *cls = get_module_config(parms->server->module_config, &mysql_log_module); 964 log_sql_state *cls = get_module_config(parms->server->module_config, &sql_log_module);
832 965
833 if (massvirtual != 0) 966 if (massvirtual != 0)
834 ap_log_error(APLOG_MARK,WARNINGLEVEL,parms->server,"mod_log_sql: do not set LogSQLHeadersInLogTable when LogSQLMassVirtualHosting is On. Ignoring."); 967 ap_log_error(APLOG_MARK,WARNINGLEVEL,parms->server,"mod_log_sql: do not set LogSQLHeadersInLogTable when LogSQLMassVirtualHosting is On. Ignoring.");
@@ -839,7 +972,7 @@ const char *set_log_sql_hin_table(cmd_parms *parms, void *dummy, char *arg)
839 972
840const char *set_log_sql_hout_table(cmd_parms *parms, void *dummy, char *arg) 973const char *set_log_sql_hout_table(cmd_parms *parms, void *dummy, char *arg)
841{ 974{
842 log_sql_state *cls = get_module_config(parms->server->module_config, &mysql_log_module); 975 log_sql_state *cls = get_module_config(parms->server->module_config, &sql_log_module);
843 976
844 if (massvirtual != 0) 977 if (massvirtual != 0)
845 ap_log_error(APLOG_MARK,WARNINGLEVEL,parms->server,"mod_log_sql: do not set LogSQLHeadersOutLogTable when LogSQLMassVirtualHosting is On. Ignoring."); 978 ap_log_error(APLOG_MARK,WARNINGLEVEL,parms->server,"mod_log_sql: do not set LogSQLHeadersOutLogTable when LogSQLMassVirtualHosting is On. Ignoring.");
@@ -850,7 +983,7 @@ const char *set_log_sql_hout_table(cmd_parms *parms, void *dummy, char *arg)
850 983
851const char *set_log_sql_transfer_log_format(cmd_parms *parms, void *dummy, char *arg) 984const char *set_log_sql_transfer_log_format(cmd_parms *parms, void *dummy, char *arg)
852{ 985{
853 log_sql_state *cls = get_module_config(parms->server->module_config, &mysql_log_module); 986 log_sql_state *cls = get_module_config(parms->server->module_config, &sql_log_module);
854 987
855 cls->transfer_log_format = arg; 988 cls->transfer_log_format = arg;
856 return NULL; 989 return NULL;
@@ -863,10 +996,17 @@ const char *set_log_sql_socket_file(cmd_parms *parms, void *dummy, char *arg)
863 return NULL; 996 return NULL;
864} 997}
865 998
999const char *set_log_sql_tcp_port(cmd_parms *parms, void *dummy, char *arg)
1000{
1001 tcp_port = (unsigned int)atoi(arg);
1002
1003 return NULL;
1004}
1005
866const char *add_log_sql_referer_ignore(cmd_parms *parms, void *dummy, char *arg) 1006const char *add_log_sql_referer_ignore(cmd_parms *parms, void *dummy, char *arg)
867{ 1007{
868 char **addme; 1008 char **addme;
869 log_sql_state *cls = get_module_config(parms->server->module_config, &mysql_log_module); 1009 log_sql_state *cls = get_module_config(parms->server->module_config, &sql_log_module);
870 1010
871 addme = push_array(cls->referer_ignore_list); 1011 addme = push_array(cls->referer_ignore_list);
872 *addme = pstrdup(cls->referer_ignore_list->pool, arg); 1012 *addme = pstrdup(cls->referer_ignore_list->pool, arg);
@@ -876,7 +1016,7 @@ const char *add_log_sql_referer_ignore(cmd_parms *parms, void *dummy, char *arg)
876const char *add_log_sql_transfer_ignore(cmd_parms *parms, void *dummy, char *arg) 1016const char *add_log_sql_transfer_ignore(cmd_parms *parms, void *dummy, char *arg)
877{ 1017{
878 char **addme; 1018 char **addme;
879 log_sql_state *cls = get_module_config(parms->server->module_config, &mysql_log_module); 1019 log_sql_state *cls = get_module_config(parms->server->module_config, &sql_log_module);
880 1020
881 addme = push_array(cls->transfer_ignore_list); 1021 addme = push_array(cls->transfer_ignore_list);
882 *addme = pstrdup(cls->transfer_ignore_list->pool, arg); 1022 *addme = pstrdup(cls->transfer_ignore_list->pool, arg);
@@ -886,7 +1026,7 @@ const char *add_log_sql_transfer_ignore(cmd_parms *parms, void *dummy, char *arg
886const char *add_log_sql_remhost_ignore(cmd_parms *parms, void *dummy, char *arg) 1026const char *add_log_sql_remhost_ignore(cmd_parms *parms, void *dummy, char *arg)
887{ 1027{
888 char **addme; 1028 char **addme;
889 log_sql_state *cls = get_module_config(parms->server->module_config, &mysql_log_module); 1029 log_sql_state *cls = get_module_config(parms->server->module_config, &sql_log_module);
890 1030
891 addme = push_array(cls->remhost_ignore_list); 1031 addme = push_array(cls->remhost_ignore_list);
892 *addme = pstrdup(cls->remhost_ignore_list->pool, arg); 1032 *addme = pstrdup(cls->remhost_ignore_list->pool, arg);
@@ -896,7 +1036,7 @@ const char *add_log_sql_remhost_ignore(cmd_parms *parms, void *dummy, char *arg)
896const char *add_log_sql_note(cmd_parms *parms, void *dummy, char *arg) 1036const char *add_log_sql_note(cmd_parms *parms, void *dummy, char *arg)
897{ 1037{
898 char **addme; 1038 char **addme;
899 log_sql_state *cls = get_module_config(parms->server->module_config, &mysql_log_module); 1039 log_sql_state *cls = get_module_config(parms->server->module_config, &sql_log_module);
900 1040
901 addme = push_array(cls->notes_list); 1041 addme = push_array(cls->notes_list);
902 *addme = pstrdup(cls->notes_list->pool, arg); 1042 *addme = pstrdup(cls->notes_list->pool, arg);
@@ -906,7 +1046,7 @@ const char *add_log_sql_note(cmd_parms *parms, void *dummy, char *arg)
906const char *add_log_sql_hout(cmd_parms *parms, void *dummy, char *arg) 1046const char *add_log_sql_hout(cmd_parms *parms, void *dummy, char *arg)
907{ 1047{
908 char **addme; 1048 char **addme;
909 log_sql_state *cls = get_module_config(parms->server->module_config, &mysql_log_module); 1049 log_sql_state *cls = get_module_config(parms->server->module_config, &sql_log_module);
910 1050
911 addme = push_array(cls->hout_list); 1051 addme = push_array(cls->hout_list);
912 *addme = pstrdup(cls->hout_list->pool, arg); 1052 *addme = pstrdup(cls->hout_list->pool, arg);
@@ -916,13 +1056,22 @@ const char *add_log_sql_hout(cmd_parms *parms, void *dummy, char *arg)
916const char *add_log_sql_hin(cmd_parms *parms, void *dummy, char *arg) 1056const char *add_log_sql_hin(cmd_parms *parms, void *dummy, char *arg)
917{ 1057{
918 char **addme; 1058 char **addme;
919 log_sql_state *cls = get_module_config(parms->server->module_config, &mysql_log_module); 1059 log_sql_state *cls = get_module_config(parms->server->module_config, &sql_log_module);
920 1060
921 addme = push_array(cls->hin_list); 1061 addme = push_array(cls->hin_list);
922 *addme = pstrdup(cls->hin_list->pool, arg); 1062 *addme = pstrdup(cls->hin_list->pool, arg);
923 return NULL; 1063 return NULL;
924} 1064}
925 1065
1066const char *add_log_sql_cookie(cmd_parms *parms, void *dummy, char *arg)
1067{
1068 char **addme;
1069 log_sql_state *cls = get_module_config(parms->server->module_config, &sql_log_module);
1070
1071 addme = push_array(cls->cookie_list);
1072 *addme = pstrdup(cls->cookie_list->pool, arg);
1073 return NULL;
1074}
926 1075
927 1076
928 1077
@@ -932,7 +1081,7 @@ const char *add_log_sql_hin(cmd_parms *parms, void *dummy, char *arg)
932 *------------------------------------------------------------*/ 1081 *------------------------------------------------------------*/
933 1082
934 1083
935/* 1084/*
936 * This function is called during server initialisation when an heavy-weight 1085 * This function is called during server initialisation when an heavy-weight
937 * process (such as a child) is being initialised. As with the 1086 * process (such as a child) is being initialised. As with the
938 * module-initialisation function, any information that needs to be recorded 1087 * module-initialisation function, any information that needs to be recorded
@@ -943,19 +1092,20 @@ const char *add_log_sql_hin(cmd_parms *parms, void *dummy, char *arg)
943static void log_sql_child_init(server_rec *s, pool *p) 1092static void log_sql_child_init(server_rec *s, pool *p)
944{ 1093{
945 int retval; 1094 int retval;
946 1095
947 retval = open_logdb_link(); 1096 retval = open_logdb_link(s);
948 if (retval == 0) 1097 if (retval == 0)
949 ap_log_error(APLOG_MARK,ERRLEVEL,s,"mod_log_sql: child spawned but unable to open database link"); 1098 ap_log_error(APLOG_MARK,ERRLEVEL,s,"mod_log_sql: child spawned but unable to open database link");
950 1099
951 #ifdef DEBUG 1100 #ifdef DEBUG
952 if (retval > 0) { 1101 if ( (retval == 1) || (retval == 2) )
953 ap_log_error(APLOG_MARK,DEBUGLEVEL,s,"mod_log_sql: open_logdb_link successful"); 1102 ap_log_error(APLOG_MARK,DEBUGLEVEL,s,"mod_log_sql: open_logdb_link successful");
954 } 1103 if (retval == 3)
1104 ap_log_error(APLOG_MARK,DEBUGLEVEL,s,"mod_log_sql: open_logdb_link said that preservation is forced");
955 #endif 1105 #endif
956} 1106}
957 1107
958/* 1108/*
959 * This function is called when an heavy-weight process (such as a child) is 1109 * This function is called when an heavy-weight process (such as a child) is
960 * being run down or destroyed. As with the child-initialisation function, 1110 * being run down or destroyed. As with the child-initialisation function,
961 * any information that needs to be recorded must be in static cells, since 1111 * any information that needs to be recorded must be in static cells, since
@@ -973,15 +1123,15 @@ static void log_sql_child_exit(server_rec *s, pool *p)
973void *log_sql_initializer(server_rec *main_server, pool *p) 1123void *log_sql_initializer(server_rec *main_server, pool *p)
974{ 1124{
975 server_rec *s; 1125 server_rec *s;
976 1126
977 log_sql_state main_conf = ap_get_module_config(main_server->module_config, &mysql_log_module); 1127 log_sql_state main_conf = ap_get_module_config(main_server->module_config, &sql_log_module);
978 1128
979 for (server_rec *s = main_server; s; s = s->next) { 1129 for (server_rec *s = main_server; s; s = s->next) {
980 conf = ap_get_module_config(s->module_config, &mysql_log_module); 1130 conf = ap_get_module_config(s->module_config, &sql_log_module);
981 if (conf->transfer_log_format == NULL && s != main_server) { 1131 if (conf->transfer_log_format == NULL && s != main_server) {
982 *conf = *main_conf; 1132 *conf = *main_conf;
983 } 1133 }
984 1134
985} 1135}
986 */ 1136 */
987 1137
@@ -996,26 +1146,28 @@ void *log_sql_initializer(server_rec *main_server, pool *p)
996 */ 1146 */
997void *log_sql_make_state(pool *p, server_rec *s) 1147void *log_sql_make_state(pool *p, server_rec *s)
998{ 1148{
999 1149
1000 log_sql_state *cls = (log_sql_state *) ap_palloc(p, sizeof(log_sql_state)); 1150 log_sql_state *cls = (log_sql_state *) ap_palloc(p, sizeof(log_sql_state));
1001 1151
1002 cls->transfer_table_name = NULL; 1152 /* These defaults are overridable in the httpd.conf file. */
1003 cls->transfer_log_format = NULL; 1153 cls->transfer_table_name = NULL; /* No default b/c we want its absence to disable logging */
1154 cls->transfer_log_format = "AbHhmRSsTUuv";
1004 cls->notes_table_name = "notes"; 1155 cls->notes_table_name = "notes";
1005 cls->hin_table_name = "headers_in"; 1156 cls->hin_table_name = "headers_in";
1006 cls->hout_table_name = "headers_out"; 1157 cls->hout_table_name = "headers_out";
1007 1158 cls->cookie_table_name = "cookies";
1159 cls->preserve_file = "/tmp/sql-preserve";
1160
1008 cls->referer_ignore_list = make_array(p, 1, sizeof(char *)); 1161 cls->referer_ignore_list = make_array(p, 1, sizeof(char *));
1009 cls->transfer_ignore_list = make_array(p, 1, sizeof(char *)); 1162 cls->transfer_ignore_list = make_array(p, 1, sizeof(char *));
1010 cls->remhost_ignore_list = make_array(p, 1, sizeof(char *)); 1163 cls->remhost_ignore_list = make_array(p, 1, sizeof(char *));
1011 cls->notes_list = make_array(p, 1, sizeof(char *)); 1164 cls->notes_list = make_array(p, 1, sizeof(char *));
1012 cls->hin_list = make_array(p, 1, sizeof(char *)); 1165 cls->hin_list = make_array(p, 1, sizeof(char *));
1013 cls->hout_list = make_array(p, 1, sizeof(char *)); 1166 cls->hout_list = make_array(p, 1, sizeof(char *));
1167 cls->cookie_list = make_array(p, 1, sizeof(char *));
1014 cls->table_made = 0; 1168 cls->table_made = 0;
1015
1016 cls->preserve_file = "/tmp/sql-preserve";
1017 cls->cookie_name = NULL; 1169 cls->cookie_name = NULL;
1018 1170
1019 return (void *) cls; 1171 return (void *) cls;
1020} 1172}
1021 1173
@@ -1036,9 +1188,15 @@ command_rec log_sql_cmds[] = {
1036 {"LogSQLHeadersInLogTable", set_log_sql_hin_table, NULL, RSRC_CONF, TAKE1, 1188 {"LogSQLHeadersInLogTable", set_log_sql_hin_table, NULL, RSRC_CONF, TAKE1,
1037 "The database table that holds the inbound headers"} 1189 "The database table that holds the inbound headers"}
1038 , 1190 ,
1191 {"LogSQLCookieLogTable", set_log_sql_cookie_table, NULL, RSRC_CONF, TAKE1,
1192 "The database table that holds the cookie info"}
1193 ,
1039 {"LogSQLTransferLogFormat", set_log_sql_transfer_log_format, NULL, RSRC_CONF, TAKE1, 1194 {"LogSQLTransferLogFormat", set_log_sql_transfer_log_format, NULL, RSRC_CONF, TAKE1,
1040 "Instruct the module what information to log to the database transfer log"} 1195 "Instruct the module what information to log to the database transfer log"}
1041 , 1196 ,
1197 {"LogSQLMachineID", set_log_sql_machine_id, NULL, RSRC_CONF, TAKE1,
1198 "Machine ID that the module will log, useful in web clusters to differentiate machines"}
1199 ,
1042 {"LogSQLRefererIgnore", add_log_sql_referer_ignore, NULL, RSRC_CONF, ITERATE, 1200 {"LogSQLRefererIgnore", add_log_sql_referer_ignore, NULL, RSRC_CONF, ITERATE,
1043 "List of referers to ignore. Accesses that match will not be logged to database"} 1201 "List of referers to ignore. Accesses that match will not be logged to database"}
1044 , 1202 ,
@@ -1052,7 +1210,7 @@ command_rec log_sql_cmds[] = {
1052 "The name of the database database for logging"} 1210 "The name of the database database for logging"}
1053 , 1211 ,
1054 {"LogSQLWhichCookie", set_log_sql_cookie, NULL, RSRC_CONF, TAKE1, 1212 {"LogSQLWhichCookie", set_log_sql_cookie, NULL, RSRC_CONF, TAKE1,
1055 "The CookieName that you want logged when using the 'c' config directive"} 1213 "The single cookie that you want logged in the access_log when using the 'c' config directive"}
1056 , 1214 ,
1057 {"LogSQLLoginInfo", set_log_sql_info, NULL, RSRC_CONF, TAKE3, 1215 {"LogSQLLoginInfo", set_log_sql_info, NULL, RSRC_CONF, TAKE3,
1058 "The database host, user-id and password for logging"} 1216 "The database host, user-id and password for logging"}
@@ -1063,33 +1221,42 @@ command_rec log_sql_cmds[] = {
1063 {"LogSQLMassVirtualHosting", set_log_sql_massvirtual, NULL, RSRC_CONF, FLAG, 1221 {"LogSQLMassVirtualHosting", set_log_sql_massvirtual, NULL, RSRC_CONF, FLAG,
1064 "Activates option(s) useful for ISPs performing mass virutal hosting"} 1222 "Activates option(s) useful for ISPs performing mass virutal hosting"}
1065 , 1223 ,
1224 {"LogSQLForcePreserve", set_log_sql_force_preserve, NULL, RSRC_CONF, FLAG,
1225 "Forces logging to preserve file and bypasses database"}
1226 ,
1066 {"LogSQLPreserveFile", set_log_sql_preserve_file, NULL, RSRC_CONF, TAKE1, 1227 {"LogSQLPreserveFile", set_log_sql_preserve_file, NULL, RSRC_CONF, TAKE1,
1067 "Name of the file to use for data preservation during database downtime"} 1228 "Name of the file to use for data preservation during database downtime"}
1068 , 1229 ,
1069 {"LogSQLSocketFile", set_log_sql_socket_file, NULL, RSRC_CONF, TAKE1, 1230 {"LogSQLSocketFile", set_log_sql_socket_file, NULL, RSRC_CONF, TAKE1,
1070 "Name of the file to employ for socket connections to database"} 1231 "Name of the file to employ for socket connections to database"}
1071 , 1232 ,
1233 {"LogSQLTCPPort", set_log_sql_tcp_port, NULL, RSRC_CONF, TAKE1,
1234 "Port number to use for TCP connections to database, defaults to 3306 if not set"}
1235 ,
1072 {"LogSQLWhichNotes", add_log_sql_note, NULL, RSRC_CONF, ITERATE, 1236 {"LogSQLWhichNotes", add_log_sql_note, NULL, RSRC_CONF, ITERATE,
1073 "Members of the 'notes' that you would like to log"} 1237 "Notes that you would like to log in a separate table"}
1074 , 1238 ,
1075 {"LogSQLWhichHeadersOut", add_log_sql_hout, NULL, RSRC_CONF, ITERATE, 1239 {"LogSQLWhichHeadersOut", add_log_sql_hout, NULL, RSRC_CONF, ITERATE,
1076 "Members of the 'headers out' that you would like to log"} 1240 "Outbound headers that you would like to log in a separate table"}
1077 , 1241 ,
1078 {"LogSQLWhichHeadersIn", add_log_sql_hin, NULL, RSRC_CONF, ITERATE, 1242 {"LogSQLWhichHeadersIn", add_log_sql_hin, NULL, RSRC_CONF, ITERATE,
1079 "Members of the 'headers in' that you would like to log"} 1243 "Inbound headers that you would like to log in a separate table"}
1244 ,
1245 {"LogSQLWhichCookies", add_log_sql_cookie, NULL, RSRC_CONF, ITERATE,
1246 "The cookie(s) that you would like to log in a separate table"}
1080 , 1247 ,
1081 {NULL} 1248 {NULL}
1082}; 1249};
1083 1250
1084 1251
1085 1252
1086/* Routine to perform the actual construction and execution of the relevant 1253/* Routine to perform the actual construction and execution of the relevant
1087 * INSERT statements. 1254 * INSERT statements.
1088 */ 1255 */
1089int log_sql_transaction(request_rec *orig) 1256int log_sql_transaction(request_rec *orig)
1090{ 1257{
1091 char **ptrptr, **ptrptr2; 1258 char **ptrptr, **ptrptr2;
1092 log_sql_state *cls = get_module_config(orig->server->module_config, &mysql_log_module); 1259 log_sql_state *cls = get_module_config(orig->server->module_config, &sql_log_module);
1093 const char *access_query; 1260 const char *access_query;
1094 request_rec *r; 1261 request_rec *r;
1095 1262
@@ -1101,36 +1268,43 @@ int log_sql_transaction(request_rec *orig)
1101 char *notes_base = "notes_"; 1268 char *notes_base = "notes_";
1102 char *hout_base = "headout_"; 1269 char *hout_base = "headout_";
1103 char *hin_base = "headin_"; 1270 char *hin_base = "headin_";
1271 char *cookie_base = "cookies_";
1104 char *a_tablename; 1272 char *a_tablename;
1105 char *n_tablename; 1273 char *n_tablename;
1106 char *i_tablename; 1274 char *i_tablename;
1107 char *o_tablename; 1275 char *o_tablename;
1276 char *c_tablename;
1108 int i; 1277 int i;
1109 1278
1110 /* Find memory long enough to hold the table name + \0. */ 1279 /* Find memory long enough to hold the table name + \0. */
1111 a_tablename = ap_pstrcat(orig->pool, access_base, ap_get_server_name(orig), NULL); 1280 a_tablename = ap_pstrcat(orig->pool, access_base, ap_get_server_name(orig), NULL);
1112 n_tablename = ap_pstrcat(orig->pool, notes_base, ap_get_server_name(orig), NULL); 1281 n_tablename = ap_pstrcat(orig->pool, notes_base, ap_get_server_name(orig), NULL);
1113 i_tablename = ap_pstrcat(orig->pool, hin_base, ap_get_server_name(orig), NULL); 1282 i_tablename = ap_pstrcat(orig->pool, hin_base, ap_get_server_name(orig), NULL);
1114 o_tablename = ap_pstrcat(orig->pool, hout_base, ap_get_server_name(orig), NULL); 1283 o_tablename = ap_pstrcat(orig->pool, hout_base, ap_get_server_name(orig), NULL);
1115 1284 c_tablename = ap_pstrcat(orig->pool, cookie_base, ap_get_server_name(orig), NULL);
1116 /* Transform any dots or dashes to underscores */ 1285
1286 /* Transform any dots to underscores */
1117 for (i = 0; i < strlen(a_tablename); i++) { 1287 for (i = 0; i < strlen(a_tablename); i++) {
1118 if ( (a_tablename[i] == '.') || (a_tablename[i] == '-') ) 1288 if (a_tablename[i] == '.')
1119 a_tablename[i] = '_'; 1289 a_tablename[i] = '_';
1120 } 1290 }
1121 for (i = 0; i < strlen(n_tablename); i++) { 1291 for (i = 0; i < strlen(n_tablename); i++) {
1122 if ( (n_tablename[i] == '.') || (n_tablename[i] == '-') ) 1292 if (n_tablename[i] == '.')
1123 n_tablename[i] = '_'; 1293 n_tablename[i] = '_';
1124 } 1294 }
1125 for (i = 0; i < strlen(i_tablename); i++) { 1295 for (i = 0; i < strlen(i_tablename); i++) {
1126 if ( (i_tablename[i] == '.') || (i_tablename[i] == '-') ) 1296 if (i_tablename[i] == '.')
1127 i_tablename[i] = '_'; 1297 i_tablename[i] = '_';
1128 } 1298 }
1129 for (i = 0; i < strlen(o_tablename); i++) { 1299 for (i = 0; i < strlen(o_tablename); i++) {
1130 if ( (o_tablename[i] == '.') || (o_tablename[i] == '-') ) 1300 if (o_tablename[i] == '.')
1131 o_tablename[i] = '_'; 1301 o_tablename[i] = '_';
1132 } 1302 }
1133 1303 for (i = 0; i < strlen(c_tablename); i++) {
1304 if (c_tablename[i] == '.')
1305 c_tablename[i] = '_';
1306 }
1307
1134 /* Tell this virtual server its transfer table name, and 1308 /* Tell this virtual server its transfer table name, and
1135 * turn on create_tables, which is implied by massvirtual. 1309 * turn on create_tables, which is implied by massvirtual.
1136 */ 1310 */
@@ -1138,9 +1312,10 @@ int log_sql_transaction(request_rec *orig)
1138 cls->notes_table_name = n_tablename; 1312 cls->notes_table_name = n_tablename;
1139 cls->hout_table_name = o_tablename; 1313 cls->hout_table_name = o_tablename;
1140 cls->hin_table_name = i_tablename; 1314 cls->hin_table_name = i_tablename;
1315 cls->cookie_table_name = c_tablename;
1141 create_tables = 1; 1316 create_tables = 1;
1142 } 1317 }
1143 1318
1144 /* Do we have enough info to log? */ 1319 /* Do we have enough info to log? */
1145 if ( cls->transfer_table_name == NULL ) { 1320 if ( cls->transfer_table_name == NULL ) {
1146 return DECLINED; 1321 return DECLINED;
@@ -1152,11 +1327,12 @@ int log_sql_transaction(request_rec *orig)
1152 char *note_query = NULL; 1327 char *note_query = NULL;
1153 char *hin_query = NULL; 1328 char *hin_query = NULL;
1154 char *hout_query = NULL; 1329 char *hout_query = NULL;
1330 char *cookie_query = NULL;
1155 const char *unique_id; 1331 const char *unique_id;
1156 const char *formatted_item; 1332 const char *formatted_item;
1157 int i, j, length; 1333 int i, j, length;
1158 int result; 1334 int result;
1159 1335
1160 for (r = orig; r->next; r = r->next) { 1336 for (r = orig; r->next; r = r->next) {
1161 continue; 1337 continue;
1162 } 1338 }
@@ -1188,10 +1364,6 @@ int log_sql_transaction(request_rec *orig)
1188 } 1364 }
1189 } 1365 }
1190 1366
1191 /* If not specified by the user, use the default format */
1192 if (cls->transfer_log_format == NULL) {
1193 cls->transfer_log_format = "AbHhmRSsTUuv";
1194 }
1195 length = strlen(cls->transfer_log_format); 1367 length = strlen(cls->transfer_log_format);
1196 1368
1197 /* Iterate through the format characters and set up the INSERT string according to 1369 /* Iterate through the format characters and set up the INSERT string according to
@@ -1205,20 +1377,20 @@ int log_sql_transaction(request_rec *orig)
1205 /* Yes, this key is one of the configured keys. 1377 /* Yes, this key is one of the configured keys.
1206 * Call the key's function and put the returned value into 'formatted_item' */ 1378 * Call the key's function and put the returned value into 'formatted_item' */
1207 formatted_item = log_sql_item_keys[j].func(log_sql_item_keys[j].want_orig_default ? orig : r, ""); 1379 formatted_item = log_sql_item_keys[j].func(log_sql_item_keys[j].want_orig_default ? orig : r, "");
1208 1380
1209 /* Massage 'formatted_item' for proper SQL eligibility... */ 1381 /* Massage 'formatted_item' for proper SQL eligibility... */
1210 if (!formatted_item) { 1382 if (!formatted_item) {
1211 formatted_item = ""; 1383 formatted_item = "";
1212 } else if (formatted_item[0] == '-' && formatted_item[1] == '\0' && !log_sql_item_keys[j].string_contents) { 1384 } else if (formatted_item[0] == '-' && formatted_item[1] == '\0' && !log_sql_item_keys[j].string_contents) {
1213 /* If apache tried to log a '-' character for a numeric field, convert that to a zero 1385 /* If apache tried to log a '-' character for a numeric field, convert that to a zero
1214 * because the database expects a numeral and will reject the '-' character. */ 1386 * because the database expects a numeral and will reject the '-' character. */
1215 formatted_item = "0"; 1387 formatted_item = "0";
1216 } 1388 }
1217 1389
1218 /* Append the fieldname and value-to-insert to the appropriate strings, quoting stringvals with ' as appropriate */ 1390 /* Append the fieldname and value-to-insert to the appropriate strings, quoting stringvals with ' as appropriate */
1219 fields = pstrcat(r->pool, fields, (i > 0 ? "," : ""), 1391 fields = pstrcat(r->pool, fields, (i > 0 ? "," : ""),
1220 log_sql_item_keys[j].sql_field_name, NULL); 1392 log_sql_item_keys[j].sql_field_name, NULL);
1221 1393
1222 values = pstrcat(r->pool, values, (i > 0 ? "," : ""), 1394 values = pstrcat(r->pool, values, (i > 0 ? "," : ""),
1223 (log_sql_item_keys[j].string_contents ? "'" : ""), 1395 (log_sql_item_keys[j].string_contents ? "'" : ""),
1224 escape_query(formatted_item, r->pool), 1396 escape_query(formatted_item, r->pool),
@@ -1230,129 +1402,181 @@ int log_sql_transaction(request_rec *orig)
1230 } 1402 }
1231 } 1403 }
1232 1404
1233 /* Work through the list of notes defined by LogSQLNotesToLog */ 1405 /* Work through the list of notes defined by LogSQLWhichNotes */
1234 i = 0; 1406 i = 0;
1235 unique_id = extract_unique_id(r, ""); 1407 unique_id = extract_unique_id(r, "");
1236 1408
1237 ptrptr2 = (char **) (cls->notes_list->elts + (cls->notes_list->nelts * cls->notes_list->elt_size)); 1409 ptrptr2 = (char **) (cls->notes_list->elts + (cls->notes_list->nelts * cls->notes_list->elt_size));
1238 for (ptrptr = (char **) cls->notes_list->elts; ptrptr < ptrptr2; ptrptr = (char **) ((char *) ptrptr + cls->notes_list->elt_size)) { 1410 for (ptrptr = (char **) cls->notes_list->elts; ptrptr < ptrptr2; ptrptr = (char **) ((char *) ptrptr + cls->notes_list->elt_size)) {
1239 /* If the specified note (*ptrptr) exists for the current request... */ 1411 /* If the specified note (*ptrptr) exists for the current request... */
1240 if ((theitem = ap_table_get(r->notes, *ptrptr))) { 1412 if ((theitem = ap_table_get(r->notes, *ptrptr))) {
1241 itemsets = ap_pstrcat(r->pool, itemsets, 1413 itemsets = ap_pstrcat(r->pool, itemsets,
1242 (i > 0 ? "," : ""), 1414 (i > 0 ? "," : ""),
1243 "('", 1415 "('",
1244 unique_id, 1416 unique_id,
1245 "','", 1417 "','",
1246 escape_query(*ptrptr, r->pool), 1418 escape_query(*ptrptr, r->pool),
1247 "','", 1419 "','",
1248 escape_query(theitem, r->pool), 1420 escape_query(theitem, r->pool),
1249 "')", 1421 "')",
1250 NULL); 1422 NULL);
1251 i++; 1423 i++;
1252 } 1424 }
1253 } 1425 }
1254 if ( itemsets != "" ) { 1426 if ( itemsets != "" ) {
1255 note_query = ap_pstrcat(r->pool, "insert into ", cls->notes_table_name, " (id, item, val) values ", itemsets, NULL); 1427 note_query = ap_pstrcat(r->pool, "insert into `", cls->notes_table_name, "` (id, item, val) values ", itemsets, NULL);
1256 #ifdef DEBUG 1428 #ifdef DEBUG
1257 ap_log_error(APLOG_MARK,DEBUGLEVEL,orig->server,"mod_log_sql: note string: %s", note_query); 1429 ap_log_error(APLOG_MARK,DEBUGLEVEL,orig->server,"mod_log_sql: note string: %s", note_query);
1258 #endif 1430 #endif
1259 } 1431 }
1260 1432
1261 /* Work through the list of headers-out defined by LogSQLHeadersOutToLog */ 1433 /* Work through the list of headers-out defined by LogSQLWhichHeadersOut*/
1262 i = 0; 1434 i = 0;
1263 itemsets = ""; 1435 itemsets = "";
1264 1436
1265 ptrptr2 = (char **) (cls->hout_list->elts + (cls->hout_list->nelts * cls->hout_list->elt_size)); 1437 ptrptr2 = (char **) (cls->hout_list->elts + (cls->hout_list->nelts * cls->hout_list->elt_size));
1266 for (ptrptr = (char **) cls->hout_list->elts; ptrptr < ptrptr2; ptrptr = (char **) ((char *) ptrptr + cls->hout_list->elt_size)) { 1438 for (ptrptr = (char **) cls->hout_list->elts; ptrptr < ptrptr2; ptrptr = (char **) ((char *) ptrptr + cls->hout_list->elt_size)) {
1267 /* If the specified note (*ptrptr) exists for the current request... */ 1439 /* If the specified header (*ptrptr) exists for the current request... */
1268 if ((theitem = ap_table_get(r->headers_out, *ptrptr))) { 1440 if ((theitem = ap_table_get(r->headers_out, *ptrptr))) {
1269 itemsets = ap_pstrcat(r->pool, itemsets, 1441 itemsets = ap_pstrcat(r->pool, itemsets,
1270 (i > 0 ? "," : ""), 1442 (i > 0 ? "," : ""),
1271 "('", 1443 "('",
1272 unique_id, 1444 unique_id,
1273 "','", 1445 "','",
1274 escape_query(*ptrptr, r->pool), 1446 escape_query(*ptrptr, r->pool),
1275 "','", 1447 "','",
1276 escape_query(theitem, r->pool), 1448 escape_query(theitem, r->pool),
1277 "')", 1449 "')",
1278 NULL); 1450 NULL);
1279 i++; 1451 i++;
1280 } 1452 }
1281 } 1453 }
1282 if ( itemsets != "" ) { 1454 if ( itemsets != "" ) {
1283 hout_query = ap_pstrcat(r->pool, "insert into ", cls->hout_table_name, " (id, item, val) values ", itemsets, NULL); 1455 hout_query = ap_pstrcat(r->pool, "insert into `", cls->hout_table_name, "` (id, item, val) values ", itemsets, NULL);
1284 #ifdef DEBUG 1456 #ifdef DEBUG
1285 ap_log_error(APLOG_MARK,DEBUGLEVEL,orig->server,"mod_log_sql: header_out string: %s", hout_query); 1457 ap_log_error(APLOG_MARK,DEBUGLEVEL,orig->server,"mod_log_sql: header_out string: %s", hout_query);
1286 #endif 1458 #endif
1287 } 1459 }
1288 1460
1289 1461
1290 /* Work through the list of headers-in defined by LogSQLHeadersInToLog */ 1462 /* Work through the list of headers-in defined by LogSQLWhichHeadersIn */
1291 i = 0; 1463 i = 0;
1292 itemsets = ""; 1464 itemsets = "";
1293 1465
1294 ptrptr2 = (char **) (cls->hin_list->elts + (cls->hin_list->nelts * cls->hin_list->elt_size)); 1466 ptrptr2 = (char **) (cls->hin_list->elts + (cls->hin_list->nelts * cls->hin_list->elt_size));
1295 for (ptrptr = (char **) cls->hin_list->elts; ptrptr < ptrptr2; ptrptr = (char **) ((char *) ptrptr + cls->hin_list->elt_size)) { 1467 for (ptrptr = (char **) cls->hin_list->elts; ptrptr < ptrptr2; ptrptr = (char **) ((char *) ptrptr + cls->hin_list->elt_size)) {
1296 /* If the specified note (*ptrptr) exists for the current request... */ 1468 /* If the specified header (*ptrptr) exists for the current request... */
1297 if ((theitem = ap_table_get(r->headers_in, *ptrptr))) { 1469 if ((theitem = ap_table_get(r->headers_in, *ptrptr))) {
1298 itemsets = ap_pstrcat(r->pool, itemsets, 1470 itemsets = ap_pstrcat(r->pool, itemsets,
1299 (i > 0 ? "," : ""), 1471 (i > 0 ? "," : ""),
1300 "('", 1472 "('",
1301 unique_id, 1473 unique_id,
1302 "','", 1474 "','",
1303 escape_query(*ptrptr, r->pool), 1475 escape_query(*ptrptr, r->pool),
1304 "','", 1476 "','",
1305 escape_query(theitem, r->pool), 1477 escape_query(theitem, r->pool),
1306 "')", 1478 "')",
1307 NULL); 1479 NULL);
1308 i++; 1480 i++;
1309 } 1481 }
1310 } 1482 }
1311 if ( itemsets != "" ) { 1483 if ( itemsets != "" ) {
1312 hin_query = ap_pstrcat(r->pool, "insert into ", cls->hin_table_name, " (id, item, val) values ", itemsets, NULL); 1484 hin_query = ap_pstrcat(r->pool, "insert into `", cls->hin_table_name, "` (id, item, val) values ", itemsets, NULL);
1313 #ifdef DEBUG 1485 #ifdef DEBUG
1314 ap_log_error(APLOG_MARK,DEBUGLEVEL,orig->server,"mod_log_sql: header_in string: %s", hin_query); 1486 ap_log_error(APLOG_MARK,DEBUGLEVEL,orig->server,"mod_log_sql: header_in string: %s", hin_query);
1315 #endif 1487 #endif
1316 } 1488 }
1317 1489
1490
1491 /* Work through the list of cookies defined by LogSQLWhichCookies */
1492 i = 0;
1493 itemsets = "";
1494
1495 ptrptr2 = (char **) (cls->cookie_list->elts + (cls->cookie_list->nelts * cls->cookie_list->elt_size));
1496 for (ptrptr = (char **) cls->cookie_list->elts; ptrptr < ptrptr2; ptrptr = (char **) ((char *) ptrptr + cls->cookie_list->elt_size)) {
1497 /* If the specified cookie (*ptrptr) exists for the current request... */
1498 if ( strncmp((theitem = extract_specific_cookie(r, *ptrptr)), "-", 1) ) {
1499 itemsets = ap_pstrcat(r->pool, itemsets,
1500 (i > 0 ? "," : ""),
1501 "('",
1502 unique_id,
1503 "','",
1504 escape_query(*ptrptr, r->pool),
1505 "','",
1506 escape_query(theitem, r->pool),
1507 "')",
1508 NULL);
1509 i++;
1510 }
1511
1512 }
1513 if ( itemsets != "" ) {
1514 cookie_query = ap_pstrcat(r->pool, "insert into `", cls->cookie_table_name, "` (id, item, val) values ", itemsets, NULL);
1515 #ifdef DEBUG
1516 ap_log_error(APLOG_MARK,DEBUGLEVEL,orig->server,"mod_log_sql: cookie string: %s", cookie_query);
1517 #endif
1518 }
1519
1520
1318 /* Set up the actual INSERT statement */ 1521 /* Set up the actual INSERT statement */
1319 access_query = ap_pstrcat(r->pool, "insert into ", cls->transfer_table_name, " (", fields, ") values (", values, ")", NULL); 1522 access_query = ap_pstrcat(r->pool, "insert into `", cls->transfer_table_name, "` (", fields, ") values (", values, ")", NULL);
1320 1523
1321 #ifdef DEBUG 1524 #ifdef DEBUG
1322 ap_log_error(APLOG_MARK,DEBUGLEVEL,r->server,"mod_log_sql: access string: %s", access_query); 1525 ap_log_error(APLOG_MARK,DEBUGLEVEL,r->server,"mod_log_sql: access string: %s", access_query);
1323 #endif 1526 #endif
1324 1527
1528 /* If the person activated force-preserve, go ahead and push all the entries
1529 * into the preserve file, then return.
1530 */
1531 if (force_preserve) {
1532 #ifdef DEBUG
1533 ap_log_error(APLOG_MARK,DEBUGLEVEL,orig->server,"mod_log_sql: preservation forced");
1534 #endif
1535 preserve_entry(orig, access_query);
1536 if ( note_query != NULL )
1537 preserve_entry(orig, note_query);
1538 if ( hin_query != NULL )
1539 preserve_entry(orig, hin_query);
1540 if ( hout_query != NULL )
1541 preserve_entry(orig, hout_query);
1542 if ( cookie_query != NULL )
1543 preserve_entry(orig, cookie_query);
1544 return OK;
1545 }
1546
1325 /* How's our mysql link integrity? */ 1547 /* How's our mysql link integrity? */
1326 if (mysql_log == NULL) { 1548 if (mysql_log == NULL) {
1327 1549
1328 /* Make a try to establish the link */ 1550 /* Make a try to establish the link */
1329 open_logdb_link(); 1551 open_logdb_link(r->server);
1330 1552
1331 if (mysql_log == NULL) { 1553 if (mysql_log == NULL) {
1332 /* Unable to re-establish a DB link, so assume that it's really 1554 /* Unable to re-establish a DB link, so assume that it's really
1333 * gone and send the entry to the preserve file instead. 1555 * gone and send the entry to the preserve file instead.
1334 * This short-circuits safe_mysql_query during a db outage and therefore 1556 * This short-circuits safe_mysql_query during a db outage and therefore
1335 * we don't keep logging the db error over and over. 1557 * we don't keep logging the db error over and over.
1336 */ 1558 */
1337 preserve_entry(orig, access_query); 1559 preserve_entry(orig, access_query);
1338 if ( note_query != NULL ) 1560 if ( note_query != NULL )
1339 preserve_entry(orig, note_query); 1561 preserve_entry(orig, note_query);
1340 if ( hin_query != NULL ) 1562 if ( hin_query != NULL )
1341 preserve_entry(orig, hin_query); 1563 preserve_entry(orig, hin_query);
1342 if ( hout_query != NULL ) 1564 if ( hout_query != NULL )
1343 preserve_entry(orig, hout_query); 1565 preserve_entry(orig, hout_query);
1344 1566 if ( cookie_query != NULL )
1567 preserve_entry(orig, cookie_query);
1568
1345 return OK; 1569 return OK;
1346 } else { 1570 } else {
1347 /* Whew, we got the DB link back */ 1571 /* Whew, we got the DB link back */
1348 ap_log_error(APLOG_MARK,NOTICELEVEL,orig->server,"mod_log_sql: child established database connection"); 1572 ap_log_error(APLOG_MARK,NOTICELEVEL,orig->server,"mod_log_sql: child established database connection");
1349 } 1573 }
1350 } 1574 }
1351 1575
1352 1576
1353 /* ---> So as of here we have a non-null value of mysql_log. <--- */ 1577 /* ---> So as of here we have a non-null value of mysql_log. <--- */
1354 /* ---> i.e. we have a good MySQL connection. <--- */ 1578 /* ---> i.e. we have a good MySQL connection. <--- */
1355 1579
1356 1580
1357 /* Make the tables if we're supposed to. */ 1581 /* Make the tables if we're supposed to. */
1358 if ((cls->table_made != 1) && (create_tables != 0)) { 1582 if ((cls->table_made != 1) && (create_tables != 0)) {
@@ -1362,14 +1586,14 @@ int log_sql_transaction(request_rec *orig)
1362 else 1586 else
1363 ap_log_error(APLOG_MARK,NOTICELEVEL,orig->server,"mod_log_sql: no problems creating tables for %s", ap_get_server_name(orig)); 1587 ap_log_error(APLOG_MARK,NOTICELEVEL,orig->server,"mod_log_sql: no problems creating tables for %s", ap_get_server_name(orig));
1364 } 1588 }
1365 1589
1366 /* Make the access-table insert */ 1590 /* Make the access-table insert */
1367 result = safe_mysql_query(orig, access_query); 1591 result = safe_mysql_query(orig, access_query);
1368 1592
1369 /* It failed, but NOT because table didn't exist */ 1593 /* It failed, but NOT because table didn't exist */
1370 if ( (result != 0) && (result != 1146) ) 1594 if ( (result != 0) && (result != 1146) )
1371 preserve_entry(orig,access_query); 1595 preserve_entry(orig,access_query);
1372 1596
1373 /* It failed because table didn't exist */ 1597 /* It failed because table didn't exist */
1374 if (result == 1146) { 1598 if (result == 1146) {
1375 ap_log_error(APLOG_MARK,ERRLEVEL,orig->server,"mod_log_sql: hmm, table didn't yet exist; creating"); 1599 ap_log_error(APLOG_MARK,ERRLEVEL,orig->server,"mod_log_sql: hmm, table didn't yet exist; creating");
@@ -1387,17 +1611,20 @@ int log_sql_transaction(request_rec *orig)
1387 } 1611 }
1388 } 1612 }
1389 } 1613 }
1390 1614
1391 /* Log the optional notes, headers, etc. */ 1615 /* Log the optional notes, headers, etc. */
1392 if ( note_query != NULL ) 1616 if ( note_query != NULL )
1393 safe_mysql_query(orig, note_query); 1617 safe_mysql_query(orig, note_query);
1394 1618
1395 if ( hout_query != NULL ) 1619 if ( hout_query != NULL )
1396 safe_mysql_query(orig, hout_query); 1620 safe_mysql_query(orig, hout_query);
1397 1621
1398 if ( hin_query != NULL ) 1622 if ( hin_query != NULL )
1399 safe_mysql_query(orig, hin_query); 1623 safe_mysql_query(orig, hin_query);
1400 1624
1625 if ( cookie_query != NULL )
1626 safe_mysql_query(orig, cookie_query);
1627
1401 return OK; 1628 return OK;
1402 } 1629 }
1403} 1630}
@@ -1406,7 +1633,7 @@ int log_sql_transaction(request_rec *orig)
1406 1633
1407 1634
1408/* The configuration array that sets up the hooks into the module. */ 1635/* The configuration array that sets up the hooks into the module. */
1409module mysql_log_module = { 1636module sql_log_module = {
1410 STANDARD_MODULE_STUFF, 1637 STANDARD_MODULE_STUFF,
1411 NULL, /* module initializer */ 1638 NULL, /* module initializer */
1412 NULL, /* create per-dir config */ 1639 NULL, /* create per-dir config */
@@ -1428,5 +1655,5 @@ module mysql_log_module = {
1428 log_sql_child_exit, /* process exit/cleanup */ 1655 log_sql_child_exit, /* process exit/cleanup */
1429 NULL /* [1] post read-request */ 1656 NULL /* [1] post read-request */
1430#endif 1657#endif
1431 1658
1432}; 1659};