You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by Alexei Kosut <ak...@nueva.pvt.k12.ca.us> on 1996/09/03 03:15:14 UTC
mod_log_config enhancements
Here's a patch that adds a couple more logging directives to
mod_log_config; I think they're useful:
%U: the URL path that was requested
%f: the filename.
%P: the PID of the child that served the request (this might be useful
for tracking the BROKEN_WAIT problem; I dunno.)
It also adds a %{...}n directive that returns the contents of a note
(from the r->notes table). The idea of this is that modules can set
notes with data to be logged. This patch, as an example, has
mod_cookies put its cookie into a note called "cookie". This allows
mod_log_config to log it without having to use a seperate cookie log
(and without having to use %{Cookie}i, which also gets the "Apache="
and any other cookies that might be sent).
Anyhow, thoughts?
Index: mod_cookies.c
===================================================================
RCS file: /export/home/cvs/apache/src/mod_cookies.c,v
retrieving revision 1.14
diff -c -r1.14 mod_cookies.c
*** mod_cookies.c 1996/08/24 14:41:32 1.14
--- mod_cookies.c 1996/09/03 01:11:13
***************
*** 368,375 ****
for (r = orig; r->next; r = r->next)
continue;
- if (*cls->fname == '\0') /* Don't log cookies */
- return DECLINED;
if (!(cookie = table_get (r->headers_in, "Cookie")))
return DECLINED; /* Theres no cookie, don't bother logging */
--- 368,373 ----
***************
*** 380,385 ****
--- 378,389 ----
cookiebuf=pstrdup( r->pool, value );
cookieend=strchr(cookiebuf,';');
if (cookieend) *cookieend='\0'; /* Ignore anything after a ; */
+
+ /* Set the cookie in a note, in case we log it seperately */
+ table_set(r->notes, "cookie", cookiebuf);
+
+ if (*cls->fname == '\0') /* Don't log cookies */
+ return DECLINED;
t = get_gmtoff(&timz);
sign = (timz < 0 ? '-' : '+');
Index: mod_log_config.c
===================================================================
RCS file: /export/home/cvs/apache/src/mod_log_config.c,v
retrieving revision 1.11
diff -c -r1.11 mod_log_config.c
*** mod_log_config.c 1996/08/27 03:34:45 1.11
--- mod_log_config.c 1996/09/03 01:11:19
***************
*** 109,120 ****
--- 109,123 ----
* follows:
*
* %...b: bytes sent.
+ * %...f: filename
* %...h: remote host
* %...{Foobar}i: The contents of Foobar: header line(s) in the request
* sent to the client.
* %...l: remote logname (from identd, if supplied)
+ * %...{Foobar}n: The contents of note "Foobar" from another module.
* %...{Foobar}o: The contents of Foobar: header line(s) in the reply.
* %...p: the port the request was served to
+ * %...P: the process ID of the child that serviced the request.
* %...r: first line of request
* %...s: status. For requests that got internally redirected, this
* is status of the *original* request --- %...>s for the last.
***************
*** 123,128 ****
--- 126,132 ----
* be in strftime(3) format.
* %...T: the time taken to serve the request, in seconds.
* %...u: remote user (from auth; may be bogus if return status (%s) is 401)
+ * %...U: the URL path requested.
* %...v: the name of the server (i.e. which virtual host?)
*
* The '...' can be nothing at all (e.g. "%h %u %r %s %b"), or it can
***************
*** 243,248 ****
--- 247,258 ----
char *log_request_line (request_rec *r, char *a)
{ return r->the_request; }
+ char *log_request_file (request_rec *r, char *a)
+ { return r->filename; }
+
+ char *log_request_uri (request_rec *r, char *a)
+ { return r->uri; }
+
char *log_status (request_rec *r, char *a)
{ return pfmt(r->pool, r->status); }
***************
*** 271,276 ****
--- 281,289 ----
return table_get (r->err_headers_out, a);
}
+ char *log_note (request_rec *r, char *a)
+ { return table_get (r->notes, a); }
+
char *log_env_var (request_rec *r, char *a)
{ return table_get (r->subprocess_env, a); }
***************
*** 315,320 ****
--- 328,340 ----
return pstrdup(r->pool, portnum);
}
+ char *log_child_pid (request_rec *r, char *a) {
+ char pidnum[10];
+
+ sprintf(pidnum, "%ld", getpid());
+ return pstrdup(r->pool, pidnum);
+ }
+
/*****************************************************************
*
* Parsing the log format string
***************
*** 331,343 ****
--- 351,367 ----
{ 't', log_request_time, 0 },
{ 'T', log_request_duration, 0 },
{ 'r', log_request_line, 1 },
+ { 'f', log_request_file, 0 },
+ { 'U', log_request_uri, 1 },
{ 's', log_status, 1 },
{ 'b', log_bytes_sent, 0 },
{ 'i', log_header_in, 0 },
{ 'o', log_header_out, 0 },
+ { 'n', log_note, 0 },
{ 'e', log_env_var, 0 },
{ 'v', log_virtual_host, 0 },
{ 'p', log_server_port, 0 },
+ { 'P', log_child_pid, 0 },
{ '\0' }
};
--
________________________________________________________________________
Alexei Kosut <ak...@nueva.pvt.k12.ca.us> The Apache HTTP Server
URL: http://www.nueva.pvt.k12.ca.us/~akosut/ http://www.apache.org/
Re: mod_log_config enhancements
Posted by Mark J Cox <ma...@ukweb.com>.
On Mon, 2 Sep 1996, Alexei Kosut wrote:
> mod_cookies put its cookie into a note called "cookie". This allows
> mod_log_config to log it without having to use a seperate cookie log
+1 on Alexei's patch; works here.
Here is an additional patch that I'd like comments on; it uses Alexei's
patch and removes the logging code completely from mod_cookies.c. Now
that the log_config module can create multiple log files the extra
overhead of handling log files and pipes internally is redundant. I've
created a "CookieLog" directive that works as before, but the
documentation can be changed to deprecate it (and suggest logging as part
of standard logs).
This has to be applied *after* Alexei's patch
Mark
*** mod_cookies.c.alex Tue Sep 3 09:13:53 1996
--- mod_cookies.c Tue Sep 3 09:58:08 1996
***************
*** 68,82 ****
* the browser (via a "Set-Cookie" header)
* Future requests from the same browser should keep the same Cookie line.
*
! * The cookie and request are logged to a file. Use the directive
! * "CookieLog somefilename" in one of the config files to enable the Cookie
! * module. By matching up all the requests with the same cookie you can
! * work out exactly what path a user took through your site.
*
* Notes:
! * 1. This code doesn't log the initial transaction (the one that created
! * the cookie to start with). If it did then the cookie log file would
! * be bigger than a normal access log.
* 2. This module has been designed to not interfere with other Cookies
* your site may be using; just avoid sending out cookies with
* the name "Apache=" or things will get confused.
--- 68,89 ----
* the browser (via a "Set-Cookie" header)
* Future requests from the same browser should keep the same Cookie line.
*
! * By matching up all the requests with the same cookie you can
! * work out exactly what path a user took through your site. To log
! * the cookie use the " %{Cookie}n " directive in a custom access log;
! *
! * Example 1 : If you currently use the standard Log file format (CLF)
! * and use the command "TransferLog somefilename", add the line
! * LogFormat "%h %l %u %t \"%r\" %s %b %{Cookie}n"
! * to your config file.
! *
! * Example 2 : If you used to use the old "CookieLog" directive, you
! * can emulate it by adding the following command to your config file
! * CustomLog filename "%{Cookie}n \"%r\" %t"
*
* Notes:
! * 1. This code now logs the initial transaction (the one that created
! * the cookie to start with).
* 2. This module has been designed to not interfere with other Cookies
* your site may be using; just avoid sending out cookies with
* the name "Apache=" or things will get confused.
***************
*** 97,102 ****
--- 104,110 ----
* 24.5.96 MJC Improved documentation after receiving comments from users
* 4.7.96 MJC Bug, "else" missing since February caused logging twice
* 19.7.96 AEK Added CookieExpires and CookieEnable directives
+ * 03.9.96 MJC Remove logging stuff from here, (use AEK notes addition)
*/
#include "httpd.h"
***************
*** 107,114 ****
module cookies_module;
typedef struct {
- char *fname;
- int log_fd;
int always;
time_t expires;
} cookie_log_state;
--- 115,120 ----
***************
*** 156,163 ****
#endif
tms = gmtime(&when);
-
-
/* Cookie with date; as strftime '%a, %d-%h-%y %H:%M:%S GMT' */
sprintf(new_cookie,
"%s%s%d%ld%d; path=/; expires=%s, %.2d-%s-%.2d %.2d:%.2d:%.2d GMT",
--- 162,167 ----
***************
*** 182,213 ****
int *disable = (int *)get_module_config(r->per_dir_config,
&cookies_module);
char *cookie;
if (*disable) return DECLINED;
if ((cookie = table_get (r->headers_in, "Cookie")))
! if (strstr(cookie,COOKIE_NAME))
! return DECLINED; /* Theres already a cookie, no new one */
make_cookie(r);
return OK; /* We set our cookie */
}
- static int cookie_flags = ( O_WRONLY | O_APPEND | O_CREAT );
-
- #ifdef __EMX__
- /* OS/2 lacks support for users and groups */
- static mode_t cookie_mode = ( S_IREAD | S_IWRITE );
- #else
- static mode_t cookie_mode = ( S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH );
- #endif
-
void *make_cookie_log_state (pool *p, server_rec *s)
{
cookie_log_state *cls =
(cookie_log_state *)palloc (p, sizeof (cookie_log_state));
- cls->fname = "";
- cls->log_fd = -1;
cls->expires = 0;
return (void *)cls;
--- 186,218 ----
int *disable = (int *)get_module_config(r->per_dir_config,
&cookies_module);
char *cookie;
+ char *value;
if (*disable) return DECLINED;
if ((cookie = table_get (r->headers_in, "Cookie")))
! if ((value=strstr(cookie,COOKIE_NAME))) {
! char *cookiebuf, *cookieend;
!
! value+=strlen(COOKIE_NAME);
! cookiebuf=pstrdup( r->pool, value );
! cookieend=strchr(cookiebuf,';');
! if (cookieend) *cookieend='\0'; /* Ignore anything after a ; */
!
! /* Set the cookie in a note, for logging */
! table_set(r->notes, "cookie", cookiebuf);
!
! return DECLINED; /* Theres already a cookie, no new one */
! }
make_cookie(r);
return OK; /* We set our cookie */
}
void *make_cookie_log_state (pool *p, server_rec *s)
{
cookie_log_state *cls =
(cookie_log_state *)palloc (p, sizeof (cookie_log_state));
cls->expires = 0;
return (void *)cls;
***************
*** 223,236 ****
return NULL;
}
- char *set_cookie_log (cmd_parms *parms, void *dummy, char *arg)
- {
- cookie_log_state *cls = get_module_config (parms->server->module_config,
- &cookies_module);
- cls->fname = arg;
- return NULL;
- }
-
char *set_cookie_exp (cmd_parms *parms, void *dummy, char *arg)
{
cookie_log_state *cls = get_module_config (parms->server->module_config,
--- 228,233 ----
***************
*** 297,304 ****
}
command_rec cookie_log_cmds[] = {
- { "CookieLog", set_cookie_log, NULL, RSRC_CONF, TAKE1,
- "the filename of the cookie log" },
{ "CookieExpires", set_cookie_exp, NULL, RSRC_CONF, TAKE1,
"an expiry date code" },
{ "CookieEnable", set_cookie_disable, NULL, OR_FILEINFO, FLAG,
--- 294,299 ----
***************
*** 306,425 ****
{ NULL }
};
- void cookie_log_child (void *cmd)
- {
- /* Child process code for 'CookieLog "|..."';
- * may want a common framework for this, since I expect it will
- * be common for other foo-loggers to want this sort of thing...
- */
-
- cleanup_for_exec();
- signal (SIGHUP, SIG_IGN);
- execl (SHELL_PATH, SHELL_PATH, "-c", (char *)cmd, NULL);
- exit (1);
- }
-
- void open_cookie_log (server_rec *s, pool *p)
- {
- cookie_log_state *cls = get_module_config (s->module_config,
- &cookies_module);
- char *fname = server_root_relative (p, cls->fname);
-
- if (cls->log_fd > 0) return;
-
- if (*cls->fname == '|') {
- FILE *dummy;
-
- spawn_child(p, cookie_log_child, (void *)(cls->fname+1),
- kill_after_timeout, &dummy, NULL);
-
- if (dummy == NULL) {
- fprintf (stderr, "Couldn't fork child for CookieLog process\n");
- exit (1);
- }
-
- cls->log_fd = fileno (dummy);
- }
- else if(*cls->fname != '\0') {
- if((cls->log_fd = popenf(p, fname, cookie_flags, cookie_mode)) < 0) {
- fprintf(stderr, "httpd: could not open cookie log file %s.\n", fname);
- perror("open");
- exit(1);
- }
- }
- }
-
- void init_cookie_log (server_rec *s, pool *p)
- {
- for (; s; s = s->next) open_cookie_log (s, p);
- }
-
- int cookie_log_transaction(request_rec *orig)
- {
- cookie_log_state *cls = get_module_config (orig->server->module_config,
- &cookies_module);
- char *str;
- long timz;
- struct tm *t;
- char tstr[MAX_STRING_LEN],sign;
- request_rec *r;
- char *cookie,*cookiebuf,*cookieend;
- char *value;
-
- for (r = orig; r->next; r = r->next)
- continue;
-
- if (!(cookie = table_get (r->headers_in, "Cookie")))
- return DECLINED; /* Theres no cookie, don't bother logging */
- value=strstr(cookie,COOKIE_NAME);
- if (!value) /* Only log cookies we generated! */
- return DECLINED;
- value+=strlen(COOKIE_NAME);
- cookiebuf=pstrdup( r->pool, value );
- cookieend=strchr(cookiebuf,';');
- if (cookieend) *cookieend='\0'; /* Ignore anything after a ; */
-
- /* Set the cookie in a note, in case we log it seperately */
- table_set(r->notes, "cookie", cookiebuf);
-
- if (*cls->fname == '\0') /* Don't log cookies */
- return DECLINED;
-
- t = get_gmtoff(&timz);
- sign = (timz < 0 ? '-' : '+');
- if(timz < 0)
- timz = -timz;
-
- strftime(tstr,MAX_STRING_LEN,"\" [%d/%b/%Y:%H:%M:%S ",t);
- if (r->status != -1)
- sprintf(&tstr[strlen(tstr)], "%c%02ld%02ld] %d\n", sign, timz/3600,
- timz%3600, r->status);
- else
- sprintf(&tstr[strlen(tstr)], "%c%02ld%02ld] -\n", sign, timz/3600,
- timz%3600);
-
- str = pstrcat(orig->pool, cookiebuf, " \"", orig->the_request, tstr, NULL);
-
- write(cls->log_fd, str, strlen(str));
-
- return OK;
- }
-
-
module cookies_module = {
STANDARD_MODULE_STUFF,
! init_cookie_log, /* initializer */
! make_cookie_dir, /* dir config creater */
! NULL, /* dir merger --- default is to override */
! make_cookie_log_state, /* server config */
! NULL, /* merge server configs */
! cookie_log_cmds, /* command table */
! NULL, /* handlers */
! NULL, /* filename translation */
! NULL, /* check_user_id */
! NULL, /* check auth */
! NULL, /* check access */
! NULL, /* type_checker */
! spot_cookie, /* fixups */
! cookie_log_transaction, /* logger */
};
--- 301,320 ----
{ NULL }
};
module cookies_module = {
STANDARD_MODULE_STUFF,
! NULL, /* initializer */
! make_cookie_dir, /* dir config creater */
! NULL, /* dir merger --- default is to override */
! make_cookie_log_state, /* server config */
! NULL, /* merge server configs */
! cookie_log_cmds, /* command table */
! NULL, /* handlers */
! NULL, /* filename translation */
! NULL, /* check_user_id */
! NULL, /* check auth */
! NULL, /* check access */
! NULL, /* type_checker */
! spot_cookie, /* fixups */
! NULL, /* logger */
};
*** mod_log_config.c.alex Tue Sep 3 09:13:59 1996
--- mod_log_config.c Tue Sep 3 09:46:38 1996
***************
*** 65,70 ****
--- 65,72 ----
* CustomLog fn format
* Log to file fn with format given by the format
* argument
+ * CookieLog fn For backwards compatability with old Cookie
+ * logging module
*
* There can be any number of TransferLog and CustomLog
* commands. Each request will be logged to _ALL_ the
***************
*** 651,661 ****
--- 653,670 ----
return add_custom_log(cmd, dummy, fn, NULL);
}
+ char *set_cookie_log(cmd_parms *cmd, void *dummy, char *fn)
+ {
+ return add_custom_log(cmd, dummy, fn, "%{Cookie}n \"%r\" %t");
+ }
+
command_rec config_log_cmds[] = {
{ "CustomLog", add_custom_log, NULL, RSRC_CONF, TAKE2,
"a file name and a custom log format string" },
{ "TransferLog", set_transfer_log, NULL, RSRC_CONF, TAKE1,
"the filename of the access log" },
+ { "CookieLog", set_cookie_log, NULL, RSRC_CONF, TAKE1,
+ "the filename of the Cookie log" },
{ "LogFormat", log_format, NULL, RSRC_CONF, TAKE1,
"a log format string (see docs)" },
{ NULL }