summaryrefslogtreecommitdiffstats
path: root/INSTALL
diff options
context:
space:
mode:2002-05-16 21:35:12 +0000
committerGravatar Christopher Powell 2002-05-16 21:35:12 +0000
commit29329b3e7c68e6af2370968d7900daffa63adb93 (patch)
tree3ccbca2b5995827151c84e4810dcdb4cfe4c64e1
parent7bac244dcd4356314c37a469b957d9b94cddaba6 (diff)
Further changes on the way to 1.17, big one was the segfault fix.
-rw-r--r--CHANGELOG9
-rw-r--r--mod_log_sql.c304
2 files changed, 160 insertions, 153 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 24e56a1..8f53074 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,4 +1,4 @@
1$Id: CHANGELOG,v 1.11 2002/05/14 21:47:14 helios Exp $ 1$Id: CHANGELOG,v 1.12 2002/05/16 21:35:12 helios Exp $
2 2
3 3
4TODO: 4TODO:
@@ -8,7 +8,8 @@ TODO:
8* check for mandatory conf directives / syntax quit if not 8* check for mandatory conf directives / syntax quit if not
9* merge server config into vh config 9* merge server config into vh config
10* port to Apache 2.x 10* port to Apache 2.x
11 11* does determining table name in massvirtual mode upon every request
12 cause performance degradation? If so fix.
12 13
13CHANGES: 14CHANGES:
14 15
@@ -32,6 +33,10 @@ CHANGES:
32 really dumb, and people have requested this change. 33 really dumb, and people have requested this change.
33* Better checking in the extract_cookie routine. Before, it could 34* Better checking in the extract_cookie routine. Before, it could
34 segfault if a person specified "c" but didn't define MySQLWhichCookie. 35 segfault if a person specified "c" but didn't define MySQLWhichCookie.
36* Some code reorg/renaming for clarity and to support the new direction
37 of database inspecificity. More to come.
38* Simplified error messages.
39* Table creation now uses safe_mysql_query and checks the result.
35 40
36 41
371.16: 421.16:
diff --git a/mod_log_sql.c b/mod_log_sql.c
index 84c6115..6726163 100644
--- a/mod_log_sql.c
+++ b/mod_log_sql.c
@@ -1,4 +1,4 @@
1/* $Id: mod_log_sql.c,v 1.12 2002/05/14 21:47:15 helios Exp $ */ 1/* $Id: mod_log_sql.c,v 1.13 2002/05/16 21:35:12 helios Exp $ */
2 2
3/* --------* 3/* --------*
4 * DEFINES * 4 * DEFINES *
@@ -76,7 +76,7 @@ typedef struct {
76 char *transfer_log_format; 76 char *transfer_log_format;
77 char *preserve_file; 77 char *preserve_file;
78 char *cookie_name; 78 char *cookie_name;
79} log_mysql_state; 79} log_sql_state;
80 80
81 81
82/* -----------------* 82/* -----------------*
@@ -322,7 +322,7 @@ static const char *extract_cookie(request_rec *r, char *a)
322 char *isvalid; 322 char *isvalid;
323 char *cookiebuf; 323 char *cookiebuf;
324 324
325 log_mysql_state *cls = get_module_config(r->server->module_config, &mysql_log_module); 325 log_sql_state *cls = get_module_config(r->server->module_config, &mysql_log_module);
326 326
327 if (cls->cookie_name != NULL) { 327 if (cls->cookie_name != NULL) {
328 #ifdef DEBUG 328 #ifdef DEBUG
@@ -423,13 +423,13 @@ static const char *extract_unique_id(request_rec *r, char *a)
423 423
424 424
425 425
426struct log_mysql_item_list { 426struct log_sql_item_list {
427 char ch; /* its letter code */ 427 char ch; /* its letter code */
428 item_key_func func; /* its extraction function */ 428 item_key_func func; /* its extraction function */
429 const char *sql_field_name; /* its column in SQL */ 429 const char *sql_field_name; /* its column in SQL */
430 int want_orig_default; /* if it requires the original request prior to internal redirection */ 430 int want_orig_default; /* if it requires the original request prior to internal redirection */
431 int string_contents; /* if it returns a string */ 431 int string_contents; /* if it returns a string */
432 } log_mysql_item_keys[] = { 432 } log_sql_item_keys[] = {
433 433
434 { 'A', extract_agent, "agent", 1, 1 }, 434 { 'A', extract_agent, "agent", 1, 1 },
435 { 'b', extract_bytes_sent, "bytes_sent", 0, 0 }, 435 { 'b', extract_bytes_sent, "bytes_sent", 0, 0 },
@@ -553,11 +553,11 @@ const char *extract_table(void *data, const char *key, const char *val)
553void preserve_entry(request_rec *r, const char *query) 553void preserve_entry(request_rec *r, const char *query)
554{ 554{
555 FILE *fp; 555 FILE *fp;
556 log_mysql_state *cls = get_module_config(r->server->module_config, &mysql_log_module); 556 log_sql_state *cls = get_module_config(r->server->module_config, &mysql_log_module);
557 557
558 fp = pfopen(r->pool, cls->preserve_file, "a"); 558 fp = pfopen(r->pool, cls->preserve_file, "a");
559 if (fp == NULL) 559 if (fp == NULL)
560 ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"attempted append of local offline file but failed."); 560 ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"mod_log_sql: attempted append of local preserve file but failed.");
561 else { 561 else {
562 fprintf(fp,"%s;\n", query); 562 fprintf(fp,"%s;\n", query);
563 pfclose(r->pool, fp); 563 pfclose(r->pool, fp);
@@ -565,7 +565,7 @@ void preserve_entry(request_rec *r, const char *query)
565} 565}
566 566
567/*-----------------------------------------------------*/ 567/*-----------------------------------------------------*/
568/* safe_mysql_query: perform a database insert with */ 568/* safe_mysql_query: perform a database query with */
569/* a degree of safety and error checking. */ 569/* a degree of safety and error checking. */
570/* */ 570/* */
571/* Parms: request record, SQL insert statement */ 571/* Parms: request record, SQL insert statement */
@@ -577,7 +577,6 @@ int safe_mysql_query(request_rec *r, const char *query)
577 int retval; 577 int retval;
578 struct timespec delay, remainder; 578 struct timespec delay, remainder;
579 int ret; 579 int ret;
580 char *str;
581 void (*handler) (int); 580 void (*handler) (int);
582 581
583 582
@@ -585,53 +584,54 @@ int safe_mysql_query(request_rec *r, const char *query)
585 handler = signal(SIGPIPE, SIG_IGN); 584 handler = signal(SIGPIPE, SIG_IGN);
586 585
587 /* First attempt for the query */ 586 /* First attempt for the query */
588 retval = mysql_query(mysql_log, query); 587 if (mysql_log != NULL)
589 588 retval = mysql_query(mysql_log, query);
589 else
590 return 1;
591
590 /* If we ran the query and it returned an error, try to be graceful. 592 /* If we ran the query and it returned an error, try to be graceful.
591 * We only reach this point if the module thinks it has a valid connection to the 593 * (The module thought it had a valid mysql_log connection but the query
592 * database (i.e. mysql_log is non-null). But that connection could go sour 594 * might have failed, so we have to check.)
593 * at any time, hence the check. */ 595 */
594 if ( retval != 0 ) 596 if ( retval != 0 )
595 { 597 {
596 log_mysql_state *cls = get_module_config(r->server->module_config, &mysql_log_module); 598 log_sql_state *cls = get_module_config(r->server->module_config, &mysql_log_module);
597 599
598 /* Something went wrong, so start by trying to restart the db link. */ 600 /* Something went wrong, so start by trying to restart the db link. */
599 ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"attempting reconnect because API said: %s", mysql_error(mysql_log)); 601 ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"mod_log_sql: first attempt failed, API said: %s", MYSQL_ERROR(mysql_log));
600 602
601 mysql_log = NULL; 603 mysql_log = NULL;
602 open_logdb_link(); 604 open_logdb_link();
603 605
604 if (mysql_log == NULL) { /* still unable to link */ 606 if (mysql_log == NULL) { /* still unable to link */
605 signal(SIGPIPE, handler); 607 signal(SIGPIPE, handler);
606 ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"httpd child reconnect failed, unable to reach database. SQL logging stopped until an httpd child regains a db connection."); 608 ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"mod_log_sql: reconnect failed, unable to reach database. SQL logging stopped until child regains a db connection.");
607 ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"log entries are being preserved in %s", cls->preserve_file); 609 ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"mod_log_sql: log entries are being preserved in %s", cls->preserve_file);
608 preserve_entry(r, query); 610 preserve_entry(r, query);
609 return retval; 611 return retval;
610 } else { 612 } else {
611 ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"reconnect successful."); 613 ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"mod_log_sql: reconnect successful");
612 } 614 }
613
614 /* Attempt a single re-try... First sleep for a tiny amount of time. */
615 delay.tv_sec = 0;
616 delay.tv_nsec = 250000000; /* max is 999999999 (nine nines) */
617 ret = nanosleep(&delay, &remainder);
618 if (ret && errno != EINTR)
619 ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"nanosleep unsuccessful.");
620
621 /* Now make our second attempt */
622 retval = mysql_query(mysql_log,query);
623
624 /* If this one also failed, log that and append to our local offline file */
625 if ( retval != 0 )
626 {
627 str = ap_pstrcat(r->pool, "delayed insert attempt failed, API said: ", MYSQL_ERROR(mysql_log), NULL);
628 ap_log_error(APLOG_MARK,ERRLEVEL,r->server,str);
629 615
630 preserve_entry(r, query); 616 /* Attempt a single re-try... First sleep for a tiny amount of time. */
631 ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"entry preserved in %s", cls->preserve_file); 617 delay.tv_sec = 0;
632 } else { 618 delay.tv_nsec = 250000000; /* max is 999999999 (nine nines) */
633 ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"insert successful after a delayed retry."); 619 ret = nanosleep(&delay, &remainder);
634 } 620 if (ret && errno != EINTR)
621 ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"mod_log_sql: nanosleep unsuccessful");
622
623 /* Now make our second attempt */
624 retval = mysql_query(mysql_log,query);
625
626 /* If this one also failed, log that and append to our local offline file */
627 if ( retval != 0 )
628 {
629 ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"mod_log_sql: second attempt failed, API said: %s", MYSQL_ERROR(mysql_log));
630 preserve_entry(r, query);
631 ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"mod_log_sql: entry preserved in %s", cls->preserve_file);
632 } else {
633 ap_log_error(APLOG_MARK,ERRLEVEL,r->server,"mod_log_sql: second attempt successful");
634 }
635 } 635 }
636 636
637 /* Restore SIGPIPE to its original handler function */ 637 /* Restore SIGPIPE to its original handler function */
@@ -646,43 +646,43 @@ int safe_mysql_query(request_rec *r, const char *query)
646 * to the directives found at Apache runtime. * 646 * to the directives found at Apache runtime. *
647 * ------------------------------------------------*/ 647 * ------------------------------------------------*/
648 648
649const char *set_mysql_massvirtual(cmd_parms *parms, void *dummy, int flag) 649const char *set_log_sql_massvirtual(cmd_parms *parms, void *dummy, int flag)
650{ 650{
651 massvirtual = ( flag ? 1 : 0); 651 massvirtual = ( flag ? 1 : 0);
652 return NULL; 652 return NULL;
653} 653}
654 654
655const char *set_log_mysql_create(cmd_parms *parms, void *dummy, int flag) 655const char *set_log_sql_create(cmd_parms *parms, void *dummy, int flag)
656{ 656{
657 create_tables = ( flag ? 1 : 0); 657 create_tables = ( flag ? 1 : 0);
658 return NULL; 658 return NULL;
659} 659}
660 660
661const char *set_log_mysql_db(cmd_parms *parms, void *dummy, char *arg) 661const char *set_log_sql_db(cmd_parms *parms, void *dummy, char *arg)
662{ 662{
663 db_name = arg; 663 db_name = arg;
664 return NULL; 664 return NULL;
665} 665}
666 666
667const char *set_log_mysql_cookie(cmd_parms *parms, void *dummy, char *arg) 667const char *set_log_sql_cookie(cmd_parms *parms, void *dummy, char *arg)
668{ 668{
669 log_mysql_state *cls = get_module_config(parms->server->module_config, &mysql_log_module); 669 log_sql_state *cls = get_module_config(parms->server->module_config, &mysql_log_module);
670 670
671 cls->cookie_name = arg; 671 cls->cookie_name = arg;
672 return NULL; 672 return NULL;
673} 673}
674 674
675const char *set_log_mysql_preserve_file(cmd_parms *parms, void *dummy, char *arg) 675const char *set_log_sql_preserve_file(cmd_parms *parms, void *dummy, char *arg)
676{ 676{
677 /* char *pfile; */ 677 /* char *pfile; */
678 log_mysql_state *cls = get_module_config(parms->server->module_config, &mysql_log_module); 678 log_sql_state *cls = get_module_config(parms->server->module_config, &mysql_log_module);
679 679
680 /* pfile = ap_pstrcat(parms->pool, "/tmp/", arg, NULL); */ 680 /* pfile = ap_pstrcat(parms->pool, "/tmp/", arg, NULL); */
681 cls->preserve_file = arg; 681 cls->preserve_file = arg;
682 return NULL; 682 return NULL;
683} 683}
684 684
685const char *set_log_mysql_info(cmd_parms *parms, void *dummy, char *host, char *user, char *pwd) 685const char *set_log_sql_info(cmd_parms *parms, void *dummy, char *host, char *user, char *pwd)
686{ 686{
687 if (*host != '.') { 687 if (*host != '.') {
688 db_host = host; 688 db_host = host;
@@ -696,37 +696,37 @@ const char *set_log_mysql_info(cmd_parms *parms, void *dummy, char *host, char *
696 return NULL; 696 return NULL;
697} 697}
698 698
699const char *set_transfer_log_mysql_table(cmd_parms *parms, void *dummy, char *argef='/httpd/mod_log_sql/tree/INSTALL?id=78adb60ccfd9497d5fbc899674ab1263609933b6#n189'>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