diff options
| author | 2001-12-07 03:52:56 +0000 | |
|---|---|---|
| committer | 2001-12-07 03:52:56 +0000 | |
| commit | 3ddc5c9b88226097f93d4c21ea51f7a37f0e56f3 (patch) | |
| tree | b141b4bfc8532e3640ca6dd7204538f74079742e | |
| parent | 84fbbe1411ec93b3aa97ad535f0f9ce737f62a52 (diff) | |
Added a mysql_close mechanism to the child exit process to fix MySQL
complaining about bad communication packets.  Considerable code reorg
and cleanup.
| -rw-r--r-- | CHANGELOG | 10 | ||||
| -rw-r--r-- | Makefile | 21 | ||||
| -rw-r--r-- | README | 27 | ||||
| -rw-r--r-- | access_log.sql | 10 | ||||
| -rw-r--r-- | mod_log_sql.c | 468 | 
5 files changed, 232 insertions, 304 deletions
| @@ -1,4 +1,4 @@ | |||
| 1 | $Id: CHANGELOG,v 1.3 2001/12/03 19:54:02 helios Exp $ | 1 | $Id: CHANGELOG,v 1.4 2001/12/07 03:52:56 helios Exp $ | 
| 2 | 2 | ||
| 3 | 3 | ||
| 4 | TODO: | 4 | TODO: | 
| @@ -8,6 +8,14 @@ TODO: | |||
| 8 | 8 | ||
| 9 | CHANGES: | 9 | CHANGES: | 
| 10 | 10 | ||
| 11 | 1.12: | ||
| 12 | |||
| 13 | * Added a mysql_close() call to get rid of those annoying MySQL | ||
| 14 | complaints every time an httpd child process terminates. (Apache | ||
| 15 | 1.3 or later.) | ||
| 16 | * Considerable code reorganization and cleanup. | ||
| 17 | |||
| 18 | |||
| 11 | 1.11: | 19 | 1.11: | 
| 12 | 20 | ||
| 13 | * Completely re-worked the cookie code. Now the user can instruct | 21 | * Completely re-worked the cookie code. Now the user can instruct | 
| @@ -1,4 +1,4 @@ | |||
| 1 | # $Id: Makefile,v 1.3 2001/12/03 19:56:58 helios Exp $ | 1 | # $Id: Makefile,v 1.4 2001/12/07 03:52:56 helios Exp $ | 
| 2 | 2 | ||
| 3 | # Verify that this points to the right place... | 3 | # Verify that this points to the right place... | 
| 4 | APACHEDIR = /usr/local/src/apache_1.3.22 | 4 | APACHEDIR = /usr/local/src/apache_1.3.22 | 
| @@ -9,9 +9,10 @@ APACHEDIR = /usr/local/src/apache_1.3.22 | |||
| 9 | DEFS = -DWANT_SSL_LOGGING | 9 | DEFS = -DWANT_SSL_LOGGING | 
| 10 | #DEFS = | 10 | #DEFS = | 
| 11 | 11 | ||
| 12 | # Use this one if you do WANT_SSL_LOGGING, and confirm the last two paths. | 12 | # Use this one if you do WANT_SSL_LOGGING, and confirm the last three paths. | 
| 13 | # Make "/usr/local/ssl/include" point to where your openssl/*.h files are, | 13 | # Point "/usr/local/ssl/include" to where your openssl/*.h files are, | 
| 14 | # and make "/usr/include/db1" point to where ndbm.h can be found. | 14 | # Point "/usr/include/db1" to where ndbm.h can be found, | 
| 15 | # Point "/usr/local/src/apache_1.3.22/src/modules/ssl" to where mod_ssl.h can be found. | ||
| 15 | # | 16 | # | 
| 16 | # How to find your directories: | 17 | # How to find your directories: | 
| 17 | # | 18 | # | 
| @@ -23,11 +24,13 @@ DEFS = -DWANT_SSL_LOGGING | |||
| 23 | # | 24 | # | 
| 24 | # $ locate ndbm.h | 25 | # $ locate ndbm.h | 
| 25 | # /usr/include/db1/ndbm.h | 26 | # /usr/include/db1/ndbm.h | 
| 27 | # | ||
| 28 | # $ locate mod_ssl.h | ||
| 29 | # /usr/local/src/apache_1.3.22/src/modules/ssl/mod_ssl.h | ||
| 26 | 30 | ||
| 27 | CFLAGS = -fpic -O2 -Wall -I/usr/local/Apache/include -I/usr/local/ssl/include -I/usr/include/db1 | 31 | CFLAGS = -fpic -O2 -Wall -I/usr/local/Apache/include -I/usr/local/ssl/include -I/usr/include/db1 -I/usr/local/src/apache_1.3.22/src/modules/ssl | 
| 28 | 32 | ||
| 29 | # Use this one if you don't WANT_SSL_LOGGING: | 33 | # Use this one if you don't WANT_SSL_LOGGING: | 
| 30 | |||
| 31 | #CFLAGS = -fpic -O2 -Wall -I/usr/local/Apache/include | 34 | #CFLAGS = -fpic -O2 -Wall -I/usr/local/Apache/include | 
| 32 | 35 | ||
| 33 | 36 | ||
| @@ -40,8 +43,8 @@ INSTALL = /usr/bin/install -m 664 | |||
| 40 | all: mod_log_mysql.o | 43 | all: mod_log_mysql.o | 
| 41 | 44 | ||
| 42 | mod_log_mysql.o: mod_log_mysql.c Makefile | 45 | mod_log_mysql.o: mod_log_mysql.c Makefile | 
| 43 | $(CC) ${CFLAGS} ${DEFS} -c mod_log_mysql.c | 46 | $(CC) ${CFLAGS} ${DEFS} -c mod_log_mysql.c | 
| 44 | 47 | ||
| 45 | install: all | 48 | install: all | 
| 46 | $(INSTALL) mod_log_mysql.o ${APACHEDIR}/src/mod_log_mysql.o | 49 | $(INSTALL) mod_log_mysql.o ${APACHEDIR}/src/mod_log_mysql.o | 
| 47 | 50 | ||
| @@ -49,7 +52,7 @@ distro: all | |||
| 49 | cp -f INSTALL /usr/local/Apache/html/mod_log_mysql/ | 52 | cp -f INSTALL /usr/local/Apache/html/mod_log_mysql/ | 
| 50 | cp -f README /usr/local/Apache/html/mod_log_mysql/ | 53 | cp -f README /usr/local/Apache/html/mod_log_mysql/ | 
| 51 | cp -f CHANGELOG /usr/local/Apache/html/mod_log_mysql/ | 54 | cp -f CHANGELOG /usr/local/Apache/html/mod_log_mysql/ | 
| 52 | cd ..; tar zcf mod_log_mysql.tar.gz mod_log_mysql/; $(INSTALL) mod_log_mysql.tar.gz /usr/local/Apache/html/mod_log_mysql/; rm -f mod_log_mysql.tar.gz | 55 | cd ..; tar zcf mod_log_mysql.tar.gz --exclude mod_log_mysql/CVS mod_log_mysql/; $(INSTALL) mod_log_mysql.tar.gz /usr/local/Apache/html/mod_log_mysql/; rm -f mod_log_mysql.tar.gz | 
| 53 | 56 | ||
| 54 | clean: | 57 | clean: | 
| 55 | rm -f *.o *~ | 58 | rm -f *.o *~ | 
| @@ -1,4 +1,4 @@ | |||
| 1 | $Id: README,v 1.2 2001/12/03 19:54:02 helios Exp $ | 1 | $Id: README,v 1.3 2001/12/07 03:52:56 helios Exp $ | 
| 2 | 2 | ||
| 3 | 3 | ||
| 4 | Homepage | 4 | Homepage | 
| @@ -105,10 +105,6 @@ request_uri: corresponds to the Apache %U directive. Contains the | |||
| 105 | needed for log analysis, and saves the database a LOT of wasted growth | 105 | needed for log analysis, and saves the database a LOT of wasted growth | 
| 106 | on unneeded bytes. | 106 | on unneeded bytes. | 
| 107 | 107 | ||
| 108 | request_duration: corresponds to the Apache %T directive. Contains the | ||
| 109 | time in seconds that it took to serve the request. | ||
| 110 | Example: 2 | ||
| 111 | |||
| 112 | virtual_host: contains the VirtualHost that is making the log entry. This | 108 | virtual_host: contains the VirtualHost that is making the log entry. This | 
| 113 | allows you to log multiple VirtualHosts to a single MySQL database and | 109 | allows you to log multiple VirtualHosts to a single MySQL database and | 
| 114 | yet still be able to extract them for separate analysis. | 110 | yet still be able to extract them for separate analysis. | 
| @@ -149,7 +145,7 @@ Notes | |||
| 149 | * The 'time_stamp' field is stored in an UNSIGNED INTEGER column, in the | 145 | * The 'time_stamp' field is stored in an UNSIGNED INTEGER column, in the | 
| 150 | standard unix "seconds since 1/1/1970 12:00:00" format. This is | 146 | standard unix "seconds since 1/1/1970 12:00:00" format. This is | 
| 151 | superior to storing the access time as a string due to size | 147 | superior to storing the access time as a string due to size | 
| 152 | requirements: an UNSIGNED INT type fits in 4 bytes. The Apache date | 148 | requirements: an UNSIGNED INT type fits in 4 bytes, whereas the Apache date | 
| 153 | string (e.g. "18/Nov/2001:13:59:52 -0800") requires 26 bytes -- | 149 | string (e.g. "18/Nov/2001:13:59:52 -0800") requires 26 bytes -- | 
| 154 | significantly larger, and those extra 22 bytes will add up over the | 150 | significantly larger, and those extra 22 bytes will add up over the | 
| 155 | thousands of accesses that a busy server will experience. Besides, | 151 | thousands of accesses that a busy server will experience. Besides, | 
| @@ -187,19 +183,6 @@ Notes | |||
| 187 | makes perfect sense anyway. | 183 | makes perfect sense anyway. | 
| 188 | 184 | ||
| 189 | 185 | ||
| 190 | Disclaimer | ||
| 191 | ---------- | ||
| 192 | |||
| 193 | It works for me (I've tested it on my '2 hits/busy day' home Linux box, | ||
| 194 | and afterwards on our pretty busy tucows mirror (>100K hits a day) and | ||
| 195 | it appears to be working fine. | ||
| 196 | |||
| 197 | If it doesn't, and causes you damage of any sort, including but not | ||
| 198 | limited to losing logs, losing money or your girlfriend leaving you | ||
| 199 | (read 'boyfriend' where applicable), I'm not liable to anything. Bug | ||
| 200 | reports and constructive flame mail are ok, though (both about the code | ||
| 201 | and this quickly-written README file). | ||
| 202 | |||
| 203 | 186 | ||
| 204 | Author / Maintainer | 187 | Author / Maintainer | 
| 205 | ------------------- | 188 | ------------------- | 
| @@ -207,11 +190,11 @@ Author / Maintainer | |||
| 207 | The actual logging code was taken from the already existing flat file | 190 | The actual logging code was taken from the already existing flat file | 
| 208 | text modules, so all that credit goes to the Apache Server group. | 191 | text modules, so all that credit goes to the Apache Server group. | 
| 209 | 192 | ||
| 210 | The MySQL routines and directives was added in by Zeev Suraski | 193 | The MySQL routines and directives were added by Zeev Suraski | 
| 211 | <bourbon@netvision.net.il> | 194 | <bourbon@netvision.net.il>. | 
| 212 | 195 | ||
| 213 | Changes from 1.06 on and the new documentation were added by | 196 | Changes from 1.06 on and the new documentation were added by | 
| 214 | Chris Powell <chris@grubbybaby.com>. It seems that the module had fallen | 197 | Chris Powell <chris@grubbybaby.com>. It seems that the module had fallen | 
| 215 | into the "unmaintained" category -- it hadn't been updated since 1998 -- | 198 | into the "unmaintained" category -- it hadn't been updated since 1998 -- | 
| 216 | so I've adopted it as the new maintainer. | 199 | so Chris adopted it as the new maintainer. | 
| 217 | 200 | ||
| diff --git a/access_log.sql b/access_log.sql index 46d5a6e..a667494 100644 --- a/access_log.sql +++ b/access_log.sql | |||
| @@ -10,16 +10,16 @@ create table access_log ( | |||
| 10 | remote_user varchar(50) not null, | 10 | remote_user varchar(50) not null, | 
| 11 | request_duration smallint not null, | 11 | request_duration smallint not null, | 
| 12 | request_line varchar(255), | 12 | request_line varchar(255), | 
| 13 | request_method not null, | 13 | request_method varchar(6) not null, | 
| 14 | request_protocol not null, | 14 | request_protocol varchar(10) not null, | 
| 15 | request_time char(28), | 15 | request_time char(28), | 
| 16 | request_uri varchar(50) not null, | 16 | request_uri varchar(50) not null, | 
| 17 | server_port smallint unsigned, | 17 | server_port smallint unsigned, | 
| 18 | ssl_cipher varchar(25), | 18 | ssl_cipher varchar(25), | 
| 19 | ssl_keysize smallint | 19 | ssl_keysize smallint unsigned, | 
| 20 | ssl_maxkeysize smallint, | 20 | ssl_maxkeysize smallint unsigned, | 
| 21 | status smallint not null, | 21 | status smallint not null, | 
| 22 | time_stamp int unsigned not null, | 22 | time_stamp int unsigned not null, | 
| 23 | virtual_host varchar(50) not null, | 23 | virtual_host varchar(50) not null | 
| 24 | ) | 24 | ) | 
| 25 | 25 | ||
| diff --git a/mod_log_sql.c b/mod_log_sql.c index 5bb992b..efbf45c 100644 --- a/mod_log_sql.c +++ b/mod_log_sql.c | |||
| @@ -1,85 +1,11 @@ | |||
| 1 | /* $Id: mod_log_sql.c,v 1.3 2001/12/03 19:54:02 helios Exp $ | 1 | /* $Id: mod_log_sql.c,v 1.4 2001/12/07 03:52:56 helios Exp $ */ | 
| 2 | * | ||
| 3 | * mod_log_mysql.c | ||
| 4 | * Release v 1.10 | ||
| 5 | * | ||
| 6 | * Hi, I'm the new maintainer of this code. If you have any questions, | ||
| 7 | * comments or suggestions (which are always welcome), please contact Chris | ||
| 8 | * Powell <chris@grubbybaby.com>. This code still falls under the rules of | ||
| 9 | * the Apache license, and all credit for the code up to my changes is still | ||
| 10 | * preserved below. | ||
| 11 | * | ||
| 12 | * ==================================================================== | ||
| 13 | * | ||
| 14 | * The original preface from version 1.05: This module was patched, wrapped | ||
| 15 | * and coded by Zeev Suraski <bourbon@netvision.net.il> | ||
| 16 | * | ||
| 17 | * It may be used freely, with the same restrictions as its predecessors | ||
| 18 | * (specified below). This module is based on code from standard apache | ||
| 19 | * modules. Their copyright notice follows. | ||
| 20 | * | ||
| 21 | * ==================================================================== | ||
| 22 | * Copyright (c) 1995-1997 The Apache Group. All rights reserved. | ||
| 23 | * | ||
| 24 | * Redistribution and use in source and binary forms, with or without | ||
| 25 | * modification, are permitted provided that the following conditions | ||
| 26 | * are met: | ||
| 27 | * | ||
| 28 | * 1. Redistributions of source code must retain the above copyright | ||
| 29 | * notice, this list of conditions and the following disclaimer. | ||
| 30 | * | ||
| 31 | * 2. Redistributions in binary form must reproduce the above copyright | ||
| 32 | * notice, this list of conditions and the following disclaimer in | ||
| 33 | * the documentation and/or other materials provided with the | ||
| 34 | * distribution. | ||
| 35 | * | ||
| 36 | * 3. All advertising materials mentioning features or use of this | ||
| 37 | * software must display the following acknowledgment: | ||
| 38 | * "This product includes software developed by the Apache Group | ||
| 39 | * for use in the Apache HTTP server project (http://www.apache.org/)." | ||
| 40 | * | ||
| 41 | * 4. The names "Apache Server" and "Apache Group" must not be used to | ||
| 42 | * endorse or promote products derived from this software without | ||
| 43 | * prior written permission. | ||
| 44 | * | ||
| 45 | * 5. Redistributions of any form whatsoever must retain the following | ||
| 46 | * acknowledgment: | ||
| 47 | * "This product includes software developed by the Apache Group | ||
| 48 | * for use in the Apache HTTP server project (http://www.apache.org/)." | ||
| 49 | * | ||
| 50 | * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY | ||
| 51 | * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
| 52 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | ||
| 53 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR | ||
| 54 | * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
| 55 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
| 56 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
| 57 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
| 58 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
| 59 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
| 60 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | ||
| 61 | * OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| 62 | * ==================================================================== | ||
| 63 | * | ||
| 64 | * This software consists of voluntary contributions made by many | ||
| 65 | * individuals on behalf of the Apache Group and was originally based | ||
| 66 | * on public domain software written at the National Center for | ||
| 67 | * Supercomputing Applications, University of Illinois, Urbana-Champaign. | ||
| 68 | * For more information on the Apache Group and the Apache HTTP server | ||
| 69 | * project, please see <http://www.apache.org/>. | ||
| 70 | * | ||
| 71 | */ | ||
| 72 | 2 | ||
| 73 | 3 | ||
| 74 | /* DEFINES */ | 4 | /* DEFINES */ | 
| 75 | #define MYSQL_ERROR(mysql) ((mysql)?(mysql_error(mysql)):"MySQL server has gone away") | 5 | #define MYSQL_ERROR(mysql) ((mysql)?(mysql_error(mysql)):"MySQL server has gone away") | 
| 76 | |||
| 77 | #define ERRLEVEL APLOG_ERR|APLOG_NOERRNO | 6 | #define ERRLEVEL APLOG_ERR|APLOG_NOERRNO | 
| 78 | 7 | #define DEBUGLEVEL APLOG_INFO|APLOG_NOERRNO | |
| 79 | #undef DEBUG | 8 | /* (DEBUG and WANT_SSL_LOGGING are defined in the Makefile DEFS line.) */ | 
| 80 | #ifdef DEBUG | ||
| 81 | #define DEBUGLEVEL APLOG_INFO|APLOG_NOERRNO | ||
| 82 | #endif | ||
| 83 | 9 | ||
| 84 | 10 | ||
| 85 | 11 | ||
| @@ -92,24 +18,35 @@ | |||
| 92 | #include "http_config.h" | 18 | #include "http_config.h" | 
| 93 | #include "http_log.h" | 19 | #include "http_log.h" | 
| 94 | #include "http_core.h" | 20 | #include "http_core.h" | 
| 95 | #if MODULE_MAGIC_NUMBER >= 19980324 | 21 | |
| 22 | /* M_M_N is defined in /usr/local/Apache/include/ap_mmn.h, 19990320 as of this writing. */ | ||
| 23 | #if MODULE_MAGIC_NUMBER >= 19980324 /* 1.3b6 or later */ | ||
| 96 | #include "ap_compat.h" | 24 | #include "ap_compat.h" | 
| 97 | #endif | 25 | #endif | 
| 98 | 26 | ||
| 99 | #ifdef WANT_SSL_LOGGING | 27 | #ifdef WANT_SSL_LOGGING /* Defined in Makefile */ | 
| 100 | #include "/usr/local/src/apache_1.3.22/src/modules/ssl/mod_ssl.h" | 28 | #include "mod_ssl.h" | 
| 101 | #endif | 29 | #endif | 
| 102 | 30 | ||
| 103 | 31 | ||
| 104 | 32 | ||
| 105 | /* DECLARATIONS */ | 33 | /* DECLARATIONS */ | 
| 106 | module mysql_log_module; | 34 | module mysql_log_module; | 
| 107 | MYSQL log_sql_server, *mysql_log = NULL; | 35 | |
| 108 | char *log_db_name = NULL, *db_host = NULL, *db_user = NULL, *db_pwd = NULL, *cookie_name = NULL; | 36 | MYSQL sql_server, *mysql_log = NULL; | 
| 37 | |||
| 38 | char *db_name = NULL; | ||
| 39 | char *db_host = NULL; | ||
| 40 | char *db_user = NULL; | ||
| 41 | char *db_pwd = NULL; | ||
| 42 | char *cookie_name = NULL; | ||
| 109 | 43 | ||
| 110 | typedef const char *(*item_key_func) (request_rec *, char *); | 44 | typedef const char *(*item_key_func) (request_rec *, char *); | 
| 45 | |||
| 111 | typedef struct { | 46 | typedef struct { | 
| 112 | char *referer_table_name, *agent_table_name, *transfer_table_name; | 47 | char *referer_table_name; | 
| 48 | char *agent_table_name; | ||
| 49 | char *transfer_table_name; | ||
| 113 | array_header *referer_ignore_list; | 50 | array_header *referer_ignore_list; | 
| 114 | array_header *transfer_ignore_list; | 51 | array_header *transfer_ignore_list; | 
| 115 | array_header *remhost_ignore_list; | 52 | array_header *remhost_ignore_list; | 
| @@ -118,29 +55,7 @@ typedef struct { | |||
| 118 | 55 | ||
| 119 | 56 | ||
| 120 | 57 | ||
| 121 | #if MODULE_MAGIC_NUMBER < 19970103 /* Defined in /usr/local/Apache/include/ap_mmn.h, 19990320 as of this writing. */ | 58 | /* FUNCTIONS */ | 
| 122 | extern const char *log_request_protocol(request_rec *r, char *a); | ||
| 123 | extern const char *log_request_method(request_rec *r, char *a); | ||
| 124 | extern const char *log_remote_host(request_rec *r, char *a); | ||
| 125 | extern const char *log_remote_logname(request_rec *r, char *a); | ||
| 126 | extern const char *log_remote_user(request_rec *r, char *a); | ||
| 127 | extern const char *log_request_time(request_rec *r, char *a); | ||
| 128 | extern const char *log_request_timestamp(request_rec *r, char *a); | ||
| 129 | extern const char *log_request_duration(request_rec *r, char *a); | ||
| 130 | extern const char *log_request_line(request_rec *r, char *a); | ||
| 131 | extern const char *log_request_file(request_rec *r, char *a); | ||
| 132 | extern const char *log_request_uri(request_rec *r, char *a); | ||
| 133 | extern const char *log_status(request_rec *r, char *a); | ||
| 134 | extern const char *log_bytes_sent(request_rec *r, char *a); | ||
| 135 | extern const char *log_header_in(request_rec *r, char *a); | ||
| 136 | extern const char *log_header_out(request_rec *r, char *a); | ||
| 137 | extern const char *log_note(request_rec *r, char *a); | ||
| 138 | extern const char *log_env_var(request_rec *r, char *a); | ||
| 139 | extern const char *log_virtual_host(request_rec *r, char *a); | ||
| 140 | extern const char *log_server_port(request_rec *r, char *a); | ||
| 141 | extern const char *log_child_pid(request_rec *r, char *a); | ||
| 142 | #else | ||
| 143 | |||
| 144 | static char *format_integer(pool *p, int i) | 59 | static char *format_integer(pool *p, int i) | 
| 145 | { | 60 | { | 
| 146 | char dummy[40]; | 61 | char dummy[40]; | 
| @@ -162,17 +77,17 @@ static char *pfmt(pool *p, int i) | |||
| 162 | * value to the calling entity. | 77 | * value to the calling entity. | 
| 163 | */ | 78 | */ | 
| 164 | 79 | ||
| 165 | static const char *log_remote_host(request_rec *r, char *a) | 80 | static const char *extract_remote_host(request_rec *r, char *a) | 
| 166 | { | 81 | { | 
| 167 | return (char *) get_remote_host(r->connection, r->per_dir_config, REMOTE_NAME); | 82 | return (char *) get_remote_host(r->connection, r->per_dir_config, REMOTE_NAME); | 
| 168 | } | 83 | } | 
| 169 | 84 | ||
| 170 | static const char *log_remote_logname(request_rec *r, char *a) | 85 | static const char *extract_remote_logname(request_rec *r, char *a) | 
| 171 | { | 86 | { | 
| 172 | return (char *) get_remote_logname(r); | 87 | return (char *) get_remote_logname(r); | 
| 173 | } | 88 | } | 
| 174 | 89 | ||
| 175 | static const char *log_remote_user(request_rec *r, char *a) | 90 | static const char *extract_remote_user(request_rec *r, char *a) | 
| 176 | { | 91 | { | 
| 177 | char *rvalue = r->connection->user; | 92 | char *rvalue = r->connection->user; | 
| 178 | 93 | ||
| @@ -185,7 +100,7 @@ static const char *log_remote_user(request_rec *r, char *a) | |||
| 185 | } | 100 | } | 
| 186 | 101 | ||
| 187 | #ifdef WANT_SSL_LOGGING | 102 | #ifdef WANT_SSL_LOGGING | 
| 188 | static const char *log_ssl_keysize(request_rec *r, char *a) | 103 | static const char *extract_ssl_keysize(request_rec *r, char *a) | 
| 189 | { | 104 | { | 
| 190 | char *result = NULL; | 105 | char *result = NULL; | 
| 191 | 106 | ||
| @@ -202,7 +117,7 @@ static const char *log_ssl_keysize(request_rec *r, char *a) | |||
| 202 | } | 117 | } | 
| 203 | } | 118 | } | 
| 204 | 119 | ||
| 205 | static const char *log_ssl_maxkeysize(request_rec *r, char *a) | 120 | static const char *extract_ssl_maxkeysize(request_rec *r, char *a) | 
| 206 | { | 121 | { | 
| 207 | char *result = NULL; | 122 | char *result = NULL; | 
| 208 | 123 | ||
| @@ -219,7 +134,7 @@ static const char *log_ssl_maxkeysize(request_rec *r, char *a) | |||
| 219 | } | 134 | } | 
| 220 | } | 135 | } | 
| 221 | 136 | ||
| 222 | static const char *log_ssl_cipher(request_rec *r, char *a) | 137 | static const char *extract_ssl_cipher(request_rec *r, char *a) | 
| 223 | { | 138 | { | 
| 224 | char *result = NULL; | 139 | char *result = NULL; | 
| 225 | 140 | ||
| @@ -232,42 +147,42 @@ static const char *log_ssl_cipher(request_rec *r, char *a) | |||
| 232 | result = NULL; | 147 | result = NULL; | 
| 233 | return result; | 148 | return result; | 
| 234 | } else { | 149 | } else { | 
| 235 | return "0"; | 150 | return "-"; | 
| 236 | } | 151 | } | 
| 237 | } | 152 | } | 
| 238 | #endif /* WANT_SSL_LOGGING */ | 153 | #endif /* WANT_SSL_LOGGING */ | 
| 239 | 154 | ||
| 240 | static const char *log_request_method(request_rec *r, char *a) | 155 | static const char *extract_request_method(request_rec *r, char *a) | 
| 241 | { | 156 | { | 
| 242 | return r->method; | 157 | return r->method; | 
| 243 | } | 158 | } | 
| 244 | 159 | ||
| 245 | static const char *log_request_protocol(request_rec *r, char *a) | 160 | static const char *extract_request_protocol(request_rec *r, char *a) | 
| 246 | { | 161 | { | 
| 247 | return r->protocol; | 162 | return r->protocol; | 
| 248 | } | 163 | } | 
| 249 | 164 | ||
| 250 | static const char *log_request_line(request_rec *r, char *a) | 165 | static const char *extract_request_line(request_rec *r, char *a) | 
| 251 | { | 166 | { | 
| 252 | return r->the_request; | 167 | return r->the_request; | 
| 253 | } | 168 | } | 
| 254 | 169 | ||
| 255 | static const char *log_request_file(request_rec *r, char *a) | 170 | static const char *extract_request_file(request_rec *r, char *a) | 
| 256 | { | 171 | { | 
| 257 | return r->filename; | 172 | return r->filename; | 
| 258 | } | 173 | } | 
| 259 | 174 | ||
| 260 | static const char *log_request_uri(request_rec *r, char *a) | 175 | static const char *extract_request_uri(request_rec *r, char *a) | 
| 261 | { | 176 | { | 
| 262 | return r->uri; | 177 | return r->uri; | 
| 263 | } | 178 | } | 
| 264 | 179 | ||
| 265 | static const char *log_status(request_rec *r, char *a) | 180 | static const char *extract_status(request_rec *r, char *a) | 
| 266 | { | 181 | { | 
| 267 | return pfmt(r->pool, r->status); | 182 | return pfmt(r->pool, r->status); | 
| 268 | } | 183 | } | 
| 269 | 184 | ||
| 270 | static const char *log_bytes_sent(request_rec *r, char *a) | 185 | static const char *extract_bytes_sent(request_rec *r, char *a) | 
| 271 | { | 186 | { | 
| 272 | if (!r->sent_bodyct) { | 187 | if (!r->sent_bodyct) { | 
| 273 | return "-"; | 188 | return "-"; | 
| @@ -280,12 +195,12 @@ static const char *log_bytes_sent(request_rec *r, char *a) | |||
| 280 | } | 195 | } | 
| 281 | } | 196 | } | 
| 282 | 197 | ||
| 283 | static const char *log_header_in(request_rec *r, char *a) | 198 | static const char *extract_header_in(request_rec *r, char *a) | 
| 284 | { | 199 | { | 
| 285 | return table_get(r->headers_in, a); | 200 | return table_get(r->headers_in, a); | 
| 286 | } | 201 | } | 
| 287 | 202 | ||
| 288 | static const char *log_header_out(request_rec *r, char *a) | 203 | static const char *extract_header_out(request_rec *r, char *a) | 
| 289 | { | 204 | { | 
| 290 | const char *cp = table_get(r->headers_out, a); | 205 | const char *cp = table_get(r->headers_out, a); | 
| 291 | if (!strcasecmp(a, "Content-type") && r->content_type) { | 206 | if (!strcasecmp(a, "Content-type") && r->content_type) { | 
| @@ -297,7 +212,7 @@ static const char *log_header_out(request_rec *r, char *a) | |||
| 297 | return table_get(r->err_headers_out, a); | 212 | return table_get(r->err_headers_out, a); | 
| 298 | } | 213 | } | 
| 299 | 214 | ||
| 300 | static const char *log_request_time(request_rec *r, char *a) | 215 | static const char *extract_request_time(request_rec *r, char *a) | 
| 301 | { | 216 | { | 
| 302 | int timz; | 217 | int timz; | 
| 303 | struct tm *t; | 218 | struct tm *t; | 
| @@ -320,7 +235,7 @@ static const char *log_request_time(request_rec *r, char *a) | |||
| 320 | return pstrdup(r->pool, tstr); | 235 | return pstrdup(r->pool, tstr); | 
| 321 | } | 236 | } | 
| 322 | 237 | ||
| 323 | static const char *log_request_duration(request_rec *r, char *a) | 238 | static const char *extract_request_duration(request_rec *r, char *a) | 
| 324 | { | 239 | { | 
| 325 | char duration[22]; /* Long enough for 2^64 */ | 240 | char duration[22]; /* Long enough for 2^64 */ | 
| 326 | 241 | ||
| @@ -328,12 +243,12 @@ static const char *log_request_duration(request_rec *r, char *a) | |||
| 328 | return pstrdup(r->pool, duration); | 243 | return pstrdup(r->pool, duration); | 
| 329 | } | 244 | } | 
| 330 | 245 | ||
| 331 | static const char *log_virtual_host(request_rec *r, char *a) | 246 | static const char *extract_virtual_host(request_rec *r, char *a) | 
| 332 | { | 247 | { | 
| 333 | return pstrdup(r->pool, r->server->server_hostname); | 248 | return pstrdup(r->pool, r->server->server_hostname); | 
| 334 | } | 249 | } | 
| 335 | 250 | ||
| 336 | static const char *log_server_port(request_rec *r, char *a) | 251 | static const char *extract_server_port(request_rec *r, char *a) | 
| 337 | { | 252 | { | 
| 338 | char portnum[22]; | 253 | char portnum[22]; | 
| 339 | 254 | ||
| @@ -341,14 +256,14 @@ static const char *log_server_port(request_rec *r, char *a) | |||
| 341 | return pstrdup(r->pool, portnum); | 256 | return pstrdup(r->pool, portnum); | 
| 342 | } | 257 | } | 
| 343 | 258 | ||
| 344 | static const char *log_child_pid(request_rec *r, char *a) | 259 | static const char *extract_child_pid(request_rec *r, char *a) | 
| 345 | { | 260 | { | 
| 346 | char pidnum[22]; | 261 | char pidnum[22]; | 
| 347 | ap_snprintf(pidnum, sizeof(pidnum), "%ld", (long) getpid()); | 262 | ap_snprintf(pidnum, sizeof(pidnum), "%ld", (long) getpid()); | 
| 348 | return pstrdup(r->pool, pidnum); | 263 | return pstrdup(r->pool, pidnum); | 
| 349 | } | 264 | } | 
| 350 | 265 | ||
| 351 | static const char *log_referer(request_rec *r, char *a) | 266 | static const char *extract_referer(request_rec *r, char *a) | 
| 352 | { | 267 | { | 
| 353 | const char *tempref; | 268 | const char *tempref; | 
| 354 | 269 | ||
| @@ -361,7 +276,7 @@ static const char *log_referer(request_rec *r, char *a) | |||
| 361 | } | 276 | } | 
| 362 | } | 277 | } | 
| 363 | 278 | ||
| 364 | static const char *log_agent(request_rec *r, char *a) | 279 | static const char *extract_agent(request_rec *r, char *a) | 
| 365 | { | 280 | { | 
| 366 | const char *tempag; | 281 | const char *tempag; | 
| 367 | 282 | ||
| @@ -374,7 +289,7 @@ static const char *log_agent(request_rec *r, char *a) | |||
| 374 | } | 289 | } | 
| 375 | } | 290 | } | 
| 376 | 291 | ||
| 377 | static const char *log_cookie(request_rec *r, char *a) | 292 | static const char *extract_cookie(request_rec *r, char *a) | 
| 378 | { | 293 | { | 
| 379 | const char *cookiestr; | 294 | const char *cookiestr; | 
| 380 | char *cookieend; | 295 | char *cookieend; | 
| @@ -396,7 +311,6 @@ static const char *log_cookie(request_rec *r, char *a) | |||
| 396 | return cookiebuf; | 311 | return cookiebuf; | 
| 397 | } | 312 | } | 
| 398 | } | 313 | } | 
| 399 | |||
| 400 | 314 | ||
| 401 | cookiestr = (char *)table_get(r->headers_in, "cookie"); | 315 | cookiestr = (char *)table_get(r->headers_in, "cookie"); | 
| 402 | if (cookiestr != NULL) { | 316 | if (cookiestr != NULL) { | 
| @@ -414,7 +328,6 @@ static const char *log_cookie(request_rec *r, char *a) | |||
| 414 | } | 328 | } | 
| 415 | } | 329 | } | 
| 416 | 330 | ||
| 417 | |||
| 418 | cookiestr = table_get(r->headers_out, "set-cookie"); | 331 | cookiestr = table_get(r->headers_out, "set-cookie"); | 
| 419 | if (cookiestr != NULL) { | 332 | if (cookiestr != NULL) { | 
| 420 | #ifdef DEBUG | 333 | #ifdef DEBUG | 
| @@ -434,8 +347,7 @@ static const char *log_cookie(request_rec *r, char *a) | |||
| 434 | return "-"; | 347 | return "-"; | 
| 435 | } | 348 | } | 
| 436 | 349 | ||
| 437 | 350 | static const char *extract_request_timestamp(request_rec *r, char *a) | |
| 438 | const char *log_request_timestamp(request_rec *r, char *a) | ||
| 439 | { | 351 | { | 
| 440 | char tstr[32]; | 352 | char tstr[32]; | 
| 441 | 353 | ||
| @@ -443,19 +355,18 @@ const char *log_request_timestamp(request_rec *r, char *a) | |||
| 443 | return pstrdup(r->pool, tstr); | 355 | return pstrdup(r->pool, tstr); | 
| 444 | } | 356 | } | 
| 445 | 357 | ||
| 446 | static const char *log_note(request_rec *r, char *a) | 358 | static const char *extract_note(request_rec *r, char *a) | 
| 447 | { | 359 | { | 
| 448 | return table_get(r->notes, a); | 360 | return table_get(r->notes, a); | 
| 449 | } | 361 | } | 
| 450 | 362 | ||
| 451 | static const char *log_env_var(request_rec *r, char *a) | 363 | static const char *extract_env_var(request_rec *r, char *a) | 
| 452 | { | 364 | { | 
| 453 | return table_get(r->subprocess_env, a); | 365 | return table_get(r->subprocess_env, a); | 
| 454 | } | 366 | } | 
| 455 | #endif /* MODULE_MAGIC_NUMBER */ | ||
| 456 | 367 | ||
| 368 | /* End declarations of various extract_ functions */ | ||
| 457 | 369 | ||
| 458 | /* End declarations of various log_ functions */ | ||
| 459 | 370 | ||
| 460 | 371 | ||
| 461 | struct log_mysql_item_list { | 372 | struct log_mysql_item_list { | 
| @@ -466,39 +377,39 @@ struct log_mysql_item_list { | |||
| 466 | int string_contents; | 377 | int string_contents; | 
| 467 | } log_mysql_item_keys[] = { | 378 | } log_mysql_item_keys[] = { | 
| 468 | 379 | ||
| 469 | { 'A', log_agent, "agent", 1, 1 }, | 380 | { 'A', extract_agent, "agent", 1, 1 }, | 
| 470 | { 'b', log_bytes_sent, "bytes_sent", 0, 0 }, | 381 | { 'b', extract_bytes_sent, "bytes_sent", 0, 0 }, | 
| 471 | { 'c', log_cookie, "cookie", 0, 1 }, | 382 | { 'c', extract_cookie, "cookie", 0, 1 }, | 
| 472 | { 'e', log_env_var, "env_var", 0, 1 }, | 383 | { 'e', extract_env_var, "env_var", 0, 1 }, | 
| 473 | { 'f', log_request_file, "request_file", 0, 1 }, | 384 | { 'f', extract_request_file, "request_file", 0, 1 }, | 
| 474 | { 'H', log_request_protocol, "request_protocol", 0, 1 }, | 385 | { 'H', extract_request_protocol, "request_protocol", 0, 1 }, | 
| 475 | { 'h', log_remote_host, "remote_host", 0, 1 }, | 386 | { 'h', extract_remote_host, "remote_host", 0, 1 }, | 
| 476 | { 'i', log_header_in, "header_in", 0, 1 }, | 387 | { 'i', extract_header_in, "header_in", 0, 1 }, | 
| 477 | { 'l', log_remote_logname, "remote_logname", 0, 1 }, | 388 | { 'l', extract_remote_logname, "remote_logname", 0, 1 }, | 
| 478 | { 'm', log_request_method, "request_method", 0, 1 }, | 389 | { 'm', extract_request_method, "request_method", 0, 1 }, | 
| 479 | { 'n', log_note, "note", 0, 1 }, | 390 | { 'n', extract_note, "note", 0, 1 }, | 
| 480 | { 'o', log_header_out, "header_out", 0, 1 }, | 391 | { 'o', extract_header_out, "header_out", 0, 1 }, | 
| 481 | { 'P', log_child_pid, "child_pid", 0, 0 }, | 392 | { 'P', extract_child_pid, "child_pid", 0, 0 }, | 
| 482 | { 'p', log_server_port, "server_port", 0, 0 }, | 393 | { 'p', extract_server_port, "server_port", 0, 0 }, | 
| 483 | { 'R', log_referer, "referer", 1, 1 }, | 394 | { 'R', extract_referer, "referer", 1, 1 }, | 
| 484 | { 'r', log_request_line, "request_line", 1, 1 }, | 395 | { 'r', extract_request_line, "request_line", 1, 1 }, | 
| 485 | { 'S', log_request_timestamp, "time_stamp", 0, 0 }, | 396 | { 'S', extract_request_timestamp, "time_stamp", 0, 0 }, | 
| 486 | { 's', log_status, "status", 1, 0 }, | 397 | { 's', extract_status, "status", 1, 0 }, | 
| 487 | { 'T', log_request_duration, "request_duration", 1, 0 }, | 398 | { 'T', extract_request_duration, "request_duration", 1, 0 }, | 
| 488 | { 't', log_request_time, "request_time", 0, 1 }, | 399 | { 't', extract_request_time, "request_time", 0, 1 }, | 
| 489 | { 'u', log_remote_user, "remote_user", 0, 1 }, | 400 | { 'u', extract_remote_user, "remote_user", 0, 1 }, | 
| 490 | { 'U', log_request_uri, "request_uri", 1, 1 }, | 401 | { 'U', extract_request_uri, "request_uri", 1, 1 }, | 
| 491 | { 'v', log_virtual_host, "virtual_host", 0, 1 }, | 402 | { 'v', extract_virtual_host, "virtual_host", 0, 1 }, | 
| 492 | #ifdef WANT_SSL_LOGGING | 403 | #ifdef WANT_SSL_LOGGING | 
| 493 | { 'q', log_ssl_keysize, "ssl_keysize", 0, 1 }, | 404 | { 'q', extract_ssl_keysize, "ssl_keysize", 0, 1 }, | 
| 494 | { 'Q', log_ssl_maxkeysize, "ssl_maxkeysize", 0, 1 }, | 405 | { 'Q', extract_ssl_maxkeysize, "ssl_maxkeysize", 0, 1 }, | 
| 495 | { 'z', log_ssl_cipher, "ssl_cipher", 0, 1 }, | 406 | { 'z', extract_ssl_cipher, "ssl_cipher", 0, 1 }, | 
| 496 | #endif | 407 | #endif | 
| 497 | {'\0'} | 408 | {'\0'} | 
| 498 | }; | 409 | }; | 
| 499 | 410 | ||
| 500 | 411 | ||
| 501 | /* Routine to escape 'dangerous' characters that would otherwise | 412 | /* Routine to escape the 'dangerous' characters that would otherwise | 
| 502 | * corrupt the INSERT string: ', \, and " | 413 | * corrupt the INSERT string: ', \, and " | 
| 503 | */ | 414 | */ | 
| 504 | const char *mysql_escape_log(const char *str, pool *p) | 415 | const char *mysql_escape_log(const char *str, pool *p) | 
| @@ -528,7 +439,7 @@ const char *mysql_escape_log(const char *str, pool *p) | |||
| 528 | /* Pre-allocate a new string that could hold twice the original, which would only | 439 | /* Pre-allocate a new string that could hold twice the original, which would only | 
| 529 | * happen if the whole original string was 'dangerous' characters. | 440 | * happen if the whole original string was 'dangerous' characters. | 
| 530 | */ | 441 | */ | 
| 531 | tmp_str = (char *) palloc(p, length *2 + 1); | 442 | tmp_str = (char *) palloc(p, length * 2 + 1); | 
| 532 | if (!tmp_str) { | 443 | if (!tmp_str) { | 
| 533 | return str; | 444 | return str; | 
| 534 | } | 445 | } | 
| @@ -552,16 +463,15 @@ const char *mysql_escape_log(const char *str, pool *p) | |||
| 552 | } | 463 | } | 
| 553 | } | 464 | } | 
| 554 | 465 | ||
| 555 | 466 | void open_logdb_link() | |
| 556 | void open_log_dblink() | ||
| 557 | { | 467 | { | 
| 558 | if (mysql_log != NULL) { /* virtual database link shared with main server */ | 468 | if (mysql_log != NULL) { /* virtual database link shared with main server */ | 
| 559 | return; | 469 | return; | 
| 560 | } | 470 | } | 
| 561 | if (log_db_name) { /* open an SQL link */ | 471 | if (db_name) { /* open an SQL link */ | 
| 562 | mysql_log = mysql_connect(&log_sql_server, db_host, db_user, db_pwd); | 472 | mysql_log = mysql_connect(&sql_server, db_host, db_user, db_pwd); | 
| 563 | if (mysql_log) { /* link opened */ | 473 | if (mysql_log) { /* link opened */ | 
| 564 | if (mysql_select_db(mysql_log, log_db_name) != 0) { /* unable to select database */ | 474 | if (mysql_select_db(mysql_log, db_name) != 0) { /* unable to select database */ | 
| 565 | mysql_close(mysql_log); | 475 | mysql_close(mysql_log); | 
| 566 | mysql_log = NULL; | 476 | mysql_log = NULL; | 
| 567 | } | 477 | } | 
| @@ -569,23 +479,72 @@ void open_log_dblink() | |||
| 569 | } | 479 | } | 
| 570 | } | 480 | } | 
| 571 | 481 | ||
| 572 | 482 | int safe_mysql_query(request_rec *r, const char *query) | |
| 573 | void *make_log_mysql_state(pool *p, server_rec *s) | ||
| 574 | { | 483 | { | 
| 575 | log_mysql_state *cls = (log_mysql_state *) palloc(p, sizeof(log_mysql_state)); | 484 | int retval = 1; | 
| 485 | struct timespec delay, remainder; | ||
| 486 | int ret; | ||
| 487 | char *str; | ||
| 488 | void (*handler) (int); | ||
| 576 | 489 | ||
| 577 | cls->referer_table_name = cls->agent_table_name = cls->transfer_table_name = ""; | 490 | /* A failed mysql_query() may send a SIGPIPE, so we ignore that signal momentarily. */ | 
| 578 | cls->referer_ignore_list = make_array(p, 1, sizeof(char *)); | 491 | handler = signal(SIGPIPE, SIG_IGN); | 
| 579 | cls->transfer_ignore_list = make_array(p, 1, sizeof(char *)); | 492 | |
| 580 | cls->remhost_ignore_list = make_array(p, 1, sizeof(char *)); | 493 | /* If there's no DB link, or if we run the query and it gacks, try to be graceful */ | 
| 581 | cls->transfer_log_format = ""; | 494 | if ( !mysql_log || | 
| 582 | return (void *) cls; | 495 | ( | 
| 496 | (retval = mysql_query(mysql_log, query)) && | ||
| 497 | (mysql_errno(mysql_log) != 0) | ||
| 498 | ) | ||
| 499 | ) | ||
| 500 | |||
| 501 | { /* We need to restart the server link */ | ||
| 502 | mysql_log = NULL; | ||
| 503 | ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"MySQL: connection lost, attempting reconnect"); | ||
| 504 | |||
| 505 | open_logdb_link(); | ||
| 506 | |||
| 507 | if (mysql_log == NULL) { /* still unable to link */ | ||
| 508 | signal(SIGPIPE, handler); | ||
| 509 | ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"MySQL: reconnect failed"); | ||
| 510 | return retval; | ||
| 511 | } | ||
| 512 | |||
| 513 | ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"MySQL: reconnect successful"); | ||
| 514 | retval = mysql_query(mysql_log, query); | ||
| 515 | } | ||
| 516 | |||
| 517 | /* Restore SIGPIPE to its original handler function */ | ||
| 518 | signal(SIGPIPE, handler); | ||
| 519 | |||
| 520 | if (retval) { | ||
| 521 | /* Attempt a single re-try... First sleep for a tiny amount of time. */ | ||
| 522 | delay.tv_sec = 0; | ||
| 523 | delay.tv_nsec = 500000000; /* max is 999999999 (nine nines) */ | ||
| 524 | ret = nanosleep(&delay, &remainder); | ||
| 525 | if (ret && errno != EINTR) | ||
| 526 | perror("nanosleep"); | ||
| 527 | |||
| 528 | /* Now re-attempt */ | ||
| 529 | retval = mysql_query(mysql_log,query); | ||
| 530 | |||
| 531 | if (retval) { | ||
| 532 | str = pstrcat(r->pool, "MySQL insert failed: ", query, NULL); | ||
| 533 | ap_log_error(APLOG_MARK,ERRLEVEL,r->server,str); | ||
| 534 | str = pstrcat(r->pool, "MySQL failure reason: ", MYSQL_ERROR(mysql_log), NULL); | ||
| 535 | ap_log_error(APLOG_MARK,ERRLEVEL,r->server,str); | ||
| 536 | } else { | ||
| 537 | ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"MySQL: insert successful after a delayed retry."); | ||
| 538 | } | ||
| 539 | } | ||
| 540 | return retval; | ||
| 583 | } | 541 | } | 
| 584 | 542 | ||
| 543 | |||
| 544 | |||
| 585 | const char *set_referer_log_mysql_table(cmd_parms *parms, void *dummy, char *arg) | 545 | const char *set_referer_log_mysql_table(cmd_parms *parms, void *dummy, char *arg) | 
| 586 | { | 546 | { | 
| 587 | log_mysql_state *cls = get_module_config(parms->server->module_config, | 547 | log_mysql_state *cls = get_module_config(parms->server->module_config, &mysql_log_module); | 
| 588 | &mysql_log_module); | ||
| 589 | 548 | ||
| 590 | cls->referer_table_name = arg; | 549 | cls->referer_table_name = arg; | 
| 591 | return NULL; | 550 | return NULL; | 
| @@ -594,8 +553,7 @@ const char *set_referer_log_mysql_table(cmd_parms *parms, void *dummy, char *arg | |||
| 594 | 553 | ||
| 595 | const char *set_agent_log_mysql_table(cmd_parms *parms, void *dummy, char *arg) | 554 | const char *set_agent_log_mysql_table(cmd_parms *parms, void *dummy, char *arg) | 
| 596 | { | 555 | { | 
| 597 | log_mysql_state *cls = get_module_config(parms->server->module_config, | 556 | log_mysql_state *cls = get_module_config(parms->server->module_config, &mysql_log_module); | 
| 598 | &mysql_log_module); | ||
| 599 | 557 | ||
| 600 | cls->agent_table_name = arg; | 558 | cls->agent_table_name = arg; | 
| 601 | return NULL; | 559 | return NULL; | 
| @@ -604,8 +562,7 @@ const char *set_agent_log_mysql_table(cmd_parms *parms, void *dummy, char *arg) | |||
| 604 | 562 | ||
| 605 | const char *set_transfer_log_mysql_table(cmd_parms *parms, void *dummy, char *arg) | 563 | const char *set_transfer_log_mysql_table(cmd_parms *parms, void *dummy, char *arg) | 
| 606 | { | 564 | { | 
| 607 | log_mysql_state *cls = get_module_config(parms->server->module_config, | 565 | log_mysql_state *cls = get_module_config(parms->server->module_config, &mysql_log_module); | 
| 608 | &mysql_log_module); | ||
| 609 | 566 | ||
| 610 | cls->transfer_table_name = arg; | 567 | cls->transfer_table_name = arg; | 
| 611 | return NULL; | 568 | return NULL; | 
| @@ -614,8 +571,7 @@ const char *set_transfer_log_mysql_table(cmd_parms *parms, void *dummy, char *ar | |||
| 614 | 571 | ||
| 615 | const char *set_transfer_log_format(cmd_parms *parms, void *dummy, char *arg) | 572 | const char *set_transfer_log_format(cmd_parms *parms, void *dummy, char *arg) | 
| 616 | { | 573 | { | 
| 617 | log_mysql_state *cls = get_module_config(parms->server->module_config, | 574 | log_mysql_state *cls = get_module_config(parms->server->module_config, &mysql_log_module); | 
| 618 | &mysql_log_module); | ||
| 619 | 575 | ||
| 620 | cls->transfer_log_format = arg; | 576 | cls->transfer_log_format = arg; | 
| 621 | return NULL; | 577 | return NULL; | 
| @@ -624,7 +580,7 @@ const char *set_transfer_log_format(cmd_parms *parms, void *dummy, char *arg) | |||
| 624 | 580 | ||
| 625 | const char *set_log_mysql_db(cmd_parms *parms, void *dummy, char *arg) | 581 | const char *set_log_mysql_db(cmd_parms *parms, void *dummy, char *arg) | 
| 626 | { | 582 | { | 
| 627 | log_db_name = arg; | 583 | db_name = arg; | 
| 628 | return NULL; | 584 | return NULL; | 
| 629 | } | 585 | } | 
| 630 | 586 | ||
| @@ -682,103 +638,68 @@ const char *add_remhost_mysql_ignore(cmd_parms *parms, void *dummy, char *arg) | |||
| 682 | return NULL; | 638 | return NULL; | 
| 683 | } | 639 | } | 
| 684 | 640 | ||
| 641 | |||
| 642 | /* | ||
| 643 | * Apache-specific hooks into the module code | ||
| 644 | * that are defined in the array 'mysql_lgog_module' (at EOF) | ||
| 645 | */ | ||
| 646 | |||
| 647 | |||
| 648 | /* Set up space for the various major configuration options */ | ||
| 649 | void *log_mysql_make_state(pool *p, server_rec *s) | ||
| 650 | { | ||
| 651 | log_mysql_state *cls = (log_mysql_state *) palloc(p, sizeof(log_mysql_state)); | ||
| 652 | |||
| 653 | cls->referer_table_name = cls->agent_table_name = cls->transfer_table_name = ""; | ||
| 654 | |||
| 655 | cls->referer_ignore_list = make_array(p, 1, sizeof(char *)); | ||
| 656 | cls->transfer_ignore_list = make_array(p, 1, sizeof(char *)); | ||
| 657 | cls->remhost_ignore_list = make_array(p, 1, sizeof(char *)); | ||
| 658 | |||
| 659 | cls->transfer_log_format = ""; | ||
| 660 | return (void *) cls; | ||
| 661 | } | ||
| 662 | |||
| 663 | |||
| 664 | /* Setup of the available httpd.conf configuration commands. | ||
| 665 | * command, function called, NULL, where available, how many arguments, verbose description | ||
| 666 | */ | ||
| 685 | command_rec log_mysql_cmds[] = { | 667 | command_rec log_mysql_cmds[] = { | 
| 686 | {"MySQLRefererLogTable", set_referer_log_mysql_table, NULL, RSRC_CONF, TAKE1, | 668 | {"MySQLRefererLogTable", set_referer_log_mysql_table, NULL, RSRC_CONF, TAKE1, | 
| 687 | "The MySQL table that holds the referer log"} | 669 | "The MySQL table that holds the referer log"} | 
| 688 | , | 670 | , | 
| 689 | {"MySQLAgentLogTable", set_agent_log_mysql_table, NULL, RSRC_CONF, TAKE1, | 671 | {"MySQLAgentLogTable", set_agent_log_mysql_table, NULL, RSRC_CONF, TAKE1, | 
| 690 | "The MySQL table that holds the agent log"} | 672 | "The MySQL table that holds the agent log"} | 
| 691 | , | 673 | , | 
| 692 | {"MySQLTransferLogTable", set_transfer_log_mysql_table, NULL, RSRC_CONF, TAKE1, | 674 | {"MySQLTransferLogTable", set_transfer_log_mysql_table, NULL, RSRC_CONF, TAKE1, | 
| 693 | "The MySQL table that holds the transfer log"} | 675 | "The MySQL table that holds the transfer log"} | 
| 694 | , | 676 | , | 
| 695 | {"MySQLTransferLogFormat", set_transfer_log_format, NULL, RSRC_CONF, TAKE1, | 677 | {"MySQLTransferLogFormat", set_transfer_log_format, NULL, RSRC_CONF, TAKE1, | 
| 696 | "Instruct the module what information to log to the MySQL transfer log"} | 678 | "Instruct the module what information to log to the MySQL transfer log"} | 
| 697 | , | 679 | , | 
| 698 | {"MySQLRefererIgnore", add_referer_mysql_ignore, NULL, RSRC_CONF, ITERATE, | 680 | {"MySQLRefererIgnore", add_referer_mysql_ignore, NULL, RSRC_CONF, ITERATE, | 
| 699 | "List of referers to ignore, accesses that match will not be logged to MySQL"} | 681 | "List of referers to ignore. Accesses that match will not be logged to MySQL"} | 
| 700 | , | 682 | , | 
| 701 | {"MySQLRequestIgnore", add_transfer_mysql_ignore, NULL, RSRC_CONF, ITERATE, | 683 | {"MySQLRequestIgnore", add_transfer_mysql_ignore, NULL, RSRC_CONF, ITERATE, | 
| 702 | "List of URIs to ignore, accesses that match will not be logged to MySQL"} | 684 | "List of URIs to ignore. Accesses that match will not be logged to MySQL"} | 
| 703 | , | 685 | , | 
| 704 | {"MySQLRemhostIgnore", add_remhost_mysql_ignore, NULL, RSRC_CONF, ITERATE, | 686 | {"MySQLRemhostIgnore", add_remhost_mysql_ignore, NULL, RSRC_CONF, ITERATE, | 
| 705 | "List of remote hosts to ignore, accesses that match will not be logged to MySQL"} | 687 | "List of remote hosts to ignore. Accesses that match will not be logged to MySQL"} | 
| 706 | , | 688 | , | 
| 707 | {"MySQLDatabase", set_log_mysql_db, NULL, RSRC_CONF, TAKE1, | 689 | {"MySQLDatabase", set_log_mysql_db, NULL, RSRC_CONF, TAKE1, | 
| 708 | "The name of the MySQL database for logging"} | 690 | "The name of the MySQL database for logging"} | 
| 709 | , | 691 | , | 
| 710 | {"MySQLWhichCookie", set_log_mysql_cookie, NULL, RSRC_CONF, TAKE1, | 692 | {"MySQLWhichCookie", set_log_mysql_cookie, NULL, RSRC_CONF, TAKE1, | 
| 711 | "The CookieName that you want logged when using the 'c' config directive"} | 693 | "The CookieName that you want logged when using the 'c' config directive"} | 
| 712 | , | 694 | , | 
| 713 | {"MySQLLoginInfo", set_log_mysql_info, NULL, RSRC_CONF, TAKE3, | 695 | {"MySQLLoginInfo", set_log_mysql_info, NULL, RSRC_CONF, TAKE3, | 
| 714 | "The MySQL host, user-id and password for logging"} | 696 | "The MySQL host, user-id and password for logging"} | 
| 715 | , | 697 | , | 
| 716 | {NULL} | 698 | {NULL} | 
| 717 | }; | 699 | }; | 
| 718 | 700 | ||
| 719 | 701 | ||
| 720 | int safe_mysql_query(request_rec *r, const char *query) | 702 | |
| 721 | { | ||
| 722 | int error = 1; | ||
| 723 | struct timespec delay, remainder; | ||
| 724 | int ret; | ||
| 725 | char *str; | ||
| 726 | void (*handler) (int); | ||
| 727 | |||
| 728 | /* A failed mysql_query() may send a SIGPIPE, so we ignore that signal momentarily. */ | ||
| 729 | handler = signal(SIGPIPE, SIG_IGN); | ||
| 730 | |||
| 731 | /* If there's no DB link, or if we run the query and it gacks, try to be graceful */ | ||
| 732 | if ( !mysql_log || | ||
| 733 | ( | ||
| 734 | (error = mysql_query(mysql_log, query)) && | ||
| 735 | !strcasecmp(mysql_error(mysql_log), "MySQL server has gone away") | ||
| 736 | ) | ||
| 737 | ) | ||
| 738 | |||
| 739 | { /* We need to restart the server link */ | ||
| 740 | mysql_log = NULL; | ||
| 741 | ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"MySQL: connection lost, attempting reconnect"); | ||
| 742 | |||
| 743 | open_log_dblink(); | ||
| 744 | |||
| 745 | if (mysql_log == NULL) { /* still unable to link */ | ||
| 746 | signal(SIGPIPE, handler); | ||
| 747 | ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"MySQL: reconnect failed."); | ||
| 748 | return error; | ||
| 749 | } | ||
| 750 | |||
| 751 | ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"MySQL: reconnect successful."); | ||
| 752 | error = mysql_query(mysql_log, query); | ||
| 753 | } | ||
| 754 | |||
| 755 | /* Restore SIGPIPE to its original handler function */ | ||
| 756 | signal(SIGPIPE, handler); | ||
| 757 | |||
| 758 | if (error) { | ||
| 759 | /* Attempt a single re-try... First sleep for a tiny amount of time. */ | ||
| 760 | delay.tv_sec = 0; | ||
| 761 | delay.tv_nsec = 500000000; /* max is 999999999 (nine nines) */ | ||
| 762 | ret = nanosleep(&delay, &remainder); | ||
| 763 | if (ret && errno != EINTR) | ||
| 764 | perror("nanosleep"); | ||
| 765 | |||
| 766 | /* Now re-attempt */ | ||
| 767 | error = mysql_query(mysql_log,query); | ||
| 768 | |||
| 769 | if (error) { | ||
| 770 | str = pstrcat(r->pool, "MySQL query failed: ", query, NULL); | ||
| 771 | ap_log_error(APLOG_MARK,ERRLEVEL,r->server,str); | ||
| 772 | str = pstrcat(r->pool, "MySQL failure reason: ", MYSQL_ERROR(mysql_log), NULL); | ||
| 773 | ap_log_error(APLOG_MARK,ERRLEVEL,r->server,str); | ||
| 774 | } else { | ||
| 775 | ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"MySQL: insert successful after a delayed retry."); | ||
| 776 | } | ||
| 777 | } | ||
| 778 | return error; | ||
| 779 | } | ||
| 780 | |||
| 781 | |||
| 782 | /* Routine to perform the actual construction and execution of the relevant | 703 | /* Routine to perform the actual construction and execution of the relevant | 
| 783 | * INSERT statements. | 704 | * INSERT statements. | 
| 784 | */ | 705 | */ | 
| @@ -805,7 +726,7 @@ int log_mysql_transaction(request_rec *orig) | |||
| 805 | } | 726 | } | 
| 806 | 727 | ||
| 807 | if (mysql_log == NULL) { /* mysql link not up, hopefully we can do something about it */ | 728 | if (mysql_log == NULL) { /* mysql link not up, hopefully we can do something about it */ | 
| 808 | open_log_dblink(); | 729 | open_logdb_link(); | 
| 809 | if (mysql_log == NULL) { | 730 | if (mysql_log == NULL) { | 
| 810 | return OK; | 731 | return OK; | 
| 811 | } | 732 | } | 
| @@ -932,13 +853,20 @@ int log_mysql_transaction(request_rec *orig) | |||
| 932 | } | 853 | } | 
| 933 | 854 | ||
| 934 | 855 | ||
| 856 | /* Called on the exit of an httpd child process */ | ||
| 857 | static void log_mysql_child_exit(server_rec *s, pool *p) | ||
| 858 | { | ||
| 859 | mysql_close(mysql_log); | ||
| 860 | } | ||
| 935 | 861 | ||
| 862 | |||
| 863 | /* The configuration array that sets up the hooks into the module. */ | ||
| 936 | module mysql_log_module = { | 864 | module mysql_log_module = { | 
| 937 | STANDARD_MODULE_STUFF, | 865 | STANDARD_MODULE_STUFF, | 
| 938 | NULL, /* initializer */ | 866 | NULL, /* initializer */ | 
| 939 | NULL, /* create per-dir config */ | 867 | NULL, /* create per-dir config */ | 
| 940 | NULL, /* merge per-dir config */ | 868 | NULL, /* merge per-dir config */ | 
| 941 | make_log_mysql_state, /* server config */ | 869 | log_mysql_make_state, /* server config */ | 
| 942 | NULL, /* merge server config */ | 870 | NULL, /* merge server config */ | 
| 943 | log_mysql_cmds, /* command table */ | 871 | log_mysql_cmds, /* command table */ | 
| 944 | NULL, /* handlers */ | 872 | NULL, /* handlers */ | 
| @@ -949,5 +877,11 @@ module mysql_log_module = { | |||
| 949 | NULL, /* type_checker */ | 877 | NULL, /* type_checker */ | 
| 950 | NULL, /* fixups */ | 878 | NULL, /* fixups */ | 
| 951 | log_mysql_transaction, /* logger */ | 879 | log_mysql_transaction, /* logger */ | 
| 952 | NULL /* header parser */ | 880 | NULL, /* header parser */ | 
| 881 | #if MODULE_MAGIC_NUMBER >= 19970728 /* 1.3-dev or later support these additionals... */ | ||
| 882 | NULL, /* child_init */ | ||
| 883 | log_mysql_child_exit, /* process exit/cleanup */ | ||
| 884 | NULL /* [#0] post read-request */ | ||
| 885 | #endif | ||
| 886 | |||
| 953 | }; | 887 | }; | 
