Main Page | Modules | Namespace List | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals | Related Pages | Examples

mod_logio.c

Go to the documentation of this file.
00001 /* Copyright 2002-2005 The Apache Software Foundation or its licensors, as
00002  * applicable.
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 /*
00018  * Written by Bojan Smojver <bojan@rexursive.com>:
00019  *
00020  * The argument to LogFormat and CustomLog is a string, which can include
00021  * literal characters copied into the log files, and '%' directives as
00022  * follows:
00023  *
00024  * %...I:  bytes received, including request and headers, cannot be zero
00025  * %...O:  bytes sent, including headers, cannot be zero
00026  *
00027  */
00028 
00029 #include "apr_strings.h"
00030 #include "apr_lib.h"
00031 #include "apr_hash.h"
00032 #include "apr_optional.h"
00033 
00034 #define APR_WANT_STRFUNC
00035 #include "apr_want.h"
00036 
00037 #include "ap_config.h"
00038 #include "mod_log_config.h"
00039 #include "httpd.h"
00040 #include "http_core.h"
00041 #include "http_config.h"
00042 #include "http_connection.h"
00043 #include "http_protocol.h"
00044 
00045 module AP_MODULE_DECLARE_DATA logio_module;
00046 
00047 static const char logio_filter_name[] = "LOG_INPUT_OUTPUT";
00048 
00049 /*
00050  * Logging of input and output config...
00051  */
00052 
00053 typedef struct logio_config_t {
00054     apr_off_t bytes_in;
00055     apr_off_t bytes_out;
00056 } logio_config_t;
00057 
00058 /*
00059  * Optional function for the core to add to bytes_out
00060  */
00061 
00062 static void ap_logio_add_bytes_out(conn_rec *c, apr_off_t bytes){
00063     logio_config_t *cf = ap_get_module_config(c->conn_config, &logio_module);
00064 
00065     cf->bytes_out += bytes;
00066 }
00067 
00068 /*
00069  * Format items...
00070  */
00071 
00072 static const char *log_bytes_in(request_rec *r, char *a)
00073 {
00074     logio_config_t *cf = ap_get_module_config(r->connection->conn_config,
00075                                               &logio_module);
00076 
00077     return apr_off_t_toa(r->pool, cf->bytes_in);
00078 }
00079 
00080 static const char *log_bytes_out(request_rec *r, char *a)
00081 {
00082     logio_config_t *cf = ap_get_module_config(r->connection->conn_config,
00083                                               &logio_module);
00084 
00085     return apr_off_t_toa(r->pool, cf->bytes_out);
00086 }
00087 
00088 /*
00089  * Reset counters after logging...
00090  */
00091 
00092 static int logio_transaction(request_rec *r)
00093 {
00094     logio_config_t *cf = ap_get_module_config(r->connection->conn_config,
00095                                               &logio_module);
00096 
00097     cf->bytes_in = cf->bytes_out = 0;
00098 
00099     return OK;
00100 }
00101 
00102 /*
00103  * Logging of input and output filters...
00104  */
00105 
00106 static apr_status_t logio_in_filter(ap_filter_t *f,
00107                                     apr_bucket_brigade *bb,
00108                                     ap_input_mode_t mode,
00109                                     apr_read_type_e block,
00110                                     apr_off_t readbytes) {
00111     apr_off_t length;
00112     apr_status_t status;
00113     logio_config_t *cf = ap_get_module_config(f->c->conn_config, &logio_module);
00114 
00115     status = ap_get_brigade(f->next, bb, mode, block, readbytes);
00116 
00117     apr_brigade_length (bb, 0, &length);
00118 
00119     if (length > 0)
00120         cf->bytes_in += length;
00121 
00122     return status;
00123 }
00124 
00125 static apr_status_t logio_out_filter(ap_filter_t *f,
00126                                      apr_bucket_brigade *bb) {
00127     apr_bucket *b = APR_BRIGADE_LAST(bb);
00128 
00129     /* End of data, make sure we flush */
00130     if (APR_BUCKET_IS_EOS(b)) {
00131         APR_BUCKET_INSERT_BEFORE(b,
00132                                  apr_bucket_flush_create(f->c->bucket_alloc));
00133     }
00134 
00135     return ap_pass_brigade(f->next, bb);
00136 }
00137 
00138 /*
00139  * The hooks...
00140  */
00141 
00142 static int logio_pre_conn(conn_rec *c, void *csd) {
00143     logio_config_t *cf = apr_pcalloc(c->pool, sizeof(*cf));
00144 
00145     ap_set_module_config(c->conn_config, &logio_module, cf);
00146 
00147     ap_add_input_filter(logio_filter_name, NULL, NULL, c);
00148     ap_add_output_filter(logio_filter_name, NULL, NULL, c);
00149 
00150     return OK;
00151 }
00152 
00153 static int logio_pre_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp)
00154 {
00155     static APR_OPTIONAL_FN_TYPE(ap_register_log_handler) *log_pfn_register;
00156     
00157     log_pfn_register = APR_RETRIEVE_OPTIONAL_FN(ap_register_log_handler);
00158 
00159     if (log_pfn_register) {
00160         log_pfn_register(p, "I", log_bytes_in, 0);
00161         log_pfn_register(p, "O", log_bytes_out, 0);
00162     }
00163 
00164     return OK;
00165 }
00166 
00167 static void register_hooks(apr_pool_t *p)
00168 {
00169     static const char *pre[] = { "mod_log_config.c", NULL };
00170 
00171     ap_hook_pre_connection(logio_pre_conn, NULL, NULL, APR_HOOK_MIDDLE);
00172     ap_hook_pre_config(logio_pre_config, NULL, NULL, APR_HOOK_REALLY_FIRST);
00173     ap_hook_log_transaction(logio_transaction, pre, NULL, APR_HOOK_MIDDLE);
00174 
00175     ap_register_input_filter(logio_filter_name, logio_in_filter, NULL,
00176                              AP_FTYPE_NETWORK - 1);
00177     ap_register_output_filter(logio_filter_name, logio_out_filter, NULL,
00178                               AP_FTYPE_NETWORK - 1);
00179 
00180     APR_REGISTER_OPTIONAL_FN(ap_logio_add_bytes_out);
00181 }
00182 
00183 module AP_MODULE_DECLARE_DATA logio_module =
00184 {
00185     STANDARD20_MODULE_STUFF,
00186     NULL,                       /* create per-dir config */
00187     NULL,                       /* merge per-dir config */
00188     NULL,                       /* server config */
00189     NULL,                       /* merge server config */
00190     NULL,                       /* command apr_table_t */
00191     register_hooks              /* register hooks */
00192 };