Hi Phil, - please check jenkins, this is broken on a couple of platforms - any chance of documentation for this? - do you have a plan to resolve this plugin with channel_stats?
On Oct 20, 2013, at 12:23 PM, sor...@apache.org wrote: > Updated Branches: > refs/heads/master 2c3f7c5e9 -> c3518560e > > > TS-2291: Add remap_state plugin to experimental. > > > Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo > Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/c3518560 > Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/c3518560 > Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/c3518560 > > Branch: refs/heads/master > Commit: c3518560e3ca80b870cd24a99b1bb54179cfa980 > Parents: 2c3f7c5 > Author: Phil Sorber <sor...@apache.org> > Authored: Sun Oct 20 13:22:56 2013 -0600 > Committer: Phil Sorber <sor...@apache.org> > Committed: Sun Oct 20 13:22:56 2013 -0600 > > ---------------------------------------------------------------------- > CHANGES | 2 + > NOTICE | 8 +- > configure.ac | 1 + > plugins/experimental/Makefile.am | 3 +- > plugins/experimental/remap_stats/Makefile.am | 21 ++ > plugins/experimental/remap_stats/remap_stats.c | 329 ++++++++++++++++++++ > 6 files changed, 362 insertions(+), 2 deletions(-) > ---------------------------------------------------------------------- > > > http://git-wip-us.apache.org/repos/asf/trafficserver/blob/c3518560/CHANGES > ---------------------------------------------------------------------- > diff --git a/CHANGES b/CHANGES > index 1446547..30c1354 100644 > --- a/CHANGES > +++ b/CHANGES > @@ -1,6 +1,8 @@ > -*- coding: utf-8 -*- > Changes with Apache Traffic Server 4.1.0 > > + *) [TS-2291] Add remap_state plugin to experimental. > + > *) [TS-2242] Update core plugins' support_email and vendor_name for > consistency. > > > http://git-wip-us.apache.org/repos/asf/trafficserver/blob/c3518560/NOTICE > ---------------------------------------------------------------------- > diff --git a/NOTICE b/NOTICE > index b486b5e..55084b6 100644 > --- a/NOTICE > +++ b/NOTICE > @@ -6,6 +6,7 @@ This product includes software developed at > - Yahoo! Inc > - Network Geographics (http://network-geographics.com) > - OmniTI > + - Comcast > > ~~~ > > @@ -42,4 +43,9 @@ Copyright (C) 2012 GoDaddy. > ~~~ > > lib/atscppapi developed by LinkedIn > -Copyright (c) 2013 LinkedIn > \ No newline at end of file > +Copyright (c) 2013 LinkedIn > + > +~~~ > + > +remap_stats plugin developed by Comcast. > +Copyright (C) 2013 Comcast > > http://git-wip-us.apache.org/repos/asf/trafficserver/blob/c3518560/configure.ac > ---------------------------------------------------------------------- > diff --git a/configure.ac b/configure.ac > index bb2f373..439a6e1 100644 > --- a/configure.ac > +++ b/configure.ac > @@ -1896,6 +1896,7 @@ AC_CONFIG_FILES([ > plugins/experimental/spdy/Makefile > plugins/experimental/tcp_info/Makefile > plugins/experimental/healthchecks/Makefile > + plugins/experimental/remap_stats/Makefile > plugins/gzip/Makefile > plugins/libloader/Makefile > plugins/header_filter/Makefile > > http://git-wip-us.apache.org/repos/asf/trafficserver/blob/c3518560/plugins/experimental/Makefile.am > ---------------------------------------------------------------------- > diff --git a/plugins/experimental/Makefile.am > b/plugins/experimental/Makefile.am > index bb97af1..eb807f8 100644 > --- a/plugins/experimental/Makefile.am > +++ b/plugins/experimental/Makefile.am > @@ -27,5 +27,6 @@ SUBDIRS = \ > channel_stats \ > authproxy \ > geoip_acl \ > - healthchecks > + healthchecks \ > + remap_stats > endif > > http://git-wip-us.apache.org/repos/asf/trafficserver/blob/c3518560/plugins/experimental/remap_stats/Makefile.am > ---------------------------------------------------------------------- > diff --git a/plugins/experimental/remap_stats/Makefile.am > b/plugins/experimental/remap_stats/Makefile.am > new file mode 100644 > index 0000000..4033fa4 > --- /dev/null > +++ b/plugins/experimental/remap_stats/Makefile.am > @@ -0,0 +1,21 @@ > +# Licensed to the Apache Software Foundation (ASF) under one > +# or more contributor license agreements. See the NOTICE file > +# distributed with this work for additional information > +# regarding copyright ownership. The ASF licenses this file > +# to you under the Apache License, Version 2.0 (the > +# "License"); you may not use this file except in compliance > +# with the License. You may obtain a copy of the License at > +# > +# http://www.apache.org/licenses/LICENSE-2.0 > +# > +# Unless required by applicable law or agreed to in writing, software > +# distributed under the License is distributed on an "AS IS" BASIS, > +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. > +# See the License for the specific language governing permissions and > +# limitations under the License. > + > +include $(top_srcdir)/build/plugins.mk > + > +pkglib_LTLIBRARIES = remap_stats.la > +remap_stats_la_SOURCES = remap_stats.c > +remap_stats_la_LDFLAGS = $(TS_PLUGIN_LDFLAGS) > > http://git-wip-us.apache.org/repos/asf/trafficserver/blob/c3518560/plugins/experimental/remap_stats/remap_stats.c > ---------------------------------------------------------------------- > diff --git a/plugins/experimental/remap_stats/remap_stats.c > b/plugins/experimental/remap_stats/remap_stats.c > new file mode 100644 > index 0000000..23c93cd > --- /dev/null > +++ b/plugins/experimental/remap_stats/remap_stats.c > @@ -0,0 +1,329 @@ > +/** @file > + > + @section license License > + > + Licensed to the Apache Software Foundation (ASF) under one > + or more contributor license agreements. See the NOTICE file > + distributed with this work for additional information > + regarding copyright ownership. The ASF licenses this file > + to you under the Apache License, Version 2.0 (the > + "License"); you may not use this file except in compliance > + with the License. You may obtain a copy of the License at > + > + http://www.apache.org/licenses/LICENSE-2.0 > + > + Unless required by applicable law or agreed to in writing, software > + distributed under the License is distributed on an "AS IS" BASIS, > + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. > + See the License for the specific language governing permissions and > + limitations under the License. > + */ > + > +#include "ink_config.h" > +#include "ink_defs.h" > + > +#include "ts/ts.h" > +#include <stdbool.h> > +#include <string.h> > +#include <stdio.h> > +#include <getopt.h> > +#include <search.h> > + > +#define PLUGIN_NAME "remap_stats" > +#define DEBUG_TAG PLUGIN_NAME > + > +typedef struct > +{ > + bool post_remap_host; > + int txn_slot; > + TSStatPersistence persist_type; > + TSMutex stat_creation_mutex; > +} config_t; > + > +typedef struct > +{ > + char *hostname; > + bool remap_success; > +} txn_data_t; > + > +static void > +stat_add(char *name, TSMgmtInt amount, TSStatPersistence persist_type, > TSMutex create_mutex) > +{ > + int stat_id = -1, *statp; > + ENTRY search, *result = NULL; > + static __thread struct hsearch_data stat_cache; > + static __thread bool hash_init = false; > + > + if (unlikely(!hash_init)) > + { > + hcreate_r(TS_MAX_API_STATS << 1, &stat_cache); > + hash_init = true; > + TSDebug(DEBUG_TAG, "stat cache hash init"); > + } > + > + search.key = name; > + hsearch_r(search, FIND, &result, &stat_cache); > + > + if (unlikely(result == NULL)) > + { > + // This is an unlikely path because we most likely have the stat > cached > + // so this mutex won't be much overhead and it fixes a race condition > + // in the RecCore. Hopefully this can be removed in the future. > + TSMutexLock(create_mutex); > + if (TS_ERROR == TSStatFindName((const char *) name, &stat_id)) > + { > + stat_id = TSStatCreate((const char *) name, > TS_RECORDDATATYPE_INT, persist_type, TS_STAT_SYNC_SUM); > + if (stat_id == TS_ERROR) > + TSDebug(DEBUG_TAG, "Error creating stat_name: %s", name); > + else > + TSDebug(DEBUG_TAG, "Created stat_name: %s stat_id: %d", > name, stat_id); > + } > + TSMutexUnlock(create_mutex); > + > + search.key = TSstrdup(name); > + statp = TSmalloc(sizeof(int)); > + *statp = stat_id; > + search.data = (void *) statp; > + hsearch_r(search, ENTER, &result, &stat_cache); > + TSDebug(DEBUG_TAG, "Cached stat_name: %s stat_id: %d", name, > stat_id); > + } > + else > + stat_id = *((int *) result->data); > + > + if (likely(stat_id >= 0)) > + TSStatIntIncrement(stat_id, amount); > + else > + TSDebug(DEBUG_TAG, "stat error! stat_name: %s stat_id: %d", name, > stat_id); > +} > + > +static char * > +get_effective_host(TSHttpTxn txn) > +{ > + char *effective_url, *tmp; > + const char *host; > + int len; > + TSMBuffer buf; > + TSMLoc url_loc; > + > + effective_url = TSHttpTxnEffectiveUrlStringGet(txn, &len); > + buf = TSMBufferCreate(); > + TSUrlCreate(buf, &url_loc); > + tmp = effective_url; > + TSUrlParse(buf, url_loc, (const char **) (&tmp), (const char *) > (effective_url + len)); > + TSfree(effective_url); > + host = TSUrlHostGet(buf, url_loc, &len); > + tmp = TSstrndup(host, len); > + TSHandleMLocRelease(buf, TS_NULL_MLOC, url_loc); > + TSMBufferDestroy(buf); > + return tmp; > +} > + > +static char * > +create_stat_name(char *hostname, char *basename) > +{ > + char *stat_name; > + size_t stat_len; > + > + stat_len = strlen(hostname) + strlen(basename) + strlen(PLUGIN_NAME) + 3 > + strlen("plugin."); > + stat_name = TSmalloc(stat_len * sizeof(char)); > + snprintf(stat_name, stat_len, "plugin.%s.%s.%s", PLUGIN_NAME, hostname, > basename); > + return stat_name; > +} > + > +static int > +handle_read_req_hdr(TSCont cont, TSEvent event, void *edata) > +{ > + TSHttpTxn txn = (TSHttpTxn) edata; > + config_t *config; > + txn_data_t *txnd; > + > + config = (config_t *) TSContDataGet(cont); > + txnd = TSmalloc(sizeof(txn_data_t)); > + txnd->remap_success = false; > + txnd->hostname = get_effective_host(txn); > + TSHttpTxnArgSet(txn, config->txn_slot, (void *) txnd); > + > + TSHttpTxnReenable(txn, TS_EVENT_HTTP_CONTINUE); > + TSDebug(DEBUG_TAG, "Read Req Handler Finished"); > + return 0; > +} > + > +static int > +handle_post_remap(TSCont cont, TSEvent event, void *edata) > +{ > + TSHttpTxn txn = (TSHttpTxn) edata; > + config_t *config; > + txn_data_t *txnd; > + > + config = (config_t *) TSContDataGet(cont); > + > + if (config->post_remap_host) > + { > + txnd = TSmalloc(sizeof(txn_data_t)); > + txnd->remap_success = true; > + txnd->hostname = NULL; > + TSHttpTxnArgSet(txn, config->txn_slot, (void *) txnd); > + } > + else > + { > + txnd = (txn_data_t *) TSHttpTxnArgGet(txn, config->txn_slot); > + txnd->remap_success = true; > + } > + > + TSHttpTxnReenable(txn, TS_EVENT_HTTP_CONTINUE); > + TSDebug(DEBUG_TAG, "Post Remap Handler Finished"); > + return 0; > +} > + > +static int > +handle_txn_close(TSCont cont, TSEvent event, void *edata) > +{ > + TSHttpTxn txn = (TSHttpTxn) edata; > + config_t *config; > + txn_data_t *txnd; > + TSHttpStatus status_code = 0; > + TSMBuffer buf; > + TSMLoc hdr_loc; > + uint64_t out_bytes, in_bytes; > + char *remap, *stat_name; > + > + config = (config_t *) TSContDataGet(cont); > + txnd = (txn_data_t *) TSHttpTxnArgGet(txn, config->txn_slot); > + > + if (txnd) > + { > + if (txnd->remap_success) > + { > + if (!config->post_remap_host) > + remap = txnd->hostname; > + else > + remap = get_effective_host(txn); > + > + if (!remap) > + remap = TSstrdup("unknown"); > + > + in_bytes = TSHttpTxnClientReqHdrBytesGet(txn); > + in_bytes += TSHttpTxnClientReqBodyBytesGet(txn); > + > + stat_name = create_stat_name(remap, "in_bytes"); > + stat_add(stat_name, (TSMgmtInt) in_bytes, config->persist_type, > config->stat_creation_mutex); > + TSfree(stat_name); > + > + out_bytes = TSHttpTxnClientRespHdrBytesGet(txn); > + out_bytes += TSHttpTxnClientRespBodyBytesGet(txn); > + > + stat_name = create_stat_name(remap, "out_bytes"); > + stat_add(stat_name, (TSMgmtInt) out_bytes, config->persist_type, > config->stat_creation_mutex); > + TSfree(stat_name); > + > + if (TSHttpTxnClientRespGet(txn, &buf, &hdr_loc) == TS_SUCCESS) > + { > + status_code = TSHttpHdrStatusGet(buf, hdr_loc); > + TSHandleMLocRelease(buf, TS_NULL_MLOC, hdr_loc); > + > + if ((status_code >= 200) && (status_code <= 299)) > + stat_name = create_stat_name(remap, "status_2xx"); > + else if ((status_code >= 300) && (status_code <= 399)) > + stat_name = create_stat_name(remap, "status_3xx"); > + else if ((status_code >= 400) && (status_code <= 499)) > + stat_name = create_stat_name(remap, "status_4xx"); > + else if ((status_code >= 500) && (status_code <= 599)) > + stat_name = create_stat_name(remap, "status_5xx"); > + else > + stat_name = create_stat_name(remap, "status_other"); > + > + stat_add(stat_name, 1, config->persist_type, > config->stat_creation_mutex); > + TSfree(stat_name); > + } > + else > + { > + stat_name = create_stat_name(remap, "status_unknown"); > + stat_add(stat_name, 1, config->persist_type, > config->stat_creation_mutex); > + TSfree(stat_name); > + } > + > + TSfree(remap); > + > + } > + else if (txnd->hostname) > + TSfree(txnd->hostname); > + > + TSfree(txnd); > + } > + > + TSHttpTxnReenable(txn, TS_EVENT_HTTP_CONTINUE); > + TSDebug(DEBUG_TAG, "Handler Finished"); > + return 0; > +} > + > +void > +TSPluginInit (int argc, const char *argv[]) > +{ > + TSPluginRegistrationInfo info; > + TSCont pre_remap_cont, post_remap_cont, global_cont; > + config_t *config; > + > + info.plugin_name = PLUGIN_NAME; > + info.vendor_name = "Apache Software Foundation"; > + info.support_email = "dev@trafficserver.apache.org"; > + > + if (TSPluginRegister(TS_SDK_VERSION_3_0 , &info) != TS_SUCCESS) > + { > + TSError("Plugin registration failed."); > + return; > + } > + else > + TSDebug(DEBUG_TAG, "Plugin registration succeeded."); > + > + config = TSmalloc(sizeof(config_t)); > + config->post_remap_host = false; > + config->persist_type = TS_STAT_NON_PERSISTENT; > + config->stat_creation_mutex = TSMutexCreate(); > + > + if (argc > 1) > + { > + int c; > + optind = 1; > + static const struct option longopts[] = { > + { "post-remap-host", no_argument, NULL, 'P' }, > + { "persistent", no_argument, NULL, 'p' }, > + { NULL, 0, NULL, 0 } > + }; > + > + while ((c = getopt_long(argc, (char * const*) argv, "Pp", longopts, > NULL)) != -1) > + { > + switch (c) > + { > + case 'P': > + config->post_remap_host = true; > + TSDebug(DEBUG_TAG, "Using post remap hostname"); > + break; > + case 'p': > + config->persist_type = TS_STAT_PERSISTENT; > + TSDebug(DEBUG_TAG, "Using persistent stats"); > + break; > + default: > + break; > + } > + } > + } > + > + TSHttpArgIndexReserve(PLUGIN_NAME, "txn data", &(config->txn_slot)); > + > + if (!config->post_remap_host) > + { > + pre_remap_cont = TSContCreate(handle_read_req_hdr, NULL); > + TSContDataSet(pre_remap_cont, (void *) config); > + TSHttpHookAdd(TS_HTTP_READ_REQUEST_HDR_HOOK, pre_remap_cont); > + } > + > + post_remap_cont = TSContCreate(handle_post_remap, NULL); > + TSContDataSet(post_remap_cont, (void *) config); > + TSHttpHookAdd(TS_HTTP_POST_REMAP_HOOK, post_remap_cont); > + > + global_cont = TSContCreate(handle_txn_close, NULL); > + TSContDataSet(global_cont, (void *) config); > + TSHttpHookAdd(TS_HTTP_TXN_CLOSE_HOOK, global_cont); > + > + TSDebug(DEBUG_TAG, "Init complete"); > +} >