From 003bb0a830bae2f27f84004fec4a485de408fb64 Mon Sep 17 00:00:00 2001 From: Evgeny Kotkov Date: Tue, 27 Sep 2016 16:13:38 +0000 Subject: [PATCH] mod_brotli: Allow compression ratio logging with new BrotliFilterNote directive. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1762512 13f79535-47bb-0310-9956-ffa450edef68 --- modules/filters/mod_brotli.c | 64 ++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/modules/filters/mod_brotli.c b/modules/filters/mod_brotli.c index 829a01e468..7b82fc9892 100644 --- a/modules/filters/mod_brotli.c +++ b/modules/filters/mod_brotli.c @@ -34,6 +34,9 @@ typedef struct brotli_server_config_t { int lgwin; int lgblock; etag_mode_e etag_mode; + const char *note_ratio_name; + const char *note_input_name; + const char *note_output_name; } brotli_server_config_t; static void *create_server_config(apr_pool_t *p, server_rec *s) @@ -56,6 +59,34 @@ static void *create_server_config(apr_pool_t *p, server_rec *s) return conf; } +static const char *set_filter_note(cmd_parms *cmd, void *dummy, + const char *arg1, const char *arg2) +{ + brotli_server_config_t *conf = + ap_get_module_config(cmd->server->module_config, &brotli_module); + + if (!arg2) { + conf->note_ratio_name = arg1; + return NULL; + } + + if (ap_cstr_casecmp(arg1, "Ratio") == 0) { + conf->note_ratio_name = arg2; + } + else if (ap_cstr_casecmp(arg1, "Input") == 0) { + conf->note_input_name = arg2; + } + else if (ap_cstr_casecmp(arg1, "Output") == 0) { + conf->note_output_name = arg2; + } + else { + return apr_psprintf(cmd->pool, "Unknown BrotliFilterNote type '%s'", + arg1); + } + + return NULL; +} + static const char *set_compression_quality(cmd_parms *cmd, void *dummy, const char *arg) { @@ -126,6 +157,8 @@ static const char *set_etag_mode(cmd_parms *cmd, void *dummy, typedef struct brotli_ctx_t { BrotliEncoderState *state; apr_bucket_brigade *bb; + apr_off_t total_in; + apr_off_t total_out; } brotli_ctx_t; static void *alloc_func(void *opaque, size_t size) @@ -164,6 +197,8 @@ static brotli_ctx_t *create_ctx(int quality, apr_pool_cleanup_register(pool, ctx, cleanup_ctx, apr_pool_cleanup_null); ctx->bb = apr_brigade_create(pool, alloc); + ctx->total_in = 0; + ctx->total_out = 0; return ctx; } @@ -203,6 +238,8 @@ static apr_status_t process_chunk(brotli_ctx_t *ctx, * ap_pass_brigade() call. */ output = BrotliEncoderTakeOutput(ctx->state, &output_len); + ctx->total_out += output_len; + b = apr_bucket_transient_create(output, output_len, ctx->bb->bucket_alloc); APR_BRIGADE_INSERT_TAIL(ctx->bb, b); @@ -215,6 +252,7 @@ static apr_status_t process_chunk(brotli_ctx_t *ctx, } } + ctx->total_in += len; return APR_SUCCESS; } @@ -249,6 +287,8 @@ static apr_status_t flush(brotli_ctx_t *ctx, */ output_len = 0; output = BrotliEncoderTakeOutput(ctx->state, &output_len); + ctx->total_out += output_len; + b = apr_bucket_heap_create(output, output_len, NULL, ctx->bb->bucket_alloc); APR_BRIGADE_INSERT_TAIL(ctx->bb, b); @@ -440,6 +480,27 @@ static apr_status_t compress_filter(ap_filter_t *f, apr_bucket_brigade *bb) return rv; } + /* Leave notes for logging. */ + if (conf->note_input_name) { + apr_table_setn(r->notes, conf->note_input_name, + apr_off_t_toa(r->pool, ctx->total_in)); + } + if (conf->note_output_name) { + apr_table_setn(r->notes, conf->note_output_name, + apr_off_t_toa(r->pool, ctx->total_out)); + } + if (conf->note_ratio_name) { + if (ctx->total_in > 0) { + int ratio = (int) (ctx->total_out * 100 / ctx->total_in); + + apr_table_setn(r->notes, conf->note_ratio_name, + apr_itoa(r->pool, ratio)); + } + else { + apr_table_setn(r->notes, conf->note_ratio_name, "-"); + } + } + APR_BUCKET_REMOVE(e); APR_BRIGADE_INSERT_TAIL(ctx->bb, e); @@ -492,6 +553,9 @@ static void register_hooks(apr_pool_t *p) } static const command_rec cmds[] = { + AP_INIT_TAKE12("BrotliFilterNote", set_filter_note, + NULL, RSRC_CONF, + "Set a note to report on compression ratio"), AP_INIT_TAKE1("BrotliCompressionQuality", set_compression_quality, NULL, RSRC_CONF, "Compression quality between 0 and 11 (higher quality means " -- 2.40.0