You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@trafficserver.apache.org by James Peach <jp...@apache.org> on 2013/10/22 05:44:55 UTC

Re: git commit: TS-2291: Add remap_state plugin to experimental.

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, sorber@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 <so...@apache.org>
> Authored: Sun Oct 20 13:22:56 2013 -0600
> Committer: Phil Sorber <so...@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");
> +}
>