Bojan Smojver wrote:
> This time a version that actually compiles :-)
>
> I have tested this and it seems to be working OK for both SSL and plain
> connections. The patch also includes changes to the documentation and
> sample configuration files, which can now take advantage of this
> logging. I've called the new custom log "combinedio".
>
> As usual, this is against the latest CVS head. I doubt that this will be
> the last of it, but it might be a good start, or at least I hope ;-)
>
> Finally, big thanks to everyone that helped me learn bits of Apache API
> and for all the ideas.
>
I'm sorry for jumping in so late in the game, but
why can't you do the same thing as a seperate module which implements
the optional hook function to get those two directives in '%I/%O'
i'm concerned that this will add undue burden on everybodies request
wheather they use the %I/%O directives or not.
> Bojan
>
>
> ------------------------------------------------------------------------
>
> diff -u --recursive --new-file httpd-2.0/docs/conf/httpd-nw.conf
>httpd-2.0-patched/docs/conf/httpd-nw.conf
> --- httpd-2.0/docs/conf/httpd-nw.conf Wed Sep 18 21:40:17 2002
> +++ httpd-2.0-patched/docs/conf/httpd-nw.conf Fri Sep 20 08:03:47 2002
> @@ -372,6 +372,7 @@
> # The following directives define some format nicknames for use with
> # a CustomLog directive (see below).
> #
> +LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O"
>combinedio
> LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
> LogFormat "%h %l %u %t \"%r\" %>s %b" common
> LogFormat "%{Referer}i -> %U" referer
> diff -u --recursive --new-file httpd-2.0/docs/conf/httpd-std.conf.in
>httpd-2.0-patched/docs/conf/httpd-std.conf.in
> --- httpd-2.0/docs/conf/httpd-std.conf.in Wed Sep 18 21:40:18 2002
> +++ httpd-2.0-patched/docs/conf/httpd-std.conf.in Fri Sep 20 08:03:18 2002
> @@ -474,6 +474,7 @@
> # The following directives define some format nicknames for use with
> # a CustomLog directive (see below).
> #
> +LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O"
>combinedio
> LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
> LogFormat "%h %l %u %t \"%r\" %>s %b" common
> LogFormat "%{Referer}i -> %U" referer
> diff -u --recursive --new-file httpd-2.0/docs/conf/httpd-win.conf
>httpd-2.0-patched/docs/conf/httpd-win.conf
> --- httpd-2.0/docs/conf/httpd-win.conf Wed Sep 18 21:40:18 2002
> +++ httpd-2.0-patched/docs/conf/httpd-win.conf Fri Sep 20 08:04:03 2002
> @@ -401,6 +401,7 @@
> # The following directives define some format nicknames for use with
> # a CustomLog directive (see below).
> #
> +LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O"
>combinedio
> LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
> LogFormat "%h %l %u %t \"%r\" %>s %b" common
> LogFormat "%{Referer}i -> %U" referer
> diff -u --recursive --new-file httpd-2.0/docs/manual/mod/mod_log_config.html.en
>httpd-2.0-patched/docs/manual/mod/mod_log_config.html.en
> --- httpd-2.0/docs/manual/mod/mod_log_config.html.en Fri Sep 13 10:15:25 2002
> +++ httpd-2.0-patched/docs/manual/mod/mod_log_config.html.en Fri Sep 20 08:05:39
>2002
> @@ -138,6 +138,12 @@
> this conflicted with the historical ssl %...{var}c syntax.)</div>
> </td></tr>
>
> +<tr><td>%...I:</td>
> +<td>Bytes received, including request and headers, cannot be zero.</td></tr>
> +
> +<tr><td>%...O:</td>
> +<td>Bytes sent, including headers, cannot be zero.</td></tr>
> +
> </table>
>
> <p>The "..." can be nothing at all (<em>e.g.</em>, <code>"%h %u
> @@ -352,4 +358,4 @@
> TransferLog logs/access_log
> </code></p></div>
>
> -</div></div><div id="footer"><p class="apache">Maintained by the <a
>href="http://httpd.apache.org/docs-project/">Apache HTTP Server Documentation
>Project</a></p><p class="menu"><a href="../mod/">Modules</a> | <a
>href="../mod/directives.html">Directives</a> | <a href="../faq/">FAQ</a> | <a
>href="../glossary.html">Glossary</a> | <a
>href="../sitemap.html">Sitemap</a></p></div></body></html>
> \ No newline at end of file
> +</div></div><div id="footer"><p class="apache">Maintained by the <a
>href="http://httpd.apache.org/docs-project/">Apache HTTP Server Documentation
>Project</a></p><p class="menu"><a href="../mod/">Modules</a> | <a
>href="../mod/directives.html">Directives</a> | <a href="../faq/">FAQ</a> | <a
>href="../glossary.html">Glossary</a> | <a
>href="../sitemap.html">Sitemap</a></p></div></body></html>
> diff -u --recursive --new-file httpd-2.0/docs/manual/mod/mod_log_config.xml
>httpd-2.0-patched/docs/manual/mod/mod_log_config.xml
> --- httpd-2.0/docs/manual/mod/mod_log_config.xml Sat Sep 7 13:22:03 2002
> +++ httpd-2.0-patched/docs/manual/mod/mod_log_config.xml Fri Sep 20 08:05:37
>2002
> @@ -143,6 +143,12 @@
> this conflicted with the historical ssl %...{var}c syntax.)</note>
> </td></tr>
>
> +<tr><td>%...I:</td>
> +<td>Bytes received, including request and headers, cannot be zero.</td></tr>
> +
> +<tr><td>%...O:</td>
> +<td>Bytes sent, including headers, cannot be zero.</td></tr>
> +
> </table>
>
> <p>The "..." can be nothing at all (<em>e.g.</em>, <code>"%h %u
> diff -u --recursive --new-file httpd-2.0/modules/loggers/mod_log_config.c
>httpd-2.0-patched/modules/loggers/mod_log_config.c
> --- httpd-2.0/modules/loggers/mod_log_config.c Mon Sep 16 23:17:57 2002
> +++ httpd-2.0-patched/modules/loggers/mod_log_config.c Fri Sep 20 07:57:32
>2002
> @@ -153,9 +153,11 @@
> * 'X' = connection aborted before the response completed.
> * '+' = connection may be kept alive after the response is sent.
> * '-' = connection will be closed after the response is sent.
> - (This directive was %...c in late versions of Apache 1.3, but
> - this conflicted with the historical ssl %...{var}c syntax.)
> -*
> + * (This directive was %...c in late versions of Apache 1.3, but
> + * this conflicted with the historical ssl %...{var}c syntax.)
> + * %...I: bytes received, including request and headers, cannot be zero
> + * %...O: bytes sent, including headers, cannot be zero
> + *
> * The '...' can be nothing at all (e.g. "%h %u %r %s %b"), or it can
> * indicate conditions for inclusion of the item (which will cause it
> * to be replaced with '-' if the condition is not met). Note that
> @@ -236,6 +238,8 @@
> static ap_log_writer_init *log_writer_init = ap_default_log_writer_init;
> static int buffered_logs = 0; /* default unbuffered */
>
> +static const char logio_filter_name[] = "LOG_INPUT_OUTPUT";
> +
> /* POSIX.1 defines PIPE_BUF as the maximum number of bytes that is
> * guaranteed to be atomic when writing a pipe. And PIPE_BUF >= 512
> * is guaranteed. So we'll just guess 512 in the event the system
> @@ -298,6 +302,16 @@
> char *condition_var;
> } config_log_state;
>
> +/*****************************************************************
> + *
> + * Logging of input and output config ...
> + */
> +
> +typedef struct logio_config_t {
> + apr_off_t bytes_in;
> + apr_off_t bytes_out;
> +} logio_config_t;
> +
> /*
> * Format items...
> * Note that many of these could have ap_sprintfs replaced with static buffers.
> @@ -620,6 +634,22 @@
> return "-";
> }
>
> +static const char *log_bytes_in(request_rec *r, char *a)
> +{
> + logio_config_t *cf = ap_get_module_config(r->connection->conn_config,
> + &log_config_module);
> +
> + return apr_off_t_toa(r->pool, cf->bytes_in);
> +}
> +
> +static const char *log_bytes_out(request_rec *r, char *a)
> +{
> + logio_config_t *cf = ap_get_module_config(r->connection->conn_config,
> + &log_config_module);
> +
> + return apr_off_t_toa(r->pool, cf->bytes_out);
> +}
> +
> /*****************************************************************
> *
> * Parsing the log format string
> @@ -904,6 +934,8 @@
> {
> multi_log_state *mls = ap_get_module_config(r->server->module_config,
> &log_config_module);
> + logio_config_t *cf = ap_get_module_config(r->connection->conn_config,
> + &log_config_module);
> config_log_state *clsarray;
> int i;
>
> @@ -927,11 +959,62 @@
> }
> }
>
> + cf->bytes_in = cf->bytes_out = 0;
> +
> return OK;
> }
>
> /*****************************************************************
> *
> + * Logging of input and output filters ...
> + */
> +
> +static apr_status_t logio_out_filter(ap_filter_t *f,
> + apr_bucket_brigade *bb) {
> + apr_off_t length;
> + logio_config_t *cf = ap_get_module_config(f->c->conn_config,
> + &log_config_module);
> +
> + if (!cf) { /* Create config */
> + cf = apr_pcalloc(f->c->pool, sizeof(*cf));
> + ap_set_module_config(f->c->conn_config, &log_config_module, cf);
> + }
> +
> + apr_brigade_length (bb, 0, &length);
> +
> + if (length > 0)
> + cf->bytes_out += length;
> +
> + return ap_pass_brigade(f->next, bb);
> +}
> +
> +static apr_status_t logio_in_filter(ap_filter_t *f,
> + apr_bucket_brigade *bb,
> + ap_input_mode_t mode,
> + apr_read_type_e block,
> + apr_off_t readbytes) {
> + apr_off_t length;
> + apr_status_t status;
> + logio_config_t *cf = ap_get_module_config(f->c->conn_config,
> + &log_config_module);
> +
> + status = ap_get_brigade(f->next, bb, mode, block, readbytes);
> +
> + if (!cf) { /* Create config */
> + cf = apr_pcalloc(f->c->pool, sizeof(*cf));
> + ap_set_module_config(f->c->conn_config, &log_config_module, cf);
> + }
> +
> + apr_brigade_length (bb, 0, &length);
> +
> + if (length > 0)
> + cf->bytes_in += length;
> +
> + return status;
> +}
> +
> +/*****************************************************************
> + *
> * Module glue...
> */
>
> @@ -1333,6 +1416,13 @@
> return rv;
> }
>
> +static int logio_pre_conn(conn_rec *c) {
> + ap_add_input_filter(logio_filter_name, NULL, NULL, c);
> + ap_add_output_filter(logio_filter_name, NULL, NULL, c);
> +
> + return OK;
> +}
> +
> static int log_pre_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp)
> {
> static APR_OPTIONAL_FN_TYPE(ap_register_log_handler) *log_pfn_register;
> @@ -1367,6 +1457,8 @@
> log_pfn_register(p, "T", log_request_duration, 1);
> log_pfn_register(p, "U", log_request_uri, 1);
> log_pfn_register(p, "s", log_status, 1);
> + log_pfn_register(p, "I", log_bytes_in, 0);
> + log_pfn_register(p, "O", log_bytes_out, 0);
> }
>
> return OK;
> @@ -1374,6 +1466,7 @@
>
> static void register_hooks(apr_pool_t *p)
> {
> + ap_hook_pre_connection(logio_pre_conn, NULL, NULL, APR_HOOK_MIDDLE);
> ap_hook_pre_config(log_pre_config,NULL,NULL,APR_HOOK_REALLY_FIRST);
> ap_hook_child_init(init_child,NULL,NULL,APR_HOOK_MIDDLE);
> ap_hook_open_logs(init_config_log,NULL,NULL,APR_HOOK_MIDDLE);
> @@ -1389,6 +1482,11 @@
> APR_REGISTER_OPTIONAL_FN(ap_register_log_handler);
> APR_REGISTER_OPTIONAL_FN(ap_log_set_writer_init);
> APR_REGISTER_OPTIONAL_FN(ap_log_set_writer);
> +
> + ap_register_input_filter(logio_filter_name, logio_in_filter, NULL,
> + AP_FTYPE_NETWORK - 1);
> + ap_register_output_filter(logio_filter_name, logio_out_filter, NULL,
> + AP_FTYPE_NETWORK - 1);
> }
>
> module AP_MODULE_DECLARE_DATA log_config_module =