You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by zw...@apache.org on 2013/10/27 22:36:45 UTC

[20/50] [abbrv] git commit: TS-2291: Add remap_state plugin to experimental.

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/5.0.x
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");
+}