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 }