diff --git a/doc/admin-guide/plugins/stats_over_http.en.rst b/doc/admin-guide/plugins/stats_over_http.en.rst index 93d82422341..f779dd460fc 100644 --- a/doc/admin-guide/plugins/stats_over_http.en.rst +++ b/doc/admin-guide/plugins/stats_over_http.en.rst @@ -41,7 +41,11 @@ default URL:: where host and port is the hostname/IP and port number of the server. +This plugin can also run as a remap plugin with an optional stats over http config file as a parameter:: + map / http://target @plugin=stats_over_http.so @pparam=config.file + +Much like the global version this pparam can also be the path to be used on the remap in order to get the stats Plugin Options ============== diff --git a/plugins/stats_over_http/stats_over_http.cc b/plugins/stats_over_http/stats_over_http.cc index cc20925202c..636005a37c9 100644 --- a/plugins/stats_over_http/stats_over_http.cc +++ b/plugins/stats_over_http/stats_over_http.cc @@ -43,6 +43,7 @@ #include #include +#include #include "swoc/TextView.h" #include "tscore/ink_config.h" #include @@ -653,7 +654,7 @@ stats_dostuff(TSCont contp, TSEvent event, void *edata) } static int -stats_origin(TSCont contp, TSEvent /* event ATS_UNUSED */, void *edata) +stats_origin(config_t *this_config, TSEvent /* event ATS_UNUSED */, void *edata, bool is_remap) { TSCont icontp; stats_state *my_state; @@ -670,7 +671,7 @@ stats_origin(TSCont contp, TSEvent /* event ATS_UNUSED */, void *edata) bool path_had_explicit_format = false; Dbg(dbg_ctl, "in the read stuff"); - config = get_config(contp); + config = this_config; if (TSHttpTxnClientReqGet(txnp, &reqp, &hdr_loc) != TS_SUCCESS) { goto cleanup; @@ -783,6 +784,7 @@ stats_origin(TSCont contp, TSEvent /* event ATS_UNUSED */, void *edata) TSContDataSet(icontp, my_state); TSHttpTxnIntercept(icontp, txnp); + goto cleanup; notforme: @@ -800,10 +802,54 @@ stats_origin(TSCont contp, TSEvent /* event ATS_UNUSED */, void *edata) if (accept_encoding_field) { TSHandleMLocRelease(reqp, TS_NULL_MLOC, accept_encoding_field); } - TSHttpTxnReenable(txnp, reenable); + if (!is_remap) { + TSHttpTxnReenable(txnp, reenable); + } + return 0; } +static int +stats_origin_global_wrapper(TSCont contp, TSEvent, void *edata) +{ + config_t *config = get_config(contp); + return stats_origin(config, TS_EVENT_NONE, edata, false); +} + +TSReturnCode +TSRemapInit(TSRemapInterface *api_info, char *errbuf, int errbuf_size) +{ + CHECK_REMAP_API_COMPATIBILITY(api_info, errbuf, errbuf_size); + return TS_SUCCESS; +} + +TSReturnCode +TSRemapNewInstance(int argc, char *argv[], void **instance, char * /* errBuf ATS_UNUSED */, int /* errBufSize ATS_UNUSED */) +{ + config_holder_t *config_holder; + config_holder = new_config_holder(argc > 1 ? argv[2] : nullptr); + *instance = static_cast(config_holder); + /* Path was not set during load, so the param was not a config file, we also + have an argument so it must be the path, set it here. Otherwise if no argument + then use the default _stats path */ + if ((config_holder->config != nullptr) && (config_holder->config->stats_path.empty()) && (argc > 1) && + (config_holder->config_path == nullptr)) { + config_holder->config->stats_path = argv[2] + ('/' == argv[2][0] ? 1 : 0); + } else if ((config_holder->config != nullptr) && (config_holder->config->stats_path.empty())) { + config_holder->config->stats_path = DEFAULT_URL_PATH; + } + return TS_SUCCESS; +} + +TSRemapStatus +TSRemapDoRemap(void *id, TSHttpTxn rh, TSRemapRequestInfo * /* ATS_UNUSED */) +{ + config_holder_t *configh = static_cast(id); + stats_origin(configh->config, TS_EVENT_NONE, rh, true); + + return TSREMAP_NO_REMAP; +} + void TSPluginInit(int argc, const char *argv[]) { @@ -860,7 +906,7 @@ TSPluginInit(int argc, const char *argv[]) /* Create a continuation with a mutex as there is a shared global structure containing the headers to add */ - main_cont = TSContCreate(stats_origin, nullptr); + main_cont = TSContCreate(stats_origin_global_wrapper, nullptr); TSContDataSet(main_cont, (void *)config_holder); TSHttpHookAdd(TS_HTTP_READ_REQUEST_HDR_HOOK, main_cont); @@ -971,6 +1017,13 @@ delete_config(config_t *config) TSfree(config); } +void +TSRemapDeleteInstance(void *ih) +{ + config_holder_t *configh = static_cast(ih); + delete_config(configh->config); +} + // standard api below... static config_t * get_config(TSCont cont)