You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by jp...@apache.org on 2016/01/22 04:23:49 UTC

[01/10] trafficserver git commit: TS-4099: missing proxy.process.http.transaction_counts.errors.empty_hangups

Repository: trafficserver
Updated Branches:
  refs/heads/master 4e2f0b818 -> e7a4dc62a


TS-4099: missing proxy.process.http.transaction_counts.errors.empty_hangups

proxy.process.http.transaction_counts.errors.empty_hangups doesn't
exist, so remove mentions of it and metrics that depend on it.


Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo
Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/4e447564
Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/4e447564
Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/4e447564

Branch: refs/heads/master
Commit: 4e44756457bc2e42a0d15a216750c7328d9425b3
Parents: e454a6e
Author: James Peach <jp...@apache.org>
Authored: Sun Dec 27 17:07:13 2015 -0800
Committer: James Peach <jp...@apache.org>
Committed: Thu Jan 21 18:52:18 2016 -0800

----------------------------------------------------------------------
 proxy/config/metrics.config.default | 78 --------------------------------
 1 file changed, 78 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/4e447564/proxy/config/metrics.config.default
----------------------------------------------------------------------
diff --git a/proxy/config/metrics.config.default b/proxy/config/metrics.config.default
index b380225..f5559d4 100644
--- a/proxy/config/metrics.config.default
+++ b/proxy/config/metrics.config.default
@@ -858,12 +858,6 @@ integer 'proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups' [
   end)
 ]]
 
-integer 'proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups' [[
-  return interval_delta_of_10s(..., function()
-    return proxy.process.http.transaction_counts.errors.empty_hangups
-  end)
-]]
-
 integer 'proxy.node.http.transaction_counts_avg_10s.errors.other' [[
   return interval_delta_of_10s(..., function()
     return proxy.process.http.transaction_counts.errors.other
@@ -886,7 +880,6 @@ float 'proxy.node.http.transaction_frac_avg_10s.hit_fresh' [[
       proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
       proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
       proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
-      proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.other
       )
   end)
@@ -907,7 +900,6 @@ float 'proxy.node.http.transaction_frac_avg_10s.hit_revalidated' [[
       proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
       proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
       proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
-      proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.other
       )
   end)
@@ -928,7 +920,6 @@ float 'proxy.node.http.transaction_frac_avg_10s.miss_cold' [[
       proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
       proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
       proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
-      proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.other
       )
   end)
@@ -948,7 +939,6 @@ float 'proxy.node.http.transaction_frac_avg_10s.miss_changed' [[
     proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
     proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
     proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
-    proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
     proxy.node.http.transaction_counts_avg_10s.errors.other
     )
   end)
@@ -969,7 +959,6 @@ float 'proxy.node.http.transaction_frac_avg_10s.miss_client_no_cache' [[
       proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
       proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
       proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
-      proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.other
       )
   end)
@@ -990,7 +979,6 @@ float 'proxy.node.http.transaction_frac_avg_10s.miss_not_cacheable' [[
       proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
       proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
       proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
-      proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.other
       )
   end)
@@ -1011,7 +999,6 @@ float 'proxy.node.http.transaction_frac_avg_10s.errors.connect_failed' [[
       proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
       proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
       proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
-      proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.other
       )
     end)
@@ -1032,7 +1019,6 @@ float 'proxy.node.http.transaction_frac_avg_10s.errors.aborts' [[
       proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
       proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
       proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
-      proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.other
       )
     end)
@@ -1053,7 +1039,6 @@ float 'proxy.node.http.transaction_frac_avg_10s.errors.possible_aborts' [[
       proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
       proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
       proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
-      proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.other
       )
     end)
@@ -1074,28 +1059,6 @@ float 'proxy.node.http.transaction_frac_avg_10s.errors.pre_accept_hangups' [[
       proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
       proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
       proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
-      proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
-      proxy.node.http.transaction_counts_avg_10s.errors.other
-      )
-    end)
-]]
-
-float 'proxy.node.http.transaction_frac_avg_10s.errors.empty_hangups' [[
-  return interval_of_10s(..., function()
-    return
-      proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups /
-      (
-      proxy.node.http.transaction_counts_avg_10s.hit_fresh                 +
-      proxy.node.http.transaction_counts_avg_10s.hit_revalidated           +
-      proxy.node.http.transaction_counts_avg_10s.miss_cold                 +
-      proxy.node.http.transaction_counts_avg_10s.miss_changed              +
-      proxy.node.http.transaction_counts_avg_10s.miss_client_no_cache      +
-      proxy.node.http.transaction_counts_avg_10s.miss_not_cacheable        +
-      proxy.node.http.transaction_counts_avg_10s.errors.connect_failed     +
-      proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
-      proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
-      proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
-      proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.other
       )
     end)
@@ -1116,7 +1079,6 @@ float 'proxy.node.http.transaction_frac_avg_10s.errors.other' [[
       proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
       proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
       proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
-      proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.other
       )
     end)
@@ -1162,10 +1124,6 @@ integer 'proxy.node.http.transaction_frac_avg_10s.errors.pre_accept_hangups_int_
   return proxy.node.http.transaction_frac_avg_10s.errors.pre_accept_hangups * 100
 ]]
 
-integer 'proxy.node.http.transaction_frac_avg_10s.errors.empty_hangups_int_pct' [[
-  return proxy.node.http.transaction_frac_avg_10s.errors.empty_hangups * 100
-]]
-
 integer 'proxy.node.http.transaction_frac_avg_10s.errors.other_int_pct' [[
   return proxy.node.http.transaction_frac_avg_10s.errors.other * 100
 ]]
@@ -1189,7 +1147,6 @@ integer 'proxy.node.http.transaction_msec_avg_10s.hit_fresh' [[
       proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
       proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
       proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
-      proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.other
       )
     end)
@@ -1214,7 +1171,6 @@ integer 'proxy.node.http.transaction_msec_avg_10s.hit_revalidated' [[
       proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
       proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
       proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
-      proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.other
       )
     end)
@@ -1239,7 +1195,6 @@ integer 'proxy.node.http.transaction_msec_avg_10s.miss_cold' [[
       proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
       proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
       proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
-      proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.other
       )
     end)
@@ -1264,7 +1219,6 @@ integer 'proxy.node.http.transaction_msec_avg_10s.miss_changed' [[
       proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
       proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
       proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
-      proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.other
       )
     end)
@@ -1289,7 +1243,6 @@ integer 'proxy.node.http.transaction_msec_avg_10s.miss_client_no_cache' [[
       proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
       proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
       proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
-      proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.other
       )
     end)
@@ -1314,7 +1267,6 @@ integer 'proxy.node.http.transaction_msec_avg_10s.miss_not_cacheable' [[
       proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
       proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
       proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
-      proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.other
       )
     end)
@@ -1339,7 +1291,6 @@ integer 'proxy.node.http.transaction_msec_avg_10s.errors.connect_failed' [[
       proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
       proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
       proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
-      proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.other
       )
     end)
@@ -1364,7 +1315,6 @@ integer 'proxy.node.http.transaction_msec_avg_10s.errors.aborts' [[
       proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
       proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
       proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
-      proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.other
       )
     end)
@@ -1389,7 +1339,6 @@ integer 'proxy.node.http.transaction_msec_avg_10s.errors.possible_aborts' [[
       proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
       proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
       proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
-      proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.other
       )
     end)
@@ -1414,32 +1363,6 @@ integer 'proxy.node.http.transaction_msec_avg_10s.errors.pre_accept_hangups' [[
       proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
       proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
       proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
-      proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
-      proxy.node.http.transaction_counts_avg_10s.errors.other
-      )
-    end)
-]]
-
-integer 'proxy.node.http.transaction_msec_avg_10s.errors.empty_hangups' [[
-  local self = ...
-  return interval_of_10s(self, function()
-    return
-      sec_to_msec              *
-      delta_of(self, function()
-        return proxy.process.http.transaction_totaltime.errors.empty_hangups
-      end) /
-      (
-      proxy.node.http.transaction_counts_avg_10s.hit_fresh                 +
-      proxy.node.http.transaction_counts_avg_10s.hit_revalidated           +
-      proxy.node.http.transaction_counts_avg_10s.miss_cold                 +
-      proxy.node.http.transaction_counts_avg_10s.miss_changed              +
-      proxy.node.http.transaction_counts_avg_10s.miss_client_no_cache      +
-      proxy.node.http.transaction_counts_avg_10s.miss_not_cacheable        +
-      proxy.node.http.transaction_counts_avg_10s.errors.connect_failed     +
-      proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
-      proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
-      proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
-      proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.other
       )
     end)
@@ -1464,7 +1387,6 @@ integer 'proxy.node.http.transaction_msec_avg_10s.errors.other' [[
       proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
       proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
       proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
-      proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.other
       )
     end)


[07/10] trafficserver git commit: TS-4099: add generic Lua bindings for metrics

Posted by jp...@apache.org.
TS-4099: add generic Lua bindings for metrics

This adds binding for metrics such that metric value can be queried
from within Lua by using their full names.


Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo
Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/e9649d2c
Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/e9649d2c
Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/e9649d2c

Branch: refs/heads/master
Commit: e9649d2c2e31c0b65f42e3db9c5e354c630b53a9
Parents: 5942c42
Author: James Peach <jp...@apache.org>
Authored: Tue Nov 24 16:08:25 2015 -0800
Committer: James Peach <jp...@apache.org>
Committed: Thu Jan 21 18:52:18 2016 -0800

----------------------------------------------------------------------
 lib/bindings/Makefile.am |   2 +
 lib/bindings/metrics.cc  | 201 ++++++++++++++++++++++++++++++++++++++++++
 lib/bindings/metrics.h   |  33 +++++++
 3 files changed, 236 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e9649d2c/lib/bindings/Makefile.am
----------------------------------------------------------------------
diff --git a/lib/bindings/Makefile.am b/lib/bindings/Makefile.am
index 661411c..3ea6f63 100644
--- a/lib/bindings/Makefile.am
+++ b/lib/bindings/Makefile.am
@@ -33,6 +33,8 @@ libbindings_la_SOURCES = \
   bindings.h \
   lua.cc \
   lua.h \
+  metrics.cc \
+  metrics.h \
   repl.cc \
   repl.h
 

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e9649d2c/lib/bindings/metrics.cc
----------------------------------------------------------------------
diff --git a/lib/bindings/metrics.cc b/lib/bindings/metrics.cc
new file mode 100644
index 0000000..66dbacf
--- /dev/null
+++ b/lib/bindings/metrics.cc
@@ -0,0 +1,201 @@
+/** @file
+
+  Lua bindings for librecords.
+
+  @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 "bindings.h"
+#include "metrics.h"
+#include "P_RecCore.h"
+#include "ts/ink_memory.h"
+#include <map>
+
+#define BINDING "lua.metrics"
+
+struct metrics_binding {
+  static metrics_binding *check(lua_State *L, int index);
+
+  typedef std::map<std::string, int> ref_map;
+
+  ats_scoped_str prefix;
+  size_t prefixlen;
+  ref_map refs;
+};
+
+metrics_binding *
+metrics_binding::check(lua_State *L, int index)
+{
+  metrics_binding *m;
+
+  luaL_checktype(L, index, LUA_TUSERDATA);
+  m = (metrics_binding *)luaL_checkudata(L, index, BINDING);
+  if (m == NULL) {
+    luaL_typerror(L, index, "userdata");
+  }
+
+  return m;
+}
+
+static bool
+metrics_record_exists(const char *name)
+{
+  RecT rec_type;
+  return RecGetRecordType(name, &rec_type) == REC_ERR_OKAY;
+}
+
+// Push the value of a record onto the Lua stack.
+static void
+metrics_push_record(const RecRecord *rec, void *ptr)
+{
+  lua_State *L = (lua_State *)ptr;
+
+  ink_assert(REC_TYPE_IS_STAT(rec->rec_type));
+
+  switch (rec->data_type) {
+  case RECD_INT: /* fallthru */
+  case RECD_COUNTER:
+    lua_pushinteger(L, rec->data.rec_int);
+    break;
+  case RECD_FLOAT:
+    lua_pushnumber(L, rec->data.rec_float);
+    break;
+  case RECD_STRING:
+    lua_pushlstring(L, rec->data.rec_string, strlen(rec->data.rec_string));
+    break;
+  default:
+    lua_pushnil(L);
+  }
+}
+
+// Return the value of a metric, relative to the bound prefix.
+static int
+metrics_index(lua_State *L)
+{
+  metrics_binding *m = metrics_binding::check(L, 1);
+  metrics_binding::ref_map::iterator ptr;
+
+  const char *key;
+  size_t len;
+
+  key = luaL_checklstring(L, 2, &len);
+  ink_release_assert(key != NULL && len != 0);
+
+  // First, check whether we have a reference stored for this key.
+  ptr = m->refs.find(std::string(key, len));
+  if (ptr != m->refs.end()) {
+    // We have a ref, so push the saved table reference to the stack.
+    lua_rawgeti(L, LUA_REGISTRYINDEX, ptr->second);
+  } else {
+    char name[m->prefixlen + sizeof(".") + len];
+
+    snprintf(name, sizeof(name), "%s.%.*s", m->prefix.get(), (int)len, key);
+
+    // Push the indexed record value, or nil if there is nothing there.
+    if (RecLookupRecord(name, metrics_push_record, L) != REC_ERR_OKAY) {
+      lua_pushnil(L);
+    }
+  }
+
+  return 1;
+}
+
+static int
+metrics_newindex(lua_State *L)
+{
+  // The stack now looks like:
+  //  1   the table value (userdata)
+  //  2   key to index (string)
+  //  3   value to insert (should be a table)
+
+  metrics_binding *m = metrics_binding::check(L, 1);
+  const char *key;
+  size_t len;
+  metrics_binding::ref_map::iterator ptr;
+
+  key = luaL_checklstring(L, 2, &len);
+  switch (lua_type(L, 3)) {
+  case LUA_TUSERDATA:
+    metrics_binding::check(L, 3);
+    break;
+  case LUA_TTABLE:
+    break;
+  default:
+    luaL_typerror(L, 3, "userdata or table");
+  }
+
+  char name[m->prefixlen + sizeof(".") + len];
+
+  snprintf(name, sizeof(name), "%s.%.*s", m->prefix.get(), (int)len, key);
+
+  // If this index is already a record, don't overwrite it.
+  if (metrics_record_exists(name)) {
+    return 0;
+  }
+
+  ptr = m->refs.find(std::string(key, len));
+  if (ptr != m->refs.end()) {
+    // Remove the previously saved reference.
+    luaL_unref(L, LUA_REGISTRYINDEX, ptr->second);
+  }
+
+  // Pop the top of the stack into a reference that we store in the refmap.
+  lua_pushvalue(L, 3);
+  m->refs[std::string(key, len)] = luaL_ref(L, LUA_REGISTRYINDEX);
+
+  return 0;
+}
+
+static int
+metrics_gc(lua_State *L)
+{
+  metrics_binding *m = metrics_binding::check(L, 1);
+
+  // Clean up any references we stashed.
+  for (metrics_binding::ref_map::iterator ptr = m->refs.begin(); ptr != m->refs.end(); ++ptr) {
+    luaL_unref(L, LUA_REGISTRYINDEX, ptr->second);
+  }
+
+  m->~metrics_binding();
+  return 0;
+}
+
+int
+lua_metrics_new(const char *prefix, lua_State *L)
+{
+  metrics_binding *m = lua_newuserobject<metrics_binding>(L);
+
+  Debug("lua", "new metrics binding for prefix %s", prefix);
+  m->prefix = ats_strdup(prefix);
+  m->prefixlen = strlen(prefix);
+
+  luaL_getmetatable(L, BINDING);
+  lua_setmetatable(L, -2);
+
+  // Leave the userdata on the stack.
+  return 1;
+}
+
+void
+lua_metrics_register(lua_State *L)
+{
+  static const luaL_reg metatable[] = {{"__gc", metrics_gc}, {"__index", metrics_index}, {"__newindex", metrics_newindex}, {0, 0}};
+
+  BindingInstance::register_metatable(L, BINDING, metatable);
+}

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e9649d2c/lib/bindings/metrics.h
----------------------------------------------------------------------
diff --git a/lib/bindings/metrics.h b/lib/bindings/metrics.h
new file mode 100644
index 0000000..e0d39ac
--- /dev/null
+++ b/lib/bindings/metrics.h
@@ -0,0 +1,33 @@
+/** @file
+ *
+ *  A brief file description
+ *
+ *  @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.
+ */
+
+#ifndef METRICS_H_FED1F5EA_9EDE_48E6_B05A_5DCAFD8DC319
+#define METRICS_H_FED1F5EA_9EDE_48E6_B05A_5DCAFD8DC319
+
+// Create a new metrics binding userdata object.
+int lua_metrics_new(const char *prefix, lua_State *L);
+
+// Register metrics binding type metatable.
+void lua_metrics_register(lua_State *L);
+
+#endif /* METRICS_H_FED1F5EA_9EDE_48E6_B05A_5DCAFD8DC319 */


[06/10] trafficserver git commit: TS-4099: missing proxy.process.http.transaction_counts.errors.early_hangups

Posted by jp...@apache.org.
TS-4099: missing proxy.process.http.transaction_counts.errors.early_hangups

proxy.process.http.transaction_counts.errors.early_hangups doesn't
exist, so remove mentions of it and metrics that depend on it.


Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo
Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/e454a6e2
Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/e454a6e2
Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/e454a6e2

Branch: refs/heads/master
Commit: e454a6e271a56bb55be988ac7771e7d73c94c026
Parents: b8539d3
Author: James Peach <jp...@apache.org>
Authored: Sun Dec 27 17:04:52 2015 -0800
Committer: James Peach <jp...@apache.org>
Committed: Thu Jan 21 18:52:18 2016 -0800

----------------------------------------------------------------------
 proxy/config/metrics.config.default | 82 --------------------------------
 1 file changed, 82 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e454a6e2/proxy/config/metrics.config.default
----------------------------------------------------------------------
diff --git a/proxy/config/metrics.config.default b/proxy/config/metrics.config.default
index 77a2bd2..b380225 100644
--- a/proxy/config/metrics.config.default
+++ b/proxy/config/metrics.config.default
@@ -858,12 +858,6 @@ integer 'proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups' [
   end)
 ]]
 
-integer 'proxy.node.http.transaction_counts_avg_10s.errors.early_hangups' [[
-  return interval_delta_of_10s(..., function()
-    return proxy.process.http.transaction_counts.errors.early_hangups
-  end)
-]]
-
 integer 'proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups' [[
   return interval_delta_of_10s(..., function()
     return proxy.process.http.transaction_counts.errors.empty_hangups
@@ -892,7 +886,6 @@ float 'proxy.node.http.transaction_frac_avg_10s.hit_fresh' [[
       proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
       proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
       proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
-      proxy.node.http.transaction_counts_avg_10s.errors.early_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.other
       )
@@ -914,7 +907,6 @@ float 'proxy.node.http.transaction_frac_avg_10s.hit_revalidated' [[
       proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
       proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
       proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
-      proxy.node.http.transaction_counts_avg_10s.errors.early_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.other
       )
@@ -936,7 +928,6 @@ float 'proxy.node.http.transaction_frac_avg_10s.miss_cold' [[
       proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
       proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
       proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
-      proxy.node.http.transaction_counts_avg_10s.errors.early_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.other
       )
@@ -957,7 +948,6 @@ float 'proxy.node.http.transaction_frac_avg_10s.miss_changed' [[
     proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
     proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
     proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
-    proxy.node.http.transaction_counts_avg_10s.errors.early_hangups      +
     proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
     proxy.node.http.transaction_counts_avg_10s.errors.other
     )
@@ -979,7 +969,6 @@ float 'proxy.node.http.transaction_frac_avg_10s.miss_client_no_cache' [[
       proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
       proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
       proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
-      proxy.node.http.transaction_counts_avg_10s.errors.early_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.other
       )
@@ -1001,7 +990,6 @@ float 'proxy.node.http.transaction_frac_avg_10s.miss_not_cacheable' [[
       proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
       proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
       proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
-      proxy.node.http.transaction_counts_avg_10s.errors.early_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.other
       )
@@ -1023,7 +1011,6 @@ float 'proxy.node.http.transaction_frac_avg_10s.errors.connect_failed' [[
       proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
       proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
       proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
-      proxy.node.http.transaction_counts_avg_10s.errors.early_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.other
       )
@@ -1045,7 +1032,6 @@ float 'proxy.node.http.transaction_frac_avg_10s.errors.aborts' [[
       proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
       proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
       proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
-      proxy.node.http.transaction_counts_avg_10s.errors.early_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.other
       )
@@ -1067,7 +1053,6 @@ float 'proxy.node.http.transaction_frac_avg_10s.errors.possible_aborts' [[
       proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
       proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
       proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
-      proxy.node.http.transaction_counts_avg_10s.errors.early_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.other
       )
@@ -1089,29 +1074,6 @@ float 'proxy.node.http.transaction_frac_avg_10s.errors.pre_accept_hangups' [[
       proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
       proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
       proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
-      proxy.node.http.transaction_counts_avg_10s.errors.early_hangups      +
-      proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
-      proxy.node.http.transaction_counts_avg_10s.errors.other
-      )
-    end)
-]]
-
-float 'proxy.node.http.transaction_frac_avg_10s.errors.early_hangups' [[
-  return interval_of_10s(..., function()
-    return
-      proxy.node.http.transaction_counts_avg_10s.errors.early_hangups /
-      (
-      proxy.node.http.transaction_counts_avg_10s.hit_fresh                 +
-      proxy.node.http.transaction_counts_avg_10s.hit_revalidated           +
-      proxy.node.http.transaction_counts_avg_10s.miss_cold                 +
-      proxy.node.http.transaction_counts_avg_10s.miss_changed              +
-      proxy.node.http.transaction_counts_avg_10s.miss_client_no_cache      +
-      proxy.node.http.transaction_counts_avg_10s.miss_not_cacheable        +
-      proxy.node.http.transaction_counts_avg_10s.errors.connect_failed     +
-      proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
-      proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
-      proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
-      proxy.node.http.transaction_counts_avg_10s.errors.early_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.other
       )
@@ -1133,7 +1095,6 @@ float 'proxy.node.http.transaction_frac_avg_10s.errors.empty_hangups' [[
       proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
       proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
       proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
-      proxy.node.http.transaction_counts_avg_10s.errors.early_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.other
       )
@@ -1155,7 +1116,6 @@ float 'proxy.node.http.transaction_frac_avg_10s.errors.other' [[
       proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
       proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
       proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
-      proxy.node.http.transaction_counts_avg_10s.errors.early_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.other
       )
@@ -1202,10 +1162,6 @@ integer 'proxy.node.http.transaction_frac_avg_10s.errors.pre_accept_hangups_int_
   return proxy.node.http.transaction_frac_avg_10s.errors.pre_accept_hangups * 100
 ]]
 
-integer 'proxy.node.http.transaction_frac_avg_10s.errors.early_hangups_int_pct' [[
-  return proxy.node.http.transaction_frac_avg_10s.errors.early_hangups * 100
-]]
-
 integer 'proxy.node.http.transaction_frac_avg_10s.errors.empty_hangups_int_pct' [[
   return proxy.node.http.transaction_frac_avg_10s.errors.empty_hangups * 100
 ]]
@@ -1233,7 +1189,6 @@ integer 'proxy.node.http.transaction_msec_avg_10s.hit_fresh' [[
       proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
       proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
       proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
-      proxy.node.http.transaction_counts_avg_10s.errors.early_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.other
       )
@@ -1259,7 +1214,6 @@ integer 'proxy.node.http.transaction_msec_avg_10s.hit_revalidated' [[
       proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
       proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
       proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
-      proxy.node.http.transaction_counts_avg_10s.errors.early_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.other
       )
@@ -1285,7 +1239,6 @@ integer 'proxy.node.http.transaction_msec_avg_10s.miss_cold' [[
       proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
       proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
       proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
-      proxy.node.http.transaction_counts_avg_10s.errors.early_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.other
       )
@@ -1311,7 +1264,6 @@ integer 'proxy.node.http.transaction_msec_avg_10s.miss_changed' [[
       proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
       proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
       proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
-      proxy.node.http.transaction_counts_avg_10s.errors.early_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.other
       )
@@ -1337,7 +1289,6 @@ integer 'proxy.node.http.transaction_msec_avg_10s.miss_client_no_cache' [[
       proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
       proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
       proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
-      proxy.node.http.transaction_counts_avg_10s.errors.early_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.other
       )
@@ -1363,7 +1314,6 @@ integer 'proxy.node.http.transaction_msec_avg_10s.miss_not_cacheable' [[
       proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
       proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
       proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
-      proxy.node.http.transaction_counts_avg_10s.errors.early_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.other
       )
@@ -1389,7 +1339,6 @@ integer 'proxy.node.http.transaction_msec_avg_10s.errors.connect_failed' [[
       proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
       proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
       proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
-      proxy.node.http.transaction_counts_avg_10s.errors.early_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.other
       )
@@ -1415,7 +1364,6 @@ integer 'proxy.node.http.transaction_msec_avg_10s.errors.aborts' [[
       proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
       proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
       proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
-      proxy.node.http.transaction_counts_avg_10s.errors.early_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.other
       )
@@ -1441,7 +1389,6 @@ integer 'proxy.node.http.transaction_msec_avg_10s.errors.possible_aborts' [[
       proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
       proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
       proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
-      proxy.node.http.transaction_counts_avg_10s.errors.early_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.other
       )
@@ -1467,33 +1414,6 @@ integer 'proxy.node.http.transaction_msec_avg_10s.errors.pre_accept_hangups' [[
       proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
       proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
       proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
-      proxy.node.http.transaction_counts_avg_10s.errors.early_hangups      +
-      proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
-      proxy.node.http.transaction_counts_avg_10s.errors.other
-      )
-    end)
-]]
-
-integer 'proxy.node.http.transaction_msec_avg_10s.errors.early_hangups' [[
-  local self = ...
-  return interval_of_10s(self, function()
-    return
-      sec_to_msec              *
-      delta_of(self, function()
-        self proxy.process.http.transaction_totaltime.errors.early_hangups
-      end) /
-      (
-      proxy.node.http.transaction_counts_avg_10s.hit_fresh                 +
-      proxy.node.http.transaction_counts_avg_10s.hit_revalidated           +
-      proxy.node.http.transaction_counts_avg_10s.miss_cold                 +
-      proxy.node.http.transaction_counts_avg_10s.miss_changed              +
-      proxy.node.http.transaction_counts_avg_10s.miss_client_no_cache      +
-      proxy.node.http.transaction_counts_avg_10s.miss_not_cacheable        +
-      proxy.node.http.transaction_counts_avg_10s.errors.connect_failed     +
-      proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
-      proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
-      proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
-      proxy.node.http.transaction_counts_avg_10s.errors.early_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.other
       )
@@ -1519,7 +1439,6 @@ integer 'proxy.node.http.transaction_msec_avg_10s.errors.empty_hangups' [[
       proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
       proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
       proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
-      proxy.node.http.transaction_counts_avg_10s.errors.early_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.other
       )
@@ -1545,7 +1464,6 @@ integer 'proxy.node.http.transaction_msec_avg_10s.errors.other' [[
       proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
       proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
       proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
-      proxy.node.http.transaction_counts_avg_10s.errors.early_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
       proxy.node.http.transaction_counts_avg_10s.errors.other
       )


[02/10] trafficserver git commit: TS-4099: missing proxy.process.http.transaction_counts.errors.errors

Posted by jp...@apache.org.
TS-4099: missing proxy.process.http.transaction_counts.errors.errors

proxy.process.http.transaction_counts.errors.errors doesn't exist,
so replace it with proxy.process.http.transaction_counts.errors.other
where applicable.


Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo
Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/b8539d3c
Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/b8539d3c
Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/b8539d3c

Branch: refs/heads/master
Commit: b8539d3cbcc99d2f87c0ee6ece00028096d9df07
Parents: 1a59001
Author: James Peach <jp...@apache.org>
Authored: Sun Dec 27 17:02:13 2015 -0800
Committer: James Peach <jp...@apache.org>
Committed: Thu Jan 21 18:52:18 2016 -0800

----------------------------------------------------------------------
 proxy/config/metrics.config.default | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/b8539d3c/proxy/config/metrics.config.default
----------------------------------------------------------------------
diff --git a/proxy/config/metrics.config.default b/proxy/config/metrics.config.default
index 0eec83a..77a2bd2 100644
--- a/proxy/config/metrics.config.default
+++ b/proxy/config/metrics.config.default
@@ -870,9 +870,9 @@ integer 'proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups' [[
   end)
 ]]
 
-integer 'proxy.node.http.transaction_counts_avg_10s.errors.errors' [[
+integer 'proxy.node.http.transaction_counts_avg_10s.errors.other' [[
   return interval_delta_of_10s(..., function()
-    return proxy.process.http.transaction_counts.errors.errors
+    return proxy.process.http.transaction_counts.errors.other
   end)
 ]]
 


[04/10] trafficserver git commit: TS-4099: add Lua bindings for custom metrics

Posted by jp...@apache.org.
TS-4099: add Lua bindings for custom metrics

Implement custom metrics in terms of Lua bindings. We export a
minimal API that constructs metrics and implicitly registers an
evaluation function. We periodically evaluate all the evaluation
functions and update their corresponding metrics.

Metrics are implicitly registered when they are loaded, so there
is no need to mention anything in mgmt/RecordsConfig.cc.

The metrics registration and evaluation syntax looks like this:

  integer 'proxy.node.http.user_agents_total_documents_served' [[
      proxy.process.http.incoming_requests
  ]]


Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo
Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/1a590016
Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/1a590016
Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/1a590016

Branch: refs/heads/master
Commit: 1a590016ae2dd2e1f868a57eec668cda886c4368
Parents: e9649d2
Author: James Peach <jp...@apache.org>
Authored: Tue Nov 24 16:19:37 2015 -0800
Committer: James Peach <jp...@apache.org>
Committed: Thu Jan 21 18:52:18 2016 -0800

----------------------------------------------------------------------
 cmd/traffic_manager/AddConfigFilesHere.cc |    1 +
 cmd/traffic_manager/Makefile.am           |   21 +-
 cmd/traffic_manager/metrics.cc            |  398 ++++++
 cmd/traffic_manager/metrics.h             |   31 +
 cmd/traffic_manager/traffic_manager.cc    |   47 +-
 mgmt/RecordsConfig.cc                     |    2 +
 proxy/config/Makefile.am                  |    5 +-
 proxy/config/metrics.config.default       | 1802 ++++++++++++++++++++++++
 8 files changed, 2299 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/1a590016/cmd/traffic_manager/AddConfigFilesHere.cc
----------------------------------------------------------------------
diff --git a/cmd/traffic_manager/AddConfigFilesHere.cc b/cmd/traffic_manager/AddConfigFilesHere.cc
index 34bc1da..2cd111c 100644
--- a/cmd/traffic_manager/AddConfigFilesHere.cc
+++ b/cmd/traffic_manager/AddConfigFilesHere.cc
@@ -84,5 +84,6 @@ initializeRegistry()
   configFiles->addFile("splitdns.config", false);
   configFiles->addFile("ssl_multicert.config", false);
   configFiles->addFile("stats.config.xml", false);
+  configFiles->addFile("metrics.config", false);
   configFiles->registerCallback(testcall);
 }

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/1a590016/cmd/traffic_manager/Makefile.am
----------------------------------------------------------------------
diff --git a/cmd/traffic_manager/Makefile.am b/cmd/traffic_manager/Makefile.am
index fecdd49..7b615fd 100644
--- a/cmd/traffic_manager/Makefile.am
+++ b/cmd/traffic_manager/Makefile.am
@@ -18,6 +18,7 @@
 bin_PROGRAMS = traffic_manager
 
 AM_CPPFLAGS = \
+  $(LUAJIT_CPPFLAGS) \
   $(iocore_include_dirs) \
   -I$(top_srcdir)/lib/records \
   -I$(top_srcdir)/proxy \
@@ -28,7 +29,11 @@ AM_CPPFLAGS = \
   -I$(top_srcdir)/mgmt/api/include \
   -I$(top_srcdir)/mgmt/cluster \
   -I$(top_srcdir)/mgmt/utils \
-  -I$(top_srcdir)/lib
+  -I$(top_srcdir)/lib \
+  -I$(top_srcdir)/lib/luajit/src
+
+AM_CXXFLAGS += \
+  $(LUAJIT_CFLAGS)
 
 AM_LDFLAGS = \
   @EXTRA_CXX_LDFLAGS@ \
@@ -36,9 +41,13 @@ AM_LDFLAGS = \
   @EXPAT_LDFLAGS@ \
   @OPENSSL_LDFLAGS@
 
+AM_LDFLAGS += \
+  $(LUAJIT_LDFLAGS)
+
 traffic_manager_SOURCES = \
   AddConfigFilesHere.cc \
   traffic_manager.cc \
+  metrics.cc \
   StatProcessor.cc \
   StatProcessor.h \
   StatType.cc \
@@ -58,7 +67,15 @@ traffic_manager_LDADD = \
   $(top_builddir)/lib/ts/libtsutil.la \
   $(top_builddir)/iocore/eventsystem/libinkevent.a \
   $(top_builddir)/proxy/shared/liberror.a \
-  $(top_builddir)/proxy/shared/libdiagsconfig.a \
+  $(top_builddir)/proxy/shared/libdiagsconfig.a
+
+if BUILD_LUAJIT
+traffic_manager_LDADD += \
+  $(top_builddir)/lib/bindings/libbindings.la \
+  $(top_builddir)/lib/luajit/src/libluajit.a
+endif
+
+traffic_manager_LDADD +=\
   $(LIBUNWIND_LIBS) \
   @LIBRESOLV@ @LIBEXPAT@ @LIBPCRE@ @LIBTCL@ @LIBCAP@ @HWLOC_LIBS@ \
   -lm

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/1a590016/cmd/traffic_manager/metrics.cc
----------------------------------------------------------------------
diff --git a/cmd/traffic_manager/metrics.cc b/cmd/traffic_manager/metrics.cc
new file mode 100644
index 0000000..7bc5bec
--- /dev/null
+++ b/cmd/traffic_manager/metrics.cc
@@ -0,0 +1,398 @@
+/** @file
+ *
+ *  Traffic Manager custom metrics.
+ *
+ *  @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 "ts/ink_config.h"
+#include "ts/ink_memory.h"
+#include "ts/Ptr.h"
+#include "ts/Vec.h"
+#include "ts/I_Layout.h"
+#include "bindings/bindings.h"
+#include "bindings/metrics.h"
+#include "I_RecCore.h"
+#include "MgmtDefs.h"
+#include "MgmtUtils.h"
+#include "WebOverview.h"
+#include "metrics.h"
+
+struct Evaluator {
+  Evaluator() : rec_name(NULL), data_type(RECD_NULL), ref(-1) {}
+
+  ~Evaluator()
+  {
+    ats_free(this->rec_name);
+    ink_release_assert(this->ref == -1);
+  }
+
+  bool
+  bind(lua_State *L, const char *metric, const char *expression)
+  {
+    if (RecGetRecordDataType(metric, &this->data_type) != REC_ERR_OKAY) {
+      return false;
+    }
+
+    this->rec_name = ats_strdup(metric);
+
+    switch (luaL_loadstring(L, expression)) {
+    case LUA_ERRSYNTAX:
+    case LUA_ERRMEM:
+      Debug("lua", "loadstring failed for %s", metric);
+      luaL_error(L, "invalid expression for %s", metric);
+      return false;
+    case 0:
+      break; // success
+    }
+
+    // The loaded chunk is now on the top of the stack. Stuff it into the registry
+    // so we can evaluate it later.
+    this->ref = luaL_ref(L, LUA_REGISTRYINDEX);
+
+    return true;
+  }
+
+  void
+  eval(lua_State *L) const
+  {
+    // Push the stashed expression chunk onto the stack.
+    lua_rawgeti(L, LUA_REGISTRYINDEX, this->ref);
+
+    // Evaluate it. Note that we don't emit a warning for
+    // evaluation errors. This is because not all metrics (eg.
+    // cache metrics) are available early in startup so we don't
+    // want to log spurious warning. Unfortunately it means that
+    // to check your config for errors you need to enable
+    // diagnostic tags.
+    lua_pushstring(L, this->rec_name);
+    if (lua_pcall(L, 1 /* nargs */, 1 /* nresults */, 0) != 0) {
+      Debug("lua", "failed to evaluate %s: %s", this->rec_name, lua_tostring(L, -1));
+      lua_pop(L, 1);
+      return;
+    }
+
+    // If we got a return value, set it on the record. Records can return nil to
+    // indicate they don't want to be set on this round.
+    if (!lua_isnil(L, -1)) {
+      RecData rec_value;
+
+      switch (this->data_type) {
+      case RECD_INT:
+        rec_value.rec_int = lua_tointeger(L, -1);
+        break;
+      case RECD_COUNTER:
+        rec_value.rec_counter = lua_tointeger(L, -1);
+        break;
+      case RECD_FLOAT:
+        // Lua will eval 0/0 to NaN rather than 0.
+        rec_value.rec_float = lua_tonumber(L, -1);
+        if (isnan(rec_value.rec_float)) {
+          rec_value.rec_float = 0.0;
+        }
+        break;
+      default:
+        goto done;
+      }
+
+      RecSetRecord(RECT_NULL, this->rec_name, this->data_type, &rec_value, NULL, REC_SOURCE_EXPLICIT);
+    }
+
+  done:
+    // Pop the return value.
+    lua_pop(L, 1);
+  }
+
+private:
+  char *rec_name;
+  RecDataT data_type;
+
+  int ref;
+};
+
+struct EvaluatorList {
+  EvaluatorList() : passes(0) {}
+  ~EvaluatorList()
+  {
+    forv_Vec(Evaluator, e, this->evaluators) { delete e; }
+  }
+
+  void
+  push_back(Evaluator *e)
+  {
+    evaluators.push_back(e);
+  }
+
+  void
+  evaluate(lua_State *L) const
+  {
+    ink_hrtime start = ink_get_hrtime_internal();
+    ink_hrtime elapsed;
+
+    forv_Vec(Evaluator, e, this->evaluators) { e->eval(L); }
+
+
+    elapsed = ink_hrtime_diff(ink_get_hrtime_internal(), start);
+    Debug("lua", "evaluated %u metrics in %fmsec", evaluators.length(), ink_hrtime_to_usec(elapsed) / 1000.0);
+  }
+
+  int64_t passes;
+  Vec<Evaluator *> evaluators;
+};
+
+static int64_t
+timestamp_now_msec()
+{
+  ink_hrtime now = ink_get_hrtime_internal();
+  return ink_hrtime_to_msec(now);
+}
+
+static int
+metrics_register_evaluator(lua_State *L)
+{
+  const char *metric;
+  const char *chunk;
+  Evaluator *eval;
+  EvaluatorList *evaluators;
+  BindingInstance *binding = BindingInstance::self(L);
+
+  // The metric name is the first upvalue (from the record creation closure).
+  metric = lua_tostring(L, lua_upvalueindex(1));
+  // The evaluation chunk is the (only) argument.
+  chunk = lua_tostring(L, -1);
+
+  binding = BindingInstance::self(L);
+  evaluators = (EvaluatorList *)binding->retrieve_ptr("evaluators");
+
+  ink_release_assert(evaluators != NULL);
+
+  eval = new Evaluator();
+  eval->bind(L, metric, chunk);
+
+  evaluators->push_back(eval);
+  return 0;
+}
+
+static int
+metrics_create_record(lua_State *L, RecDataT data_type)
+{
+  const char *name;
+  RecT rec_type = RECT_NULL;
+  int error = REC_ERR_FAIL;
+
+  BindingInstance::typecheck(L, "record.create", LUA_TSTRING, LUA_TNONE);
+
+  // Get the name of the record to create.
+  name = lua_tostring(L, -1);
+
+  if (strncmp(name, "proxy.process.", sizeof("proxy.process.") - 1) == 0) {
+    rec_type = RECT_PROCESS;
+  } else if (strncmp(name, "proxy.node.", sizeof("proxy.node.") - 1) == 0) {
+    rec_type = RECT_NODE;
+  } else if (strncmp(name, "proxy.cluster.", sizeof("proxy.cluster.") - 1) == 0) {
+    rec_type = RECT_CLUSTER;
+  }
+
+  // You have to follow the naming convention.
+  if (rec_type == RECT_NULL) {
+    luaL_error(L, "invalid metric name '%s'", name);
+  }
+
+  switch (data_type) {
+  case RECD_INT:
+    error = RecRegisterStatInt(rec_type, name, 0, RECP_NON_PERSISTENT);
+    break;
+  case RECD_FLOAT:
+    error = RecRegisterStatFloat(rec_type, name, 0, RECP_NON_PERSISTENT);
+    break;
+  case RECD_COUNTER:
+    error = RecRegisterStatCounter(rec_type, name, 0, RECP_NON_PERSISTENT);
+    break;
+  default:
+    break;
+  }
+
+  if (error != REC_ERR_OKAY) {
+    luaL_error(L, "failed to register metric '%s'", name);
+  }
+
+  // Push a copy of the metric name onto the stack.
+  lua_pushvalue(L, -1);
+  // Push the Evaluator as a closure with the metric name as an upvalue.
+  lua_pushcclosure(L, metrics_register_evaluator, 1);
+
+  Debug("lua", "registered %s as record type %d", name, rec_type);
+  return 1;
+}
+
+static int
+metrics_create_integer(lua_State *L)
+{
+  return metrics_create_record(L, RECD_INT);
+}
+
+static int
+metrics_create_counter(lua_State *L)
+{
+  return metrics_create_record(L, RECD_COUNTER);
+}
+
+static int
+metrics_create_float(lua_State *L)
+{
+  return metrics_create_record(L, RECD_FLOAT);
+}
+
+static int
+metrics_cluster_sum(lua_State *L)
+{
+  const char *rec_name;
+  RecDataT data_type;
+  RecData rec_data;
+
+  // Get the name of the record to sum.
+  rec_name = lua_tostring(L, -1);
+
+  // XXX Check whether we have a cached value for this somewhere ...
+
+  // If not, get the record data type.
+  if (RecGetRecordDataType(rec_name, &data_type) == REC_ERR_FAIL) {
+    luaL_error(L, "unknown metric name '%s'", rec_name);
+  }
+
+  // Sum the cluster value.
+  if (!overviewGenerator->varClusterDataFromName(data_type, rec_name, &rec_data)) {
+    RecDataClear(data_type, &rec_data);
+
+    // If we can't get any cluster data, return nil. This will generally cause the
+    // evaluator to fail, which is handled by logging and ignoring the failure.
+    lua_pushnil(L);
+    return 1;
+  }
+
+  switch (data_type) {
+  case RECD_INT: /* fallthru */
+  case RECD_COUNTER:
+    lua_pushinteger(L, rec_data.rec_int);
+    break;
+  case RECD_FLOAT:
+    lua_pushnumber(L, rec_data.rec_float);
+    break;
+  case RECD_STRING:
+    lua_pushlstring(L, rec_data.rec_string, strlen(rec_data.rec_string));
+    break;
+  default:
+    lua_pushnil(L);
+  }
+
+  // Return 1 value on the stack.
+  return 1;
+}
+
+static void
+register_metrics_namespace(BindingInstance &binding)
+{
+  // XXX Currently known metrics namespace prefixes. Figure out a way to
+  // add new metrics nodes as new prefixes are added.
+  const char *prefixes[] = {
+    "proxy.cluster", "proxy.cluster.cache", "proxy.cluster.cache.contents", "proxy.cluster.dns", "proxy.cluster.hostdb",
+    "proxy.cluster.http", "proxy.cluster.log", "proxy.node", "proxy.node.cache", "proxy.node.cache.contents", "proxy.node.cluster",
+    "proxy.node.config", "proxy.node.config.restart_required", "proxy.node.dns", "proxy.node.hostdb", "proxy.node.http",
+    "proxy.node.http.transaction_counts_avg_10s", "proxy.node.http.transaction_counts_avg_10s.errors",
+    "proxy.node.http.transaction_counts_avg_10s.other", "proxy.node.http.transaction_frac_avg_10s",
+    "proxy.node.http.transaction_frac_avg_10s.errors", "proxy.node.http.transaction_frac_avg_10s.other",
+    "proxy.node.http.transaction_msec_avg_10s", "proxy.node.http.transaction_msec_avg_10s.errors",
+    "proxy.node.http.transaction_msec_avg_10s.other", "proxy.node.log", "proxy.node.restarts.manager", "proxy.node.restarts.proxy",
+    "proxy.node.version.manager", "proxy.process.cache", "proxy.process.cache.direntries", "proxy.process.cache.evacuate",
+    "proxy.process.cache.frags_per_doc", "proxy.process.cache.frags_per_doc.3+", "proxy.process.cache.lookup",
+    "proxy.process.cache.ram_cache", "proxy.process.cache.read", "proxy.process.cache.read_busy", "proxy.process.cache.remove",
+    "proxy.process.cache.scan", "proxy.process.cache.sync", "proxy.process.cache.update", "proxy.process.cache.write",
+    "proxy.process.cache.write.backlog", "proxy.process.cluster", "proxy.process.congestion", "proxy.process.dns",
+    "proxy.process.hostdb", "proxy.process.http", "proxy.process.http.milestone", "proxy.process.http.transaction_counts",
+    "proxy.process.http.transaction_counts.errors", "proxy.process.http.transaction_counts.hit_fresh",
+    "proxy.process.http.transaction_counts.other", "proxy.process.http.transaction_totaltime",
+    "proxy.process.http.transaction_totaltime.errors", "proxy.process.http.transaction_totaltime.hit_fresh",
+    "proxy.process.http.transaction_totaltime.other", "proxy.process.http.websocket", "proxy.process.http2", "proxy.process.https",
+    "proxy.process.log", "proxy.process.net", "proxy.process.socks", "proxy.process.ssl", "proxy.process.ssl.cipher.user_agent",
+    "proxy.process.version.server",
+  };
+
+  // Register the metrics userdata type.
+  lua_metrics_register(binding.lua);
+
+  // Bind metric nodes to all the metrics namespace prefixes.
+  for (unsigned i = 0; i < countof(prefixes); ++i) {
+    if (lua_metrics_new(prefixes[i], binding.lua) == 1) {
+      binding.bind_value(prefixes[i], -1);
+      lua_pop(binding.lua, 1);
+    }
+  }
+}
+
+bool
+metrics_binding_initialize(BindingInstance &binding)
+{
+  ats_scoped_str sysconfdir(RecConfigReadConfigDir());
+  ats_scoped_str config(Layout::get()->relative_to(sysconfdir, "metrics.config"));
+
+  if (!binding.construct()) {
+    mgmt_fatal(stderr, 0, "failed to initialize Lua runtime\n");
+  }
+
+  // Register the metrics bindings.
+  register_metrics_namespace(binding);
+
+  // Register our own API.
+  binding.bind_function("integer", metrics_create_integer);
+  binding.bind_function("counter", metrics_create_counter);
+  binding.bind_function("float", metrics_create_float);
+  binding.bind_function("metrics.cluster.sum", metrics_cluster_sum);
+
+  binding.bind_constant("metrics.now.msec", timestamp_now_msec());
+  binding.bind_constant("metrics.update.pass", int64_t(0));
+
+  // Stash a backpointer to the evaluators.
+  binding.attach_ptr("evaluators", new EvaluatorList());
+
+  // Finally, execute the config file.
+  return binding.require(config.get());
+}
+
+void
+metrics_binding_destroy(BindingInstance &binding)
+{
+  EvaluatorList *evaluators;
+
+  evaluators = (EvaluatorList *)binding.retrieve_ptr("evaluators");
+  binding.attach_ptr("evaluators", NULL);
+  delete evaluators;
+}
+
+void
+metrics_binding_evaluate(BindingInstance &binding)
+{
+  EvaluatorList *evaluators;
+
+  evaluators = (EvaluatorList *)binding.retrieve_ptr("evaluators");
+  ink_release_assert(evaluators != NULL);
+
+  binding.bind_constant("metrics.now.msec", timestamp_now_msec());
+  binding.bind_constant("metrics.update.pass", ++evaluators->passes);
+  evaluators->evaluate(binding.lua);
+}

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/1a590016/cmd/traffic_manager/metrics.h
----------------------------------------------------------------------
diff --git a/cmd/traffic_manager/metrics.h b/cmd/traffic_manager/metrics.h
new file mode 100644
index 0000000..4bc97ce
--- /dev/null
+++ b/cmd/traffic_manager/metrics.h
@@ -0,0 +1,31 @@
+/** @file
+ *
+ *  Traffic Manager custom metrics.
+ *
+ *  @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.
+ */
+
+#ifndef METRICS_H_D289E71B_AAC5_4CF3_9954_D54EDED60D1B
+#define METRICS_H_D289E71B_AAC5_4CF3_9954_D54EDED60D1B
+
+bool metrics_binding_initialize(BindingInstance &binding);
+void metrics_binding_destroy(BindingInstance &binding);
+void metrics_binding_evaluate(BindingInstance &binding);
+
+#endif /* METRICS_H_D289E71B_AAC5_4CF3_9954_D54EDED60D1B */

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/1a590016/cmd/traffic_manager/traffic_manager.cc
----------------------------------------------------------------------
diff --git a/cmd/traffic_manager/traffic_manager.cc b/cmd/traffic_manager/traffic_manager.cc
index f12da0a..cae77b8 100644
--- a/cmd/traffic_manager/traffic_manager.cc
+++ b/cmd/traffic_manager/traffic_manager.cc
@@ -51,6 +51,10 @@
 #include "StatProcessor.h"
 #include "P_RecLocal.h"
 
+#include "bindings/bindings.h"
+#include "bindings/metrics.h"
+#include "metrics.h"
+
 #if TS_USE_POSIX_CAP
 #include <sys/capability.h>
 #endif
@@ -87,8 +91,10 @@ static const char *recs_conf = "records.config";
 
 static int fds_limit;
 
+static int metrics_version;
+
 // TODO: Use positive instead negative selection
-//       Thsis should just be #if defined(solaris)
+//       This should just be #if defined(solaris)
 #if !defined(linux) && !defined(freebsd) && !defined(darwin)
 static void SignalHandler(int sig, siginfo_t *t, void *f);
 static void SignalAlrmHandler(int sig, siginfo_t *t, void *f);
@@ -437,11 +443,15 @@ main(int argc, const char **argv)
   int proxy_backdoor = -1;
   char *group_addr = NULL, *tsArgs = NULL;
   bool disable_syslog = false;
+  RecBool enable_lua = false;
   char userToRunAs[MAX_LOGIN + 1];
   RecInt fds_throttle = -1;
   time_t ticker;
   ink_thread synthThrId;
 
+  int binding_version = 0;
+  BindingInstance *binding = NULL;
+
   ArgumentDescription argument_descriptions[] = {
     {"proxyOff", '-', "Disable proxy", "F", &proxy_off, NULL, NULL},
     {"aconfPort", '-', "Autoconf port", "I", &aconf_port_arg, "MGMT_ACONF_PORT", NULL},
@@ -508,6 +518,7 @@ main(int argc, const char **argv)
   }
 
   RecGetRecordInt("proxy.config.net.connections_throttle", &fds_throttle);
+  RecGetRecordBool("proxy.config.stats.enable_lua", &enable_lua);
 
   set_process_limits(fds_throttle); // as root
 
@@ -727,12 +738,28 @@ main(int argc, const char **argv)
   RecRegisterStatInt(RECT_NODE, "proxy.node.config.restart_required.manager", 0, RECP_NON_PERSISTENT);
   RecRegisterStatInt(RECT_NODE, "proxy.node.config.restart_required.cop", 0, RECP_NON_PERSISTENT);
 
+  if (enable_lua) {
+    binding = new BindingInstance;
+    metrics_binding_initialize(*binding);
+  }
+
   int sleep_time = 0; // sleep_time given in sec
 
   for (;;) {
     lmgmt->processEventQueue();
     lmgmt->pollMgmtProcessServer();
 
+    if (enable_lua) {
+      if (binding_version != metrics_version) {
+        metrics_binding_destroy(*binding);
+        delete binding;
+
+        binding = new BindingInstance;
+        metrics_binding_initialize(*binding);
+        binding_version = metrics_version;
+      }
+    }
+
     // Handle rotation of output log (aka traffic.out) as well as DIAGS_LOG_FILENAME (aka manager.log)
     rotateLogs();
 
@@ -762,8 +789,12 @@ main(int argc, const char **argv)
     lmgmt->ccom->checkPeers(&ticker);
     overviewGenerator->checkForUpdates();
 
-    if (statProcessor) {
-      statProcessor->processStat();
+    if (enable_lua) {
+      metrics_binding_evaluate(*binding);
+    } else {
+      if (statProcessor) {
+        statProcessor->processStat();
+      }
     }
 
     if (lmgmt->mgmt_shutdown_outstanding != MGMT_PENDING_NONE) {
@@ -834,8 +865,13 @@ main(int argc, const char **argv)
     }
   }
 
+  if (binding) {
+    metrics_binding_destroy(*binding);
+    delete binding;
+  }
+
   if (statProcessor) {
-    delete (statProcessor);
+    delete statProcessor;
   }
 
 #ifndef MGMT_SERVICE
@@ -1020,6 +1056,9 @@ fileUpdated(char *fname, bool incVersion)
       statProcessor->rereadConfig(configFiles);
     }
     mgmt_log(stderr, "[fileUpdated] stats.config.xml file has been modified\n");
+  } else if (strcmp(fname, "metrics.config") == 0) {
+    ink_atomic_increment(&metrics_version, 1);
+    mgmt_log(stderr, "[fileUpdated] metrics.config file has been modified\n");
   } else if (strcmp(fname, "congestion.config") == 0) {
     lmgmt->signalFileChange("proxy.config.http.congestion_control.filename");
   } else {

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/1a590016/mgmt/RecordsConfig.cc
----------------------------------------------------------------------
diff --git a/mgmt/RecordsConfig.cc b/mgmt/RecordsConfig.cc
index 4a3ec43..9eea1b3 100644
--- a/mgmt/RecordsConfig.cc
+++ b/mgmt/RecordsConfig.cc
@@ -1120,6 +1120,8 @@ static const RecordElement RecordsConfig[] =
   // Jira TS-21
   {RECT_CONFIG, "proxy.config.stats.snap_file", RECD_STRING, "stats.snap", RECU_RESTART_TS, RR_NULL, RECC_NULL, NULL, RECA_NULL}
   ,
+  {RECT_CONFIG, "proxy.config.stats.enable_lua", RECD_INT, "0", RECU_RESTART_TM, RR_NULL, RECC_INT, "[0-1]", RECA_NULL}
+  ,
 
   //        ###########
   //        # Parsing #

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/1a590016/proxy/config/Makefile.am
----------------------------------------------------------------------
diff --git a/proxy/config/Makefile.am b/proxy/config/Makefile.am
index 9e654d7..6625990 100644
--- a/proxy/config/Makefile.am
+++ b/proxy/config/Makefile.am
@@ -35,15 +35,16 @@ dist_sysconf_DATA =	\
   ip_allow.config.default \
   log_hosts.config.default \
   logs_xml.config.default \
+  metrics.config.default \
   parent.config.default \
-  volume.config.default \
   plugin.config.default \
   remap.config.default \
   socks.config.default \
   splitdns.config.default \
   ssl_multicert.config.default \
   stats.config.xml.default \
-  vaddrs.config.default
+  vaddrs.config.default \
+  volume.config.default
 
 install-exec-hook:
 	for dfltcfgfile in $(dist_sysconf_DATA) $(nodist_sysconf_DATA) ; \


[03/10] trafficserver git commit: TS-4099: add Lua bindings for custom metrics

Posted by jp...@apache.org.
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/1a590016/proxy/config/metrics.config.default
----------------------------------------------------------------------
diff --git a/proxy/config/metrics.config.default b/proxy/config/metrics.config.default
new file mode 100644
index 0000000..0eec83a
--- /dev/null
+++ b/proxy/config/metrics.config.default
@@ -0,0 +1,1802 @@
+-- Dynamic metrics.
+-- This file is processed by Traffic Manager to evaluate dynamic metric definitions.
+
+-- XML Transliteration Notes:
+--
+-- The 'minimum' and 'maximum' XML elements effectively do nothing.
+-- These are called to set the initial value during XML parsing, so
+-- the net effect is to set the value to 'minimum. Since we always
+-- zero metrice on creation there's nothing to do there.
+--
+-- In the cluster-based statistics, the aggregation is further
+-- divided into two types: sum and re-calculate. Sum refers calculating
+-- the proxy.cluster.* variable by simply summing all required
+-- proxy.node.* variables from nodes in the cluster. Re-calculate
+-- refers to summing all proxy.nodes.* variables that are used in the
+-- process of calculation before performing the calculation.  An analogy
+-- would be, summing all open connection in the cluster vs. the average
+-- hit rate in the cluster.
+--
+-- The "operation" attribute ends up in StatExprToken::m_sum_var. For "sum"
+-- and default, m_sum_var is true. For "sum" operations, the cluster metric
+-- don't evaluate expression, then just sum the associated node metric across
+-- the cluster.
+
+-- Handling periodic updates.
+--
+-- Some metrics calculate periodic updates using the interval_of()
+-- and delta_of() APIs. These rely on the fact that the metric name
+-- is passed as the first argument to each evaluation function (so
+-- we can use it as a unique table key), and that if the evaluation
+-- function returns nil, no value is stored (ie. the metric simply
+-- retains its previous value. We combine these characteristics to
+-- run the evaluators on every update cycle but to only store the
+-- value or calculate a delta when the desired interval has passed.
+
+-- Lua API.
+--
+-- VALUE metrics.cluster.sum(METRIC)
+--    Sum the named METRIC across the cluster. METRIC must be a string naming a node
+--    metric since only node metrics are shared across the cluster.
+--
+-- metrics.now.msec
+--    Wall-clock time in milliseconds.
+--
+-- metrics.update.pass
+--    Count of metric updates passes performed in this Lua state
+--
+-- integer(NAME, FUNC), counter(NAME, FUNC), float(NAME, FUNC)
+--    These global functions register a metric of the corresponding name. Each
+--    registered metric will be periodically recalculated by evaluating the 
+--    given function.
+--
+--    The scope of a metric is derived from the name. 'proxy.cluster.*' metrics
+--    are placed in CLUSTER scope and 'proxy.node.*' metrics are placed in NODE
+--    scope.
+--
+--    The name of the metric is passed to evaluation function on each invocation.
+--    This can be used to greate a unique key for persisting data in global tables.
+
+-- Multiplier to convert seconds to milliseconds
+sec_to_msec = 1000
+
+-- Return the sum of the given metric across all cluster nodes. metrics.cluster.sum()
+-- will memoize its result so that summing the same value multiple times in the same
+-- metrics pass is not too expensive. The metric name should always be a node metric.
+function cluster(name)
+  return metrics.cluster.sum(name)
+end
+
+-- Convert bytes to megabits.
+function mbits(bytes)
+  return bytes * 8 / 1000000
+end
+
+-- Convert bytes to mebibytes.
+function mbytes(bytes)
+  return bytes / (1024 * 1024)
+end
+
+-- Return the current time in milliseconds.
+function now()
+  return metrics.now.msec
+end
+
+-- interval_of(msec, key, fn)
+--
+-- Call a function after an interval (in milliseconds) elapses.
+-- The function is called with a single argument of the elapsed
+-- time in milliseconds.
+--
+-- key: unique persistence key
+-- fn: function to call after the interval elapses
+interval_of = (function()
+
+  function __interval_of(msec, fn)
+    local previous = now()
+    return function()
+      local current = now()
+      local elapsed = current - previous
+      if elapsed > msec then
+        previous = current
+        return fn(elapsed)
+      else
+        return nil
+      end
+    end
+  end
+
+  local intervals = {}
+
+  return function(msec, scope, fn)
+    if intervals[scope] == nil then
+      intervals[scope] = __interval_of(msec, fn)
+    end
+    return intervals[scope]()
+  end
+end)()
+
+function interval_of_10s(key, fn)
+  return interval_of(10 * 1000, key, fn)
+end
+
+-- Register a function that returns the delta in every call.
+delta_of = (function ()
+
+  function __delta_of(fn)
+    local previous = fn()
+    return function()
+      local current = fn()
+      local difference = current - previous
+      previous = current
+      return difference
+    end
+  end
+
+  local deltas = {}
+
+  return function(key, fn)
+    if deltas[key] == nil then
+      deltas[key] = __delta_of(fn)
+    end
+
+    return deltas[key]()
+  end
+end)()
+
+-- Wrap delta_of() over an interval to find the rate of change
+-- for a value over the given interval in milliseconds.
+--
+-- msec: interval in milliseconds
+-- key: unique persistence key
+-- fn: function that returns the value
+function rate_of(msec, key, fn)
+  return interval_of(msec, key,
+    function(elapsed)
+      return delta_of(key, fn) * 1000 / elapsed
+    end
+  )
+end
+
+-- Find the per-second rate of change for a value over 10sec.
+function rate_of_10s(key, fn)
+  return rate_of(10 * 1000, key, fn)
+end
+
+-- Return the change over an interval. Most of the metrics that use
+-- this don't really make sense. It's not an average in the way that
+-- people would reasonably expect it to be.
+function interval_delta_of_10s(key, fn)
+  return interval_of_10s(key, function()
+    return delta_of(key, fn)
+  end)
+end
+
+counter 'proxy.node.http.user_agents_total_documents_served' [[
+  return proxy.process.http.incoming_requests
+]]
+
+counter 'proxy.cluster.http.user_agents_total_documents_served' [[
+  return cluster('proxy.node.http.user_agents_total_documents_served')
+]]
+
+counter 'proxy.node.http.user_agents_total_transactions_count' [[
+  return proxy.process.http.incoming_requests
+]]
+
+counter 'proxy.cluster.http.user_agents_total_transactions_count' [[
+  return cluster('proxy.node.http.user_agents_total_transactions_count')
+]]
+
+counter 'proxy.node.http.origin_server_total_transactions_count' [[
+  return proxy.process.http.outgoing_requests
+]]
+
+counter 'proxy.cluster.http.origin_server_total_transactions_count' [[
+  return cluster('proxy.node.http.origin_server_total_transactions_count')
+]]
+
+counter 'proxy.node.http.cache_current_connections_count' [[
+  return proxy.process.http.current_cache_connections
+]]
+
+counter 'proxy.cluster.http.cache_current_connections_count' [[
+  return cluster('proxy.node.http.cache_current_connections_count')
+]]
+
+counter 'proxy.node.http.user_agent_current_connections_count' [[
+  return proxy.process.http.current_client_connections
+]]
+
+counter 'proxy.cluster.http.user_agent_current_connections_count' [[
+  return cluster('proxy.node.http.user_agent_current_connections_count')
+]]
+
+counter 'proxy.node.http.origin_server_current_connections_count' [[
+  return proxy.process.http.current_server_connections
+]]
+
+counter 'proxy.cluster.http.origin_server_current_connections_count' [[
+  return cluster('proxy.node.http.origin_server_current_connections_count')
+]]
+
+--
+-- Cache metrics.
+--
+
+integer 'proxy.node.cache.bytes_total' [[
+  return proxy.process.cache.bytes_total
+]]
+
+--
+-- DNS metrics.
+--
+
+counter 'proxy.node.dns.total_dns_lookups' [[
+  return proxy.process.dns.total_dns_lookups
+]]
+
+counter 'proxy.cluster.dns.total_dns_lookups' [[
+  return cluster('proxy.node.dns.total_dns_lookups')
+]]
+
+--
+-- HostDB metrics.
+--
+
+counter 'proxy.node.hostdb.total_lookups' [[
+  return proxy.process.hostdb.total_lookups
+]]
+
+counter 'proxy.node.hostdb.total_hits' [[
+  return proxy.process.hostdb.total_hits
+]]
+
+--
+-- Cluster metrics.
+--
+
+integer 'proxy.node.cluster.nodes' [[
+  return proxy.process.cluster.nodes
+]]
+
+--
+-- HTTP Cache.
+--
+
+counter 'proxy.node.http.cache_lookups' [[
+  return proxy.process.http.cache_lookups
+]]
+
+counter 'proxy.node.http.cache_writes' [[
+  return proxy.process.http.cache_writes
+]]
+
+counter 'proxy.node.http.cache_updates' [[
+  return proxy.process.http.cache_updates
+]]
+
+counter 'proxy.node.http.cache_deletes' [[
+  return proxy.process.http.cache_deletes
+]]
+
+counter 'proxy.node.http.cache_hit_fresh' [[
+  return proxy.process.http.cache_hit_fresh
+]]
+
+counter 'proxy.node.http.cache_hit_mem_fresh' [[
+  return proxy.process.http.cache_hit_mem_fresh
+]]
+
+counter 'proxy.node.http.cache_hit_revalidated' [[
+  return proxy.process.http.cache_hit_revalidated
+]]
+
+counter 'proxy.node.http.cache_hit_ims' [[
+  return proxy.process.http.cache_hit_ims
+]]
+
+counter 'proxy.node.http.cache_hit_stale_served' [[
+  return proxy.process.http.cache_hit_stale_served
+]]
+
+counter 'proxy.node.http.cache_miss_cold' [[
+  return proxy.process.http.cache_miss_cold
+]]
+
+counter 'proxy.node.http.cache_miss_changed' [[
+  return proxy.process.http.cache_miss_changed
+]]
+
+counter 'proxy.node.http.cache_miss_client_no_cache' [[
+  return proxy.process.http.cache_miss_client_no_cache
+]]
+
+counter 'proxy.node.http.cache_miss_client_not_cacheable' [[
+  return proxy.process.http.cache_miss_client_not_cacheable
+]]
+
+counter 'proxy.node.http.cache_miss_ims' [[
+  return proxy.process.http.cache_miss_ims
+]]
+
+counter 'proxy.node.http.cache_read_error' [[
+  return proxy.process.http.cache_read_error
+]]
+
+counter 'proxy.node.http.cache_write_errors' [[
+  return proxy.process.http.cache_write_errors
+]]
+
+counter 'proxy.node.http.cache_read_errors' [[
+  return proxy.process.http.cache_read_errors
+]]
+
+-- StatAggregation::Ag_XactsPerSecond() -->
+integer 'proxy.node.http.user_agent_xacts_per_second' [[
+  local self = ...
+
+  return rate_of_10s(self,
+    function() return proxy.process.http.incoming_requests end
+  )
+]]
+
+integer'proxy.cluster.http.user_agent_xacts_per_second' [[
+  return cluster('proxy.node.http.user_agent_xacts_per_second')
+]]
+
+integer 'proxy.node.user_agent_xacts_per_second' [[
+  return proxy.node.http.user_agent_xacts_per_second
+]]
+
+integer 'proxy.cluster.user_agent_xacts_per_second' [[
+  return cluster('proxy.cluster.http.user_agent_xacts_per_second')
+]]
+
+counter 'proxy.node.user_agents_total_documents_served' [[
+  return proxy.node.http.user_agents_total_documents_served
+]]
+
+-- StatAggregation::Ag_DnsLookupsPerSecond()
+integer 'proxy.node.dns.lookups_per_second' [[
+  local self = ...
+
+  return rate_of_10s(self,
+    function() return proxy.process.dns.total_dns_lookups end
+  )
+]]
+
+integer 'proxy.cluster.dns.lookups_per_second' [[
+  return cluster('proxy.node.dns.lookups_per_second')
+]]
+
+-- StatAggregation::Ag_HostdbHitRate() -->
+integer 'proxy.node.hostdb.total_lookups_avg_10s' [[
+  local self = ...
+
+  return interval_delta_of_10s(self, function()
+    return proxy.process.hostdb.total_lookups
+  end)
+]]
+
+integer 'proxy.cluster.hostdb.total_lookups_avg_10s' [[
+  return cluster('proxy.node.hostdb.total_lookups_avg_10s')
+]]
+
+integer 'proxy.node.hostdb.total_hits_avg_10s' [[
+  local self = ...
+
+  return interval_delta_of_10s(self, function()
+    return proxy.process.hostdb.total_hits
+  end)
+]]
+
+integer 'proxy.cluster.hostdb.total_hits_avg_10s' [[
+  return cluster('proxy.node.hostdb.total_hits_avg_10s')
+]]
+
+float 'proxy.node.hostdb.hit_ratio_avg_10s' [[
+  local self = ...
+
+  return interval_of_10s(self, function()
+    return
+      proxy.node.hostdb.total_hits_avg_10s    /
+      proxy.node.hostdb.total_lookups_avg_10s
+  end)
+]]
+
+float 'proxy.cluster.hostdb.hit_ratio_avg_10s' [[
+  local self = ...
+
+  return interval_of_10s(self, function()
+    return
+      cluster('proxy.node.hostdb.total_hits_avg_10s')    /
+      cluster('proxy.node.hostdb.total_lookups_avg_10s')
+  end)
+]]
+
+float 'proxy.node.hostdb.hit_ratio' [[
+  return proxy.process.hostdb.total_hits / proxy.process.hostdb.total_lookups
+]]
+
+counter 'proxy.node.http.user_agent_total_request_bytes' [[
+  return proxy.process.http.user_agent_request_document_total_size +
+    proxy.process.http.user_agent_request_header_total_size
+]]
+
+counter 'proxy.cluster.http.user_agent_total_request_bytes' [[
+  return cluster('proxy.node.http.user_agent_total_request_bytes')
+]]
+
+counter 'proxy.node.http.user_agent_total_response_bytes' [[
+  return proxy.process.http.user_agent_response_document_total_size +
+    proxy.process.http.user_agent_response_header_total_size
+]]
+
+counter 'proxy.cluster.http.user_agent_total_response_bytes' [[
+  return cluster('proxy.node.http.user_agent_total_response_bytes')
+]]
+
+counter 'proxy.node.http.origin_server_total_request_bytes' [[
+  return proxy.process.http.origin_server_request_document_total_size +
+    proxy.process.http.origin_server_request_header_total_size
+]]
+
+counter 'proxy.cluster.http.origin_server_total_request_bytes' [[
+  return cluster('proxy.node.http.origin_server_total_request_bytes')
+]]
+
+counter 'proxy.node.http.origin_server_total_response_bytes' [[
+  return proxy.process.http.origin_server_response_document_total_size +
+    proxy.process.http.origin_server_response_header_total_size
+]]
+
+counter 'proxy.cluster.http.origin_server_total_response_bytes' [[
+  return cluster('proxy.node.http.origin_server_total_response_bytes')
+]]
+
+-- Add up the downstream (client <-> proxy) traffic volume.
+counter 'proxy.node.user_agent_total_bytes' [[
+  return proxy.node.http.user_agent_total_request_bytes +
+    proxy.node.http.user_agent_total_response_bytes
+]]
+
+-- Add up the upstream (client <-> proxy) traffic volume.
+counter 'proxy.node.origin_server_total_bytes' [[
+  return proxy.node.http.origin_server_total_request_bytes +
+    proxy.node.http.origin_server_total_response_bytes +
+    proxy.node.http.parent_proxy_total_request_bytes +
+    proxy.node.http.parent_proxy_total_response_bytes
+]]
+
+float 'proxy.node.bandwidth_hit_ratio' [[
+  return (proxy.node.user_agent_total_bytes - proxy.node.origin_server_total_bytes)
+      / proxy.node.user_agent_total_bytes
+]]
+
+float 'proxy.cluster.bandwidth_hit_ratio' [[
+  return (cluster('proxy.node.user_agent_total_bytes') - cluster('proxy.node.origin_server_total_bytes'))
+      / cluster('proxy.node.user_agent_total_bytes')
+]]
+
+float 'proxy.node.user_agent_total_bytes_avg_10s' [[
+  local self = ...
+
+  return interval_delta_of_10s(self, function()
+    return proxy.node.user_agent_total_bytes
+  end)
+]]
+
+float 'proxy.cluster.user_agent_total_bytes_avg_10s' [[
+  return cluster('proxy.node.user_agent_total_bytes_avg_10s')
+]]
+
+float 'proxy.node.origin_server_total_bytes_avg_10s' [[
+  local self = ...
+
+  return interval_delta_of_10s(self, function()
+    return proxy.node.origin_server_total_bytes
+  end)
+]]
+
+float 'proxy.cluster.origin_server_total_bytes_avg_10s' [[
+  return cluster('proxy.node.origin_server_total_bytes_avg_10s')
+]]
+
+float 'proxy.node.bandwidth_hit_ratio_avg_10s' [[
+  local self = ...
+
+  return interval_of_10s(self, function()
+    return (
+      proxy.node.user_agent_total_bytes_avg_10s -
+      proxy.node.origin_server_total_bytes_avg_10s
+    ) / proxy.node.user_agent_total_bytes_avg_10s
+  end)
+]]
+
+float 'proxy.cluster.bandwidth_hit_ratio_avg_10s' [[
+  return (
+    cluster('proxy.node.user_agent_total_bytes_avg_10s') -
+    cluster('proxy.node.origin_server_total_bytes_avg_10s')
+  ) / cluster('proxy.node.user_agent_total_bytes_avg_10s')
+]]
+
+integer 'proxy.node.bandwidth_hit_ratio_avg_10s_int_pct' [[
+  return proxy.node.bandwidth_hit_ratio_avg_10s * 100
+]]
+
+-- StatAggregation::Ag_Throughput()
+integer 'proxy.node.http.throughput' [[
+  local self = ...
+
+  return rate_of_10s(self,
+    function() return proxy.node.http.user_agent_total_response_bytes end
+  )
+]]
+
+integer 'proxy.cluster.http.throughput' [[
+  return cluster('proxy.cluster.http.throughput')
+]]
+
+float 'proxy.node.client_throughput_out' [[
+  return mbits(proxy.node.http.throughput)
+]]
+
+float 'proxy.cluster.client_throughput_out' [[
+  return cluster('proxy.node.client_throughput_out')
+]]
+
+-- StatAggregation::Ag_cacheHits()
+float 'proxy.node.http.cache_hit_fresh_avg_10s' [[
+  local self = ...
+
+  return interval_delta_of_10s(self, function()
+    return proxy.process.http.cache_hit_fresh
+  end)
+]]
+
+float 'proxy.node.http.cache_hit_mem_fresh_avg_10s' [[
+  local self = ...
+
+  return interval_delta_of_10s(self, function()
+    return proxy.process.http.cache_hit_mem_fresh
+  end)
+]]
+
+float 'proxy.node.http.cache_hit_revalidated_avg_10s' [[
+  local self = ...
+
+  return interval_delta_of_10s(self, function()
+    return proxy.process.http.cache_hit_revalidated
+  end)
+]]
+
+float 'proxy.node.http.cache_hit_ims_avg_10s' [[
+  local self = ...
+
+  return interval_delta_of_10s(self, function()
+    return proxy.process.http.cache_hit_ims
+  end)
+]]
+
+float 'proxy.node.http.cache_hit_stale_served_avg_10s' [[
+  local self = ...
+
+  return interval_delta_of_10s(self, function()
+    return proxy.process.http.cache_hit_stale_served
+  end)
+]]
+
+float 'proxy.node.http.cache_miss_cold_avg_10s' [[
+  local self = ...
+
+  return interval_delta_of_10s(self, function()
+    return proxy.process.http.cache_miss_cold
+  end)
+]]
+
+float 'proxy.node.http.cache_miss_changed_avg_10s' [[
+  local self = ...
+
+  return interval_delta_of_10s(self, function()
+    return proxy.process.http.cache_miss_changed
+  end)
+]]
+
+float 'proxy.node.http.cache_miss_client_no_cache_avg_10s' [[
+  local self = ...
+
+  return interval_delta_of_10s(self, function()
+    return proxy.process.http.cache_miss_client_no_cache
+  end)
+]]
+
+float 'proxy.node.http.cache_miss_ims_avg_10s' [[
+  local self = ...
+
+  return interval_delta_of_10s(self, function()
+    return proxy.process.http.cache_miss_ims
+  end)
+]]
+
+float 'proxy.node.http.cache_read_error_avg_10s' [[
+  local self = ...
+
+  return interval_delta_of_10s(self, function()
+    return proxy.process.http.cache_read_error
+  end)
+]]
+
+float 'proxy.node.cache_total_hits_avg_10s' [[
+  return
+    proxy.node.http.cache_hit_fresh_avg_10s        +
+    proxy.node.http.cache_hit_revalidated_avg_10s  +
+    proxy.node.http.cache_hit_ims_avg_10s          +
+    proxy.node.http.cache_hit_stale_served_avg_10s
+]]
+
+float 'proxy.cluster.cache_total_hits_avg_10s' [[
+  return cluster('proxy.node.cache_total_hits_avg_10s')
+]]
+
+float 'proxy.node.cache_total_hits_mem_avg_10s' [[
+  return proxy.node.http.cache_hit_mem_fresh_avg_10s
+]]
+
+float 'proxy.cluster.cache_total_hits_mem_avg_10s' [[
+  return cluster('proxy.node.cache_total_hits_mem_avg_10s')
+]]
+
+float 'proxy.node.cache_total_misses_avg_10s' [[
+  return
+    proxy.node.http.cache_miss_cold_avg_10s            +
+    proxy.node.http.cache_miss_changed_avg_10s         +
+    proxy.node.http.cache_miss_client_no_cache_avg_10s +
+    proxy.node.http.cache_miss_ims_avg_10s             +
+    proxy.node.http.cache_read_error_avg_10s
+]]
+
+float 'proxy.cluster.cache_total_misses_avg_10s' [[
+  return cluster('proxy.node.cache_total_misses_avg_10s')
+]]
+
+float 'proxy.node.cache_hit_ratio_avg_10s' [[
+  return
+    proxy.node.cache_total_hits_avg_10s   /
+    (
+    proxy.node.cache_total_hits_avg_10s   +
+    proxy.node.cache_total_misses_avg_10s
+    )
+]]
+
+float 'proxy.cluster.cache_hit_ratio_avg_10s' [[
+  return
+    cluster('proxy.node.cache_total_hits_avg_10s')   /
+    (
+    cluster('proxy.node.cache_total_hits_avg_10s')   +
+    cluster('proxy.node.cache_total_misses_avg_10s')
+    )
+]]
+
+float 'proxy.node.cache_hit_mem_ratio_avg_10s' [[
+  return
+    proxy.node.cache_total_hits_mem_avg_10s   /
+    (
+    proxy.node.cache_total_hits_avg_10s   +
+    proxy.node.cache_total_misses_avg_10s
+    )
+]]
+
+float 'proxy.cluster.cache_hit_mem_ratio_avg_10s' [[
+  return
+    cluster('proxy.node.cache_total_hits_mem_avg_10s')   /
+    (
+    cluster('proxy.node.cache_total_hits_avg_10s')   +
+    cluster('proxy.node.cache_total_misses_avg_10s')
+    )
+]]
+
+integer 'proxy.node.cache_hit_ratio_avg_10s_int_pct' [[
+  return proxy.node.cache_hit_ratio_avg_10s * 100
+]]
+
+integer 'proxy.node.cache_hit_mem_ratio_avg_10s_int_pct' [[
+  return proxy.node.cache_hit_mem_ratio_avg_10s * 100
+]]
+
+counter 'proxy.node.cache_total_hits' [[
+  return proxy.process.http.cache_hit_fresh +
+    proxy.process.http.cache_hit_revalidated +
+    proxy.process.http.cache_hit_ims +
+    proxy.process.http.cache_hit_stale_served
+]]
+
+counter 'proxy.cluster.cache_total_hits' [[
+  return cluster('proxy.node.cache_total_hits')
+]]
+
+counter 'proxy.node.cache_total_hits_mem' [[
+  return proxy.process.http.cache_hit_mem_fresh
+]]
+
+counter 'proxy.cluster.cache_total_hits_mem' [[
+  return cluster('proxy.node.cache_total_hits_mem')
+]]
+
+counter 'proxy.node.cache_total_misses' [[
+  return
+    proxy.process.http.cache_miss_cold            +
+    proxy.process.http.cache_miss_changed         +
+    proxy.process.http.cache_miss_client_no_cache +
+    proxy.process.http.cache_miss_ims             +
+    proxy.process.http.cache_read_error
+]]
+
+counter 'proxy.cluster.cache_total_misses' [[
+  return
+    cluster('proxy.node.http.cache_miss_cold')            +
+    cluster('proxy.node.http.cache_miss_changed')         +
+    cluster('proxy.node.http.cache_miss_client_no_cache') +
+    cluster('proxy.node.http.cache_miss_ims')             +
+    cluster('proxy.node.http.cache_read_error')
+]]
+
+float 'proxy.node.cache_hit_ratio' [[
+  return
+    proxy.node.cache_total_hits   /
+    (
+      proxy.node.cache_total_hits   +
+      proxy.node.cache_total_misses
+    )
+]]
+
+float 'proxy.cluster.cache_hit_ratio' [[
+  return
+    cluster('proxy.node.cache_total_hits')   /
+    (
+      cluster('proxy.node.cache_total_hits')   +
+      cluster('proxy.node.cache_total_misses')
+    )
+]]
+
+float 'proxy.node.cache_hit_mem_ratio' [[
+  return
+    proxy.node.cache_total_hits_mem   /
+    (
+    proxy.node.cache_total_hits   +
+    proxy.node.cache_total_misses
+    )
+]]
+
+float 'proxy.cluster.cache_hit_mem_ratio' [[
+  return
+    cluster('proxy.node.cache_total_hits_mem')   /
+    (
+    cluster('proxy.node.cache_total_hits')   +
+    cluster('proxy.node.cache_total_misses')
+    )
+]]
+
+-- StatAggregation::Ag_cachePercent().
+integer 'proxy.node.cache.bytes_free' [[
+  return
+    proxy.process.cache.bytes_total -
+    proxy.process.cache.bytes_used
+]]
+
+float 'proxy.node.cache.percent_free' [[
+  return
+    proxy.node.cache.bytes_free /
+    proxy.process.cache.bytes_total
+]]
+
+float 'proxy.cluster.cache.percent_free' [[
+  return
+    cluster('proxy.node.cache.bytes_free') /
+    cluster('proxy.node.cache.bytes_total')
+]]
+
+-- StatAggregation::Ag_TransactionPercentsAndMeanTimes()
+
+integer 'proxy.node.http.transaction_counts_avg_10s.hit_fresh' [[
+  return interval_delta_of_10s(..., function()
+    return proxy.process.http.transaction_counts.hit_fresh
+  end)
+]]
+
+integer 'proxy.node.http.transaction_counts_avg_10s.hit_revalidated' [[
+  return interval_delta_of_10s(..., function()
+    return proxy.process.http.transaction_counts.hit_revalidated
+  end)
+]]
+
+integer 'proxy.node.http.transaction_counts_avg_10s.miss_cold' [[
+  return interval_delta_of_10s(..., function()
+    return proxy.process.http.transaction_counts.miss_cold
+  end)
+]]
+
+integer 'proxy.node.http.transaction_counts_avg_10s.miss_changed' [[
+  return interval_delta_of_10s(..., function()
+    return proxy.process.http.transaction_counts.miss_changed
+  end)
+]]
+
+integer 'proxy.node.http.transaction_counts_avg_10s.miss_client_no_cache' [[
+  return interval_delta_of_10s(..., function()
+    return proxy.process.http.transaction_counts.miss_client_no_cache
+  end)
+]]
+
+integer 'proxy.node.http.transaction_counts_avg_10s.miss_not_cacheable' [[
+  return interval_delta_of_10s(..., function()
+    return proxy.process.http.transaction_counts.miss_not_cacheable
+  end)
+]]
+
+integer 'proxy.node.http.transaction_counts_avg_10s.errors.connect_failed' [[
+  return interval_delta_of_10s(..., function()
+    return proxy.process.http.transaction_counts.errors.connect_failed
+  end)
+]]
+
+integer 'proxy.node.http.transaction_counts_avg_10s.errors.aborts' [[
+  return interval_delta_of_10s(..., function()
+    return proxy.process.http.transaction_counts.errors.aborts
+  end)
+]]
+
+integer 'proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts' [[
+  return interval_delta_of_10s(..., function()
+    return proxy.process.http.transaction_counts.errors.possible_aborts
+  end)
+]]
+
+integer 'proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups' [[
+  return interval_delta_of_10s(..., function()
+    return proxy.process.http.transaction_counts.errors.pre_accept_hangups
+  end)
+]]
+
+integer 'proxy.node.http.transaction_counts_avg_10s.errors.early_hangups' [[
+  return interval_delta_of_10s(..., function()
+    return proxy.process.http.transaction_counts.errors.early_hangups
+  end)
+]]
+
+integer 'proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups' [[
+  return interval_delta_of_10s(..., function()
+    return proxy.process.http.transaction_counts.errors.empty_hangups
+  end)
+]]
+
+integer 'proxy.node.http.transaction_counts_avg_10s.errors.errors' [[
+  return interval_delta_of_10s(..., function()
+    return proxy.process.http.transaction_counts.errors.errors
+  end)
+]]
+
+-- StatAggregation.cc::frac_names()
+float 'proxy.node.http.transaction_frac_avg_10s.hit_fresh' [[
+  return interval_of_10s(..., function()
+    return
+      proxy.node.http.transaction_counts_avg_10s.hit_fresh /
+      (
+      proxy.node.http.transaction_counts_avg_10s.hit_fresh                 +
+      proxy.node.http.transaction_counts_avg_10s.hit_revalidated           +
+      proxy.node.http.transaction_counts_avg_10s.miss_cold                 +
+      proxy.node.http.transaction_counts_avg_10s.miss_changed              +
+      proxy.node.http.transaction_counts_avg_10s.miss_client_no_cache      +
+      proxy.node.http.transaction_counts_avg_10s.miss_not_cacheable        +
+      proxy.node.http.transaction_counts_avg_10s.errors.connect_failed     +
+      proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
+      proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
+      proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
+      proxy.node.http.transaction_counts_avg_10s.errors.early_hangups      +
+      proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
+      proxy.node.http.transaction_counts_avg_10s.errors.other
+      )
+  end)
+]]
+
+float 'proxy.node.http.transaction_frac_avg_10s.hit_revalidated' [[
+  return interval_of_10s(..., function()
+    return
+      proxy.node.http.transaction_counts_avg_10s.hit_revalidated /
+      (
+      proxy.node.http.transaction_counts_avg_10s.hit_fresh                 +
+      proxy.node.http.transaction_counts_avg_10s.hit_revalidated           +
+      proxy.node.http.transaction_counts_avg_10s.miss_cold                 +
+      proxy.node.http.transaction_counts_avg_10s.miss_changed              +
+      proxy.node.http.transaction_counts_avg_10s.miss_client_no_cache      +
+      proxy.node.http.transaction_counts_avg_10s.miss_not_cacheable        +
+      proxy.node.http.transaction_counts_avg_10s.errors.connect_failed     +
+      proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
+      proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
+      proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
+      proxy.node.http.transaction_counts_avg_10s.errors.early_hangups      +
+      proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
+      proxy.node.http.transaction_counts_avg_10s.errors.other
+      )
+  end)
+]]
+
+float 'proxy.node.http.transaction_frac_avg_10s.miss_cold' [[
+  return interval_of_10s(..., function()
+    return
+      proxy.node.http.transaction_counts_avg_10s.miss_cold /
+      (
+      proxy.node.http.transaction_counts_avg_10s.hit_fresh                 +
+      proxy.node.http.transaction_counts_avg_10s.hit_revalidated           +
+      proxy.node.http.transaction_counts_avg_10s.miss_cold                 +
+      proxy.node.http.transaction_counts_avg_10s.miss_changed              +
+      proxy.node.http.transaction_counts_avg_10s.miss_client_no_cache      +
+      proxy.node.http.transaction_counts_avg_10s.miss_not_cacheable        +
+      proxy.node.http.transaction_counts_avg_10s.errors.connect_failed     +
+      proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
+      proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
+      proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
+      proxy.node.http.transaction_counts_avg_10s.errors.early_hangups      +
+      proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
+      proxy.node.http.transaction_counts_avg_10s.errors.other
+      )
+  end)
+]]
+
+float 'proxy.node.http.transaction_frac_avg_10s.miss_changed' [[
+  return interval_of_10s(..., function()
+    proxy.node.http.transaction_counts_avg_10s.miss_changed /
+    (
+    proxy.node.http.transaction_counts_avg_10s.hit_fresh                 +
+    proxy.node.http.transaction_counts_avg_10s.hit_revalidated           +
+    proxy.node.http.transaction_counts_avg_10s.miss_cold                 +
+    proxy.node.http.transaction_counts_avg_10s.miss_changed              +
+    proxy.node.http.transaction_counts_avg_10s.miss_client_no_cache      +
+    proxy.node.http.transaction_counts_avg_10s.miss_not_cacheable        +
+    proxy.node.http.transaction_counts_avg_10s.errors.connect_failed     +
+    proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
+    proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
+    proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
+    proxy.node.http.transaction_counts_avg_10s.errors.early_hangups      +
+    proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
+    proxy.node.http.transaction_counts_avg_10s.errors.other
+    )
+  end)
+]]
+
+float 'proxy.node.http.transaction_frac_avg_10s.miss_client_no_cache' [[
+  return interval_of_10s(..., function()
+    return
+      proxy.node.http.transaction_counts_avg_10s.miss_client_no_cache /
+      (
+      proxy.node.http.transaction_counts_avg_10s.hit_fresh                 +
+      proxy.node.http.transaction_counts_avg_10s.hit_revalidated           +
+      proxy.node.http.transaction_counts_avg_10s.miss_cold                 +
+      proxy.node.http.transaction_counts_avg_10s.miss_changed              +
+      proxy.node.http.transaction_counts_avg_10s.miss_client_no_cache      +
+      proxy.node.http.transaction_counts_avg_10s.miss_not_cacheable        +
+      proxy.node.http.transaction_counts_avg_10s.errors.connect_failed     +
+      proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
+      proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
+      proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
+      proxy.node.http.transaction_counts_avg_10s.errors.early_hangups      +
+      proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
+      proxy.node.http.transaction_counts_avg_10s.errors.other
+      )
+  end)
+]]
+
+float 'proxy.node.http.transaction_frac_avg_10s.miss_not_cacheable' [[
+  return interval_of_10s(..., function()
+    return
+      proxy.node.http.transaction_counts_avg_10s.miss_not_cacheable /
+      (
+      proxy.node.http.transaction_counts_avg_10s.hit_fresh                 +
+      proxy.node.http.transaction_counts_avg_10s.hit_revalidated           +
+      proxy.node.http.transaction_counts_avg_10s.miss_cold                 +
+      proxy.node.http.transaction_counts_avg_10s.miss_changed              +
+      proxy.node.http.transaction_counts_avg_10s.miss_client_no_cache      +
+      proxy.node.http.transaction_counts_avg_10s.miss_not_cacheable        +
+      proxy.node.http.transaction_counts_avg_10s.errors.connect_failed     +
+      proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
+      proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
+      proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
+      proxy.node.http.transaction_counts_avg_10s.errors.early_hangups      +
+      proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
+      proxy.node.http.transaction_counts_avg_10s.errors.other
+      )
+  end)
+]]
+
+float 'proxy.node.http.transaction_frac_avg_10s.errors.connect_failed' [[
+  return interval_of_10s(..., function()
+    return
+      proxy.node.http.transaction_counts_avg_10s.errors.connect_failed /
+      (
+      proxy.node.http.transaction_counts_avg_10s.hit_fresh                 +
+      proxy.node.http.transaction_counts_avg_10s.hit_revalidated           +
+      proxy.node.http.transaction_counts_avg_10s.miss_cold                 +
+      proxy.node.http.transaction_counts_avg_10s.miss_changed              +
+      proxy.node.http.transaction_counts_avg_10s.miss_client_no_cache      +
+      proxy.node.http.transaction_counts_avg_10s.miss_not_cacheable        +
+      proxy.node.http.transaction_counts_avg_10s.errors.connect_failed     +
+      proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
+      proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
+      proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
+      proxy.node.http.transaction_counts_avg_10s.errors.early_hangups      +
+      proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
+      proxy.node.http.transaction_counts_avg_10s.errors.other
+      )
+    end)
+]]
+
+float 'proxy.node.http.transaction_frac_avg_10s.errors.aborts' [[
+  return interval_of_10s(..., function()
+    return
+      proxy.node.http.transaction_counts_avg_10s.errors.aborts /
+      (
+      proxy.node.http.transaction_counts_avg_10s.hit_fresh                 +
+      proxy.node.http.transaction_counts_avg_10s.hit_revalidated           +
+      proxy.node.http.transaction_counts_avg_10s.miss_cold                 +
+      proxy.node.http.transaction_counts_avg_10s.miss_changed              +
+      proxy.node.http.transaction_counts_avg_10s.miss_client_no_cache      +
+      proxy.node.http.transaction_counts_avg_10s.miss_not_cacheable        +
+      proxy.node.http.transaction_counts_avg_10s.errors.connect_failed     +
+      proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
+      proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
+      proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
+      proxy.node.http.transaction_counts_avg_10s.errors.early_hangups      +
+      proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
+      proxy.node.http.transaction_counts_avg_10s.errors.other
+      )
+    end)
+]]
+
+float 'proxy.node.http.transaction_frac_avg_10s.errors.possible_aborts' [[
+  return interval_of_10s(..., function()
+    return
+      proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts /
+      (
+      proxy.node.http.transaction_counts_avg_10s.hit_fresh                 +
+      proxy.node.http.transaction_counts_avg_10s.hit_revalidated           +
+      proxy.node.http.transaction_counts_avg_10s.miss_cold                 +
+      proxy.node.http.transaction_counts_avg_10s.miss_changed              +
+      proxy.node.http.transaction_counts_avg_10s.miss_client_no_cache      +
+      proxy.node.http.transaction_counts_avg_10s.miss_not_cacheable        +
+      proxy.node.http.transaction_counts_avg_10s.errors.connect_failed     +
+      proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
+      proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
+      proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
+      proxy.node.http.transaction_counts_avg_10s.errors.early_hangups      +
+      proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
+      proxy.node.http.transaction_counts_avg_10s.errors.other
+      )
+    end)
+]]
+
+float 'proxy.node.http.transaction_frac_avg_10s.errors.pre_accept_hangups' [[
+  return interval_of_10s(..., function()
+    return
+      proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups /
+      (
+      proxy.node.http.transaction_counts_avg_10s.hit_fresh                 +
+      proxy.node.http.transaction_counts_avg_10s.hit_revalidated           +
+      proxy.node.http.transaction_counts_avg_10s.miss_cold                 +
+      proxy.node.http.transaction_counts_avg_10s.miss_changed              +
+      proxy.node.http.transaction_counts_avg_10s.miss_client_no_cache      +
+      proxy.node.http.transaction_counts_avg_10s.miss_not_cacheable        +
+      proxy.node.http.transaction_counts_avg_10s.errors.connect_failed     +
+      proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
+      proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
+      proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
+      proxy.node.http.transaction_counts_avg_10s.errors.early_hangups      +
+      proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
+      proxy.node.http.transaction_counts_avg_10s.errors.other
+      )
+    end)
+]]
+
+float 'proxy.node.http.transaction_frac_avg_10s.errors.early_hangups' [[
+  return interval_of_10s(..., function()
+    return
+      proxy.node.http.transaction_counts_avg_10s.errors.early_hangups /
+      (
+      proxy.node.http.transaction_counts_avg_10s.hit_fresh                 +
+      proxy.node.http.transaction_counts_avg_10s.hit_revalidated           +
+      proxy.node.http.transaction_counts_avg_10s.miss_cold                 +
+      proxy.node.http.transaction_counts_avg_10s.miss_changed              +
+      proxy.node.http.transaction_counts_avg_10s.miss_client_no_cache      +
+      proxy.node.http.transaction_counts_avg_10s.miss_not_cacheable        +
+      proxy.node.http.transaction_counts_avg_10s.errors.connect_failed     +
+      proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
+      proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
+      proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
+      proxy.node.http.transaction_counts_avg_10s.errors.early_hangups      +
+      proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
+      proxy.node.http.transaction_counts_avg_10s.errors.other
+      )
+    end)
+]]
+
+float 'proxy.node.http.transaction_frac_avg_10s.errors.empty_hangups' [[
+  return interval_of_10s(..., function()
+    return
+      proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups /
+      (
+      proxy.node.http.transaction_counts_avg_10s.hit_fresh                 +
+      proxy.node.http.transaction_counts_avg_10s.hit_revalidated           +
+      proxy.node.http.transaction_counts_avg_10s.miss_cold                 +
+      proxy.node.http.transaction_counts_avg_10s.miss_changed              +
+      proxy.node.http.transaction_counts_avg_10s.miss_client_no_cache      +
+      proxy.node.http.transaction_counts_avg_10s.miss_not_cacheable        +
+      proxy.node.http.transaction_counts_avg_10s.errors.connect_failed     +
+      proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
+      proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
+      proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
+      proxy.node.http.transaction_counts_avg_10s.errors.early_hangups      +
+      proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
+      proxy.node.http.transaction_counts_avg_10s.errors.other
+      )
+    end)
+]]
+
+float 'proxy.node.http.transaction_frac_avg_10s.errors.other' [[
+  return interval_of_10s(..., function()
+    return
+      proxy.node.http.transaction_counts_avg_10s.errors.other /
+      (
+      proxy.node.http.transaction_counts_avg_10s.hit_fresh                 +
+      proxy.node.http.transaction_counts_avg_10s.hit_revalidated           +
+      proxy.node.http.transaction_counts_avg_10s.miss_cold                 +
+      proxy.node.http.transaction_counts_avg_10s.miss_changed              +
+      proxy.node.http.transaction_counts_avg_10s.miss_client_no_cache      +
+      proxy.node.http.transaction_counts_avg_10s.miss_not_cacheable        +
+      proxy.node.http.transaction_counts_avg_10s.errors.connect_failed     +
+      proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
+      proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
+      proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
+      proxy.node.http.transaction_counts_avg_10s.errors.early_hangups      +
+      proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
+      proxy.node.http.transaction_counts_avg_10s.errors.other
+      )
+    end)
+]]
+
+integer 'proxy.node.http.transaction_frac_avg_10s.hit_fresh_int_pct' [[
+  return proxy.node.http.transaction_frac_avg_10s.hit_fresh * 100
+]]
+
+integer 'proxy.node.http.transaction_frac_avg_10s.miss_cold_int_pct' [[
+  return proxy.node.http.transaction_frac_avg_10s.miss_cold * 100
+]]
+
+integer 'proxy.node.http.transaction_frac_avg_10s.hit_revalidated_int_pct' [[
+  return proxy.node.http.transaction_frac_avg_10s.hit_revalidated * 100
+]]
+
+integer 'proxy.node.http.transaction_frac_avg_10s.miss_changed_int_pct' [[
+  return proxy.node.http.transaction_frac_avg_10s.miss_changed * 100
+]]
+
+integer 'proxy.node.http.transaction_frac_avg_10s.miss_client_no_cache_int_pct' [[
+  return proxy.node.http.transaction_frac_avg_10s.miss_client_no_cache * 100
+]]
+
+integer 'proxy.node.http.transaction_frac_avg_10s.miss_not_cacheable_int_pct' [[
+  return proxy.node.http.transaction_frac_avg_10s.miss_not_cacheable * 100
+]]
+
+integer 'proxy.node.http.transaction_frac_avg_10s.errors.connect_failed_int_pct' [[
+  return proxy.node.http.transaction_frac_avg_10s.errors.connect_failed * 100
+]]
+
+integer 'proxy.node.http.transaction_frac_avg_10s.errors.aborts_int_pct' [[
+  return proxy.node.http.transaction_frac_avg_10s.errors.aborts * 100
+]]
+
+integer 'proxy.node.http.transaction_frac_avg_10s.errors.possible_aborts_int_pct' [[
+  return proxy.node.http.transaction_frac_avg_10s.errors.possible_aborts * 100
+]]
+
+integer 'proxy.node.http.transaction_frac_avg_10s.errors.pre_accept_hangups_int_pct' [[
+  return proxy.node.http.transaction_frac_avg_10s.errors.pre_accept_hangups * 100
+]]
+
+integer 'proxy.node.http.transaction_frac_avg_10s.errors.early_hangups_int_pct' [[
+  return proxy.node.http.transaction_frac_avg_10s.errors.early_hangups * 100
+]]
+
+integer 'proxy.node.http.transaction_frac_avg_10s.errors.empty_hangups_int_pct' [[
+  return proxy.node.http.transaction_frac_avg_10s.errors.empty_hangups * 100
+]]
+
+integer 'proxy.node.http.transaction_frac_avg_10s.errors.other_int_pct' [[
+  return proxy.node.http.transaction_frac_avg_10s.errors.other * 100
+]]
+
+integer 'proxy.node.http.transaction_msec_avg_10s.hit_fresh' [[
+  local self = ...
+  return interval_of_10s(self, function()
+    return
+      sec_to_msec                  *
+      delta_of(self, function()
+        return proxy.process.http.transaction_totaltime.hit_fresh
+      end) /
+      (
+      proxy.node.http.transaction_counts_avg_10s.hit_fresh                 +
+      proxy.node.http.transaction_counts_avg_10s.hit_revalidated           +
+      proxy.node.http.transaction_counts_avg_10s.miss_cold                 +
+      proxy.node.http.transaction_counts_avg_10s.miss_changed              +
+      proxy.node.http.transaction_counts_avg_10s.miss_client_no_cache      +
+      proxy.node.http.transaction_counts_avg_10s.miss_not_cacheable        +
+      proxy.node.http.transaction_counts_avg_10s.errors.connect_failed     +
+      proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
+      proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
+      proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
+      proxy.node.http.transaction_counts_avg_10s.errors.early_hangups      +
+      proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
+      proxy.node.http.transaction_counts_avg_10s.errors.other
+      )
+    end)
+]]
+
+integer 'proxy.node.http.transaction_msec_avg_10s.hit_revalidated' [[
+  local self = ...
+  return interval_of_10s(self, function()
+    return
+      sec_to_msec         *
+      delta_of(self, function()
+        return proxy.process.http.transaction_totaltime.hit_revalidated
+      end) /
+      (
+      proxy.node.http.transaction_counts_avg_10s.hit_fresh                 +
+      proxy.node.http.transaction_counts_avg_10s.hit_revalidated           +
+      proxy.node.http.transaction_counts_avg_10s.miss_cold                 +
+      proxy.node.http.transaction_counts_avg_10s.miss_changed              +
+      proxy.node.http.transaction_counts_avg_10s.miss_client_no_cache      +
+      proxy.node.http.transaction_counts_avg_10s.miss_not_cacheable        +
+      proxy.node.http.transaction_counts_avg_10s.errors.connect_failed     +
+      proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
+      proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
+      proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
+      proxy.node.http.transaction_counts_avg_10s.errors.early_hangups      +
+      proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
+      proxy.node.http.transaction_counts_avg_10s.errors.other
+      )
+    end)
+]]
+
+integer 'proxy.node.http.transaction_msec_avg_10s.miss_cold' [[
+  local self = ...
+  return interval_of_10s(self, function()
+    return
+      sec_to_msec   *
+      delta_of(self, function()
+        proxy.process.http.transaction_totaltime.miss_cold
+      end) /
+      (
+      proxy.node.http.transaction_counts_avg_10s.hit_fresh                 +
+      proxy.node.http.transaction_counts_avg_10s.hit_revalidated           +
+      proxy.node.http.transaction_counts_avg_10s.miss_cold                 +
+      proxy.node.http.transaction_counts_avg_10s.miss_changed              +
+      proxy.node.http.transaction_counts_avg_10s.miss_client_no_cache      +
+      proxy.node.http.transaction_counts_avg_10s.miss_not_cacheable        +
+      proxy.node.http.transaction_counts_avg_10s.errors.connect_failed     +
+      proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
+      proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
+      proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
+      proxy.node.http.transaction_counts_avg_10s.errors.early_hangups      +
+      proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
+      proxy.node.http.transaction_counts_avg_10s.errors.other
+      )
+    end)
+]]
+
+integer 'proxy.node.http.transaction_msec_avg_10s.miss_changed' [[
+  local self = ...
+  return interval_of_10s(self, function()
+    return
+      sec_to_msec   *
+      delta_of(self, function()
+        return proxy.process.http.transaction_totaltime.miss_changed
+      end) /
+      (
+      proxy.node.http.transaction_counts_avg_10s.hit_fresh                 +
+      proxy.node.http.transaction_counts_avg_10s.hit_revalidated           +
+      proxy.node.http.transaction_counts_avg_10s.miss_cold                 +
+      proxy.node.http.transaction_counts_avg_10s.miss_changed              +
+      proxy.node.http.transaction_counts_avg_10s.miss_client_no_cache      +
+      proxy.node.http.transaction_counts_avg_10s.miss_not_cacheable        +
+      proxy.node.http.transaction_counts_avg_10s.errors.connect_failed     +
+      proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
+      proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
+      proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
+      proxy.node.http.transaction_counts_avg_10s.errors.early_hangups      +
+      proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
+      proxy.node.http.transaction_counts_avg_10s.errors.other
+      )
+    end)
+]]
+
+integer 'proxy.node.http.transaction_msec_avg_10s.miss_client_no_cache' [[
+  local self = ...
+  return interval_of_10s(self, function()
+    return
+      sec_to_msec              *
+      delta_of(self, function()
+        return proxy.process.http.transaction_totaltime.miss_client_no_cache
+      end) /
+      (
+      proxy.node.http.transaction_counts_avg_10s.hit_fresh                 +
+      proxy.node.http.transaction_counts_avg_10s.hit_revalidated           +
+      proxy.node.http.transaction_counts_avg_10s.miss_cold                 +
+      proxy.node.http.transaction_counts_avg_10s.miss_changed              +
+      proxy.node.http.transaction_counts_avg_10s.miss_client_no_cache      +
+      proxy.node.http.transaction_counts_avg_10s.miss_not_cacheable        +
+      proxy.node.http.transaction_counts_avg_10s.errors.connect_failed     +
+      proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
+      proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
+      proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
+      proxy.node.http.transaction_counts_avg_10s.errors.early_hangups      +
+      proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
+      proxy.node.http.transaction_counts_avg_10s.errors.other
+      )
+    end)
+]]
+
+integer 'proxy.node.http.transaction_msec_avg_10s.miss_not_cacheable' [[
+  local self = ...
+  return interval_of_10s(self, function()
+    return
+      sec_to_msec            *
+      delta_of)self, function()
+        return proxy.process.http.transaction_totaltime.miss_not_cacheable
+      end) /
+      (
+      proxy.node.http.transaction_counts_avg_10s.hit_fresh                 +
+      proxy.node.http.transaction_counts_avg_10s.hit_revalidated           +
+      proxy.node.http.transaction_counts_avg_10s.miss_cold                 +
+      proxy.node.http.transaction_counts_avg_10s.miss_changed              +
+      proxy.node.http.transaction_counts_avg_10s.miss_client_no_cache      +
+      proxy.node.http.transaction_counts_avg_10s.miss_not_cacheable        +
+      proxy.node.http.transaction_counts_avg_10s.errors.connect_failed     +
+      proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
+      proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
+      proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
+      proxy.node.http.transaction_counts_avg_10s.errors.early_hangups      +
+      proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
+      proxy.node.http.transaction_counts_avg_10s.errors.other
+      )
+    end)
+]]
+
+integer 'proxy.node.http.transaction_msec_avg_10s.errors.connect_failed' [[
+  local self = ...
+  return interval_of_10s(self, function()
+    return
+      sec_to_msec               *
+      delta_of(self, function()
+        return proxy.process.http.transaction_totaltime.errors.connect_failed
+      end) /
+      (
+      proxy.node.http.transaction_counts_avg_10s.hit_fresh                 +
+      proxy.node.http.transaction_counts_avg_10s.hit_revalidated           +
+      proxy.node.http.transaction_counts_avg_10s.miss_cold                 +
+      proxy.node.http.transaction_counts_avg_10s.miss_changed              +
+      proxy.node.http.transaction_counts_avg_10s.miss_client_no_cache      +
+      proxy.node.http.transaction_counts_avg_10s.miss_not_cacheable        +
+      proxy.node.http.transaction_counts_avg_10s.errors.connect_failed     +
+      proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
+      proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
+      proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
+      proxy.node.http.transaction_counts_avg_10s.errors.early_hangups      +
+      proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
+      proxy.node.http.transaction_counts_avg_10s.errors.other
+      )
+    end)
+]]
+
+integer 'proxy.node.http.transaction_msec_avg_10s.errors.aborts' [[
+  local self = ...
+  return interval_of_10s(self, function()
+    return
+      sec_to_msec       *
+      delta_of(self, function()
+        return proxy.process.http.transaction_totaltime.errors.aborts
+      end) /
+      (
+      proxy.node.http.transaction_counts_avg_10s.hit_fresh                 +
+      proxy.node.http.transaction_counts_avg_10s.hit_revalidated           +
+      proxy.node.http.transaction_counts_avg_10s.miss_cold                 +
+      proxy.node.http.transaction_counts_avg_10s.miss_changed              +
+      proxy.node.http.transaction_counts_avg_10s.miss_client_no_cache      +
+      proxy.node.http.transaction_counts_avg_10s.miss_not_cacheable        +
+      proxy.node.http.transaction_counts_avg_10s.errors.connect_failed     +
+      proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
+      proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
+      proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
+      proxy.node.http.transaction_counts_avg_10s.errors.early_hangups      +
+      proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
+      proxy.node.http.transaction_counts_avg_10s.errors.other
+      )
+    end)
+]]
+
+integer 'proxy.node.http.transaction_msec_avg_10s.errors.possible_aborts' [[
+  local self = ...
+  return interval_of_10s(self, function()
+    return
+      sec_to_msec                *
+      delta_of(self, function()
+        return proxy.process.http.transaction_totaltime.errors.possible_aborts
+      end) /
+      (
+      proxy.node.http.transaction_counts_avg_10s.hit_fresh                 +
+      proxy.node.http.transaction_counts_avg_10s.hit_revalidated           +
+      proxy.node.http.transaction_counts_avg_10s.miss_cold                 +
+      proxy.node.http.transaction_counts_avg_10s.miss_changed              +
+      proxy.node.http.transaction_counts_avg_10s.miss_client_no_cache      +
+      proxy.node.http.transaction_counts_avg_10s.miss_not_cacheable        +
+      proxy.node.http.transaction_counts_avg_10s.errors.connect_failed     +
+      proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
+      proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
+      proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
+      proxy.node.http.transaction_counts_avg_10s.errors.early_hangups      +
+      proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
+      proxy.node.http.transaction_counts_avg_10s.errors.other
+      )
+    end)
+]]
+
+integer 'proxy.node.http.transaction_msec_avg_10s.errors.pre_accept_hangups' [[
+  local self = ...
+  return interval_of_10s(self, function()
+    return
+      sec_to_msec                   *
+      delta_of(self, function()
+        return proxy.process.http.transaction_totaltime.errors.pre_accept_hangups
+      end) /
+      (
+      proxy.node.http.transaction_counts_avg_10s.hit_fresh                 +
+      proxy.node.http.transaction_counts_avg_10s.hit_revalidated           +
+      proxy.node.http.transaction_counts_avg_10s.miss_cold                 +
+      proxy.node.http.transaction_counts_avg_10s.miss_changed              +
+      proxy.node.http.transaction_counts_avg_10s.miss_client_no_cache      +
+      proxy.node.http.transaction_counts_avg_10s.miss_not_cacheable        +
+      proxy.node.http.transaction_counts_avg_10s.errors.connect_failed     +
+      proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
+      proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
+      proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
+      proxy.node.http.transaction_counts_avg_10s.errors.early_hangups      +
+      proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
+      proxy.node.http.transaction_counts_avg_10s.errors.other
+      )
+    end)
+]]
+
+integer 'proxy.node.http.transaction_msec_avg_10s.errors.early_hangups' [[
+  local self = ...
+  return interval_of_10s(self, function()
+    return
+      sec_to_msec              *
+      delta_of(self, function()
+        self proxy.process.http.transaction_totaltime.errors.early_hangups
+      end) /
+      (
+      proxy.node.http.transaction_counts_avg_10s.hit_fresh                 +
+      proxy.node.http.transaction_counts_avg_10s.hit_revalidated           +
+      proxy.node.http.transaction_counts_avg_10s.miss_cold                 +
+      proxy.node.http.transaction_counts_avg_10s.miss_changed              +
+      proxy.node.http.transaction_counts_avg_10s.miss_client_no_cache      +
+      proxy.node.http.transaction_counts_avg_10s.miss_not_cacheable        +
+      proxy.node.http.transaction_counts_avg_10s.errors.connect_failed     +
+      proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
+      proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
+      proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
+      proxy.node.http.transaction_counts_avg_10s.errors.early_hangups      +
+      proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
+      proxy.node.http.transaction_counts_avg_10s.errors.other
+      )
+    end)
+]]
+
+integer 'proxy.node.http.transaction_msec_avg_10s.errors.empty_hangups' [[
+  local self = ...
+  return interval_of_10s(self, function()
+    return
+      sec_to_msec              *
+      delta_of(self, function()
+        return proxy.process.http.transaction_totaltime.errors.empty_hangups
+      end) /
+      (
+      proxy.node.http.transaction_counts_avg_10s.hit_fresh                 +
+      proxy.node.http.transaction_counts_avg_10s.hit_revalidated           +
+      proxy.node.http.transaction_counts_avg_10s.miss_cold                 +
+      proxy.node.http.transaction_counts_avg_10s.miss_changed              +
+      proxy.node.http.transaction_counts_avg_10s.miss_client_no_cache      +
+      proxy.node.http.transaction_counts_avg_10s.miss_not_cacheable        +
+      proxy.node.http.transaction_counts_avg_10s.errors.connect_failed     +
+      proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
+      proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
+      proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
+      proxy.node.http.transaction_counts_avg_10s.errors.early_hangups      +
+      proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
+      proxy.node.http.transaction_counts_avg_10s.errors.other
+      )
+    end)
+]]
+
+integer 'proxy.node.http.transaction_msec_avg_10s.errors.other' [[
+  local self = ...
+  return interval_of_10s(self, function()
+    return
+      sec_to_msec      *
+      delta_of(self, function()
+        return proxy.process.http.transaction_totaltime.errors.other
+      end) /
+      (
+      proxy.node.http.transaction_counts_avg_10s.hit_fresh                 +
+      proxy.node.http.transaction_counts_avg_10s.hit_revalidated           +
+      proxy.node.http.transaction_counts_avg_10s.miss_cold                 +
+      proxy.node.http.transaction_counts_avg_10s.miss_changed              +
+      proxy.node.http.transaction_counts_avg_10s.miss_client_no_cache      +
+      proxy.node.http.transaction_counts_avg_10s.miss_not_cacheable        +
+      proxy.node.http.transaction_counts_avg_10s.errors.connect_failed     +
+      proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
+      proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
+      proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
+      proxy.node.http.transaction_counts_avg_10s.errors.early_hangups      +
+      proxy.node.http.transaction_counts_avg_10s.errors.empty_hangups      +
+      proxy.node.http.transaction_counts_avg_10s.errors.other
+      )
+    end)
+]]
+
+-- StatAggregation::Ag_Connections().
+
+integer 'proxy.node.current_client_connections' [[
+  return proxy.node.http.user_agent_current_connections_count
+]]
+
+integer 'proxy.cluster.current_client_connections' [[
+  return cluster('proxy.node.current_client_connections')
+]]
+
+integer 'proxy.node.current_server_connections' [[
+  return
+    proxy.node.http.origin_server_current_connections_count +
+    proxy.node.http.current_parent_proxy_connections
+]]
+
+integer 'proxy.cluster.current_server_connections' [[
+  return cluster('proxy.node.current_server_connections')
+]]
+
+integer 'proxy.node.current_cache_connections' [[
+  return
+    proxy.node.http.cache_current_connections_count
+]]
+
+integer 'proxy.cluster.current_cache_connections' [[
+  return cluster('proxy.node.current_cache_connections')
+]]
+
+integer 'proxy.node.client_throughput_out_kbit' [[
+  -- Convert Mbit/sec to Kbit/sec.
+  return proxy.node.client_throughput_out * 1000
+]]
+
+integer 'proxy.cluster.client_throughput_out_kbit' [[
+  return cluster('proxy.node.client_throughput_out_kbit')
+]]
+
+-- If proxy.node.cache_hit_ratio represents 100% as 1.0, this
+-- represents it as 100.
+integer 'proxy.node.cache_hit_ratio_int_pct' [[
+    return proxy.node.cache_hit_ratio * 100
+]]
+
+integer 'proxy.cluster.cache_hit_ratio_int_pct' [[
+  return proxy.cluster.cache_hit_ratio * 100
+]]
+
+integer 'proxy.node.cache_hit_mem_ratio_int_pct' [[
+  return proxy.node.cache_hit_mem_ratio * 100
+]]
+
+integer 'proxy.cluster.cache_hit_mem_ratio_int_pct' [[
+  return proxy.node.cache_hit_mem_ratio * 100
+]]
+
+integer 'proxy.node.bandwidth_hit_ratio_int_pct' [[
+  return proxy.node.bandwidth_hit_ratio * 100
+]]
+
+integer 'proxy.cluster.bandwidth_hit_ratio_int_pct' [[
+  return proxy.cluster.bandwidth_hit_ratio * 100
+]]
+
+integer 'proxy.node.cache.percent_free_int_pct' [[
+  return proxy.node.cache.percent_free * 100
+]]
+
+integer 'proxy.cluster.cache.percent_free_int_pct' [[
+  return proxy.cluster.cache.percent_free * 100
+]]
+
+integer 'proxy.node.hostdb.hit_ratio_int_pct' [[
+  return proxy.node.hostdb.hit_ratio * 100
+]]
+
+integer 'proxy.cluster.hostdb.hit_ratio_int_pct' [[
+  return proxy.cluster.hostdb.hit_ratio * 100
+]]
+
+integer 'proxy.node.cache.bytes_total_mb' [[
+  return mbytes(proxy.process.cache.bytes_total)
+]]
+
+integer 'proxy.node.cache.bytes_free_mb' [[
+  return mbytes(proxy.node.cache.bytes_free)
+]]
+
+integer 'proxy.cluster.cache.bytes_free_mb' [[
+  return mbytes(proxy.cluster.cache.bytes_free)
+]]
+
+integer 'proxy.cluster.http.current_parent_proxy_connections' [[
+  return cluster('proxy.node.http.current_parent_proxy_connections')
+]]
+
+counter 'proxy.cluster.http.parent_proxy_total_request_bytes' [[
+  return cluster('proxy.node.http.parent_proxy_total_request_bytes')
+]]
+
+counter 'proxy.cluster.http.parent_proxy_total_response_bytes' [[
+  return cluster('proxy.node.http.parent_proxy_total_response_bytes')
+]]
+
+-- Logging.
+counter 'proxy.node.log.event_log_access_ok' [[
+  return proxy.process.log.event_log_access_ok
+]]
+
+counter 'proxy.cluster.log.event_log_access_ok' [[
+  return cluster('proxy.node.log.event_log_access_ok')
+]]
+
+counter 'proxy.node.log.event_log_access_skip' [[
+  return proxy.process.log.event_log_access_skip
+]]
+
+counter 'proxy.cluster.log.event_log_access_skip' [[
+  return cluster('proxy.node.log.event_log_access_skip')
+]]
+
+counter 'proxy.node.log.event_log_access_aggr' [[
+  return proxy.process.log.event_log_access_aggr
+]]
+
+counter 'proxy.cluster.log.event_log_access_aggr' [[
+  return cluster('proxy.node.log.event_log_access_aggr')
+]]
+
+counter 'proxy.node.log.event_log_access_full' [[
+  return proxy.process.log.event_log_access_full
+]]
+
+counter 'proxy.cluster.log.event_log_access_full' [[
+  return cluster('proxy.node.log.event_log_access_full')
+]]
+
+counter 'proxy.node.log.event_log_access_fail' [[
+  return proxy.process.log.event_log_access_fail
+]]
+
+counter 'proxy.cluster.log.event_log_access_fail' [[
+  return cluster('proxy.node.log.event_log_access_fail')
+]]
+
+counter 'proxy.node.log.num_lost_before_sent_to_network' [[
+  return proxy.process.log.num_lost_before_sent_to_network
+]]
+
+counter 'proxy.cluster.log.num_lost_before_sent_to_network' [[
+  return cluster('proxy.node.log.num_lost_before_sent_to_network')
+]]
+
+counter 'proxy.node.log.num_sent_to_network' [[
+  return proxy.process.log.num_sent_to_network
+]]
+
+counter 'proxy.cluster.log.num_sent_to_network' [[
+  return cluster('proxy.node.log.num_sent_to_network')
+]]
+
+counter 'proxy.node.log.bytes_lost_before_sent_to_network' [[
+  return proxy.process.log.bytes_lost_before_sent_to_network
+]]
+
+counter 'proxy.cluster.log.bytes_lost_before_sent_to_network' [[
+  return cluster('proxy.node.log.bytes_lost_before_sent_to_network')
+]]
+
+counter 'proxy.node.log.bytes_sent_to_network' [[
+  return proxy.process.log.bytes_sent_to_network
+]]
+
+counter 'proxy.cluster.log.bytes_sent_to_network' [[
+  return cluster('proxy.node.log.bytes_sent_to_network')
+]]
+
+counter 'proxy.node.log.num_received_from_network' [[
+  return proxy.process.log.num_received_from_network
+]]
+
+counter 'proxy.cluster.log.num_received_from_network' [[
+  return cluster('proxy.node.log.num_received_from_network')
+]]
+
+counter 'proxy.node.log.bytes_received_from_network' [[
+  return proxy.process.log.bytes_received_from_network
+]]
+
+counter 'proxy.cluster.log.bytes_received_from_network' [[
+  return cluster('proxy.node.log.bytes_received_from_network')
+]]
+
+counter 'proxy.node.log.bytes_lost_before_preproc' [[
+  return proxy.process.log.bytes_lost_before_preproc
+]]
+
+counter 'proxy.cluster.log.bytes_lost_before_preproc' [[
+  return cluster('proxy.node.log.bytes_lost_before_preproc')
+]]
+
+counter 'proxy.node.log.num_lost_before_flush_to_disk' [[
+  return proxy.process.log.num_lost_before_flush_to_disk
+]]
+
+counter 'proxy.cluster.log.num_lost_before_flush_to_disk' [[
+  return cluster('proxy.node.log.bytes_lost_before_preproc')
+]]
+
+counter 'proxy.node.log.bytes_lost_before_flush_to_disk' [[
+  return proxy.process.log.bytes_lost_before_flush_to_disk
+]]
+
+counter 'proxy.cluster.log.bytes_lost_before_flush_to_disk' [[
+  return cluster('proxy.node.log.bytes_lost_before_preproc')
+]]
+
+counter 'proxy.node.log.bytes_lost_before_written_to_disk' [[
+  return proxy.process.log.bytes_lost_before_written_to_disk
+]]
+
+counter 'proxy.cluster.log.bytes_lost_before_written_to_disk' [[
+  return cluster('proxy.node.log.bytes_lost_before_written_to_disk')
+]]
+
+integer 'proxy.node.log.bytes_sent_to_network_avg_10s' [[
+  return interval_delta_of_10s(..., function()
+    return proxy.process.log.bytes_sent_to_network
+  end)
+]]
+
+integer 'proxy.cluster.log.bytes_sent_to_network_avg_10s' [[
+  return cluster(' proxy.node.log.bytes_sent_to_network_avg_10s')
+]]
+
+integer 'proxy.node.log.bytes_received_from_network_avg_10s' [[
+  return interval_delta_of_10s(..., function()
+    return proxy.process.log.bytes_received_from_network
+  end)
+]]
+
+integer 'proxy.cluster.log.bytes_received_from_network_avg_10s' [[
+  return cluster('proxy.node.log.bytes_received_from_network_avg_10s')
+]]
+
+counter 'proxy.process.ssl.total_success_handshake_count_in' [[
+  return proxy.process.ssl.total_success_handshake_count
+]]


[08/10] trafficserver git commit: TS-4099: add automatic metrics namespace management

Posted by jp...@apache.org.
TS-4099: add automatic metrics namespace management

Rather than hardcoding the set of metrics namespace prefixes, poll
it at runtime. We keep polling until the namespace converges and
periodically thereafter to account for metrics created by plugins.


Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo
Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/b547b651
Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/b547b651
Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/b547b651

Branch: refs/heads/master
Commit: b547b651b662af16f6866d524b7661176e2b2e92
Parents: 4e44756
Author: James Peach <jp...@apache.org>
Authored: Wed Dec 30 16:36:24 2015 -0800
Committer: James Peach <jp...@apache.org>
Committed: Thu Jan 21 19:21:30 2016 -0800

----------------------------------------------------------------------
 cmd/traffic_manager/metrics.cc | 77 +++++++++++++++----------------------
 lib/bindings/bindings.cc       | 73 +++++++++++++++++++++++++++--------
 lib/bindings/bindings.h        |  8 ++--
 lib/bindings/metrics.cc        | 42 ++++++++++++++++++++
 lib/bindings/metrics.h         |  7 ++++
 5 files changed, 142 insertions(+), 65 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/b547b651/cmd/traffic_manager/metrics.cc
----------------------------------------------------------------------
diff --git a/cmd/traffic_manager/metrics.cc b/cmd/traffic_manager/metrics.cc
index 7bc5bec..9608a60 100644
--- a/cmd/traffic_manager/metrics.cc
+++ b/cmd/traffic_manager/metrics.cc
@@ -127,7 +127,7 @@ private:
 };
 
 struct EvaluatorList {
-  EvaluatorList() : passes(0) {}
+  EvaluatorList() : update(true), passes(0) {}
   ~EvaluatorList()
   {
     forv_Vec(Evaluator, e, this->evaluators) { delete e; }
@@ -147,15 +147,27 @@ struct EvaluatorList {
 
     forv_Vec(Evaluator, e, this->evaluators) { e->eval(L); }
 
-
     elapsed = ink_hrtime_diff(ink_get_hrtime_internal(), start);
     Debug("lua", "evaluated %u metrics in %fmsec", evaluators.length(), ink_hrtime_to_usec(elapsed) / 1000.0);
   }
 
+  bool update;
   int64_t passes;
   Vec<Evaluator *> evaluators;
 };
 
+static int
+update_metrics_namespace(lua_State *L)
+{
+  lua_Integer count;
+
+  lua_metrics_install(L);
+  count = lua_tointeger(L, 1);
+  lua_pop(L, 1);
+
+  return count;
+}
+
 static int64_t
 timestamp_now_msec()
 {
@@ -305,46 +317,6 @@ metrics_cluster_sum(lua_State *L)
   return 1;
 }
 
-static void
-register_metrics_namespace(BindingInstance &binding)
-{
-  // XXX Currently known metrics namespace prefixes. Figure out a way to
-  // add new metrics nodes as new prefixes are added.
-  const char *prefixes[] = {
-    "proxy.cluster", "proxy.cluster.cache", "proxy.cluster.cache.contents", "proxy.cluster.dns", "proxy.cluster.hostdb",
-    "proxy.cluster.http", "proxy.cluster.log", "proxy.node", "proxy.node.cache", "proxy.node.cache.contents", "proxy.node.cluster",
-    "proxy.node.config", "proxy.node.config.restart_required", "proxy.node.dns", "proxy.node.hostdb", "proxy.node.http",
-    "proxy.node.http.transaction_counts_avg_10s", "proxy.node.http.transaction_counts_avg_10s.errors",
-    "proxy.node.http.transaction_counts_avg_10s.other", "proxy.node.http.transaction_frac_avg_10s",
-    "proxy.node.http.transaction_frac_avg_10s.errors", "proxy.node.http.transaction_frac_avg_10s.other",
-    "proxy.node.http.transaction_msec_avg_10s", "proxy.node.http.transaction_msec_avg_10s.errors",
-    "proxy.node.http.transaction_msec_avg_10s.other", "proxy.node.log", "proxy.node.restarts.manager", "proxy.node.restarts.proxy",
-    "proxy.node.version.manager", "proxy.process.cache", "proxy.process.cache.direntries", "proxy.process.cache.evacuate",
-    "proxy.process.cache.frags_per_doc", "proxy.process.cache.frags_per_doc.3+", "proxy.process.cache.lookup",
-    "proxy.process.cache.ram_cache", "proxy.process.cache.read", "proxy.process.cache.read_busy", "proxy.process.cache.remove",
-    "proxy.process.cache.scan", "proxy.process.cache.sync", "proxy.process.cache.update", "proxy.process.cache.write",
-    "proxy.process.cache.write.backlog", "proxy.process.cluster", "proxy.process.congestion", "proxy.process.dns",
-    "proxy.process.hostdb", "proxy.process.http", "proxy.process.http.milestone", "proxy.process.http.transaction_counts",
-    "proxy.process.http.transaction_counts.errors", "proxy.process.http.transaction_counts.hit_fresh",
-    "proxy.process.http.transaction_counts.other", "proxy.process.http.transaction_totaltime",
-    "proxy.process.http.transaction_totaltime.errors", "proxy.process.http.transaction_totaltime.hit_fresh",
-    "proxy.process.http.transaction_totaltime.other", "proxy.process.http.websocket", "proxy.process.http2", "proxy.process.https",
-    "proxy.process.log", "proxy.process.net", "proxy.process.socks", "proxy.process.ssl", "proxy.process.ssl.cipher.user_agent",
-    "proxy.process.version.server",
-  };
-
-  // Register the metrics userdata type.
-  lua_metrics_register(binding.lua);
-
-  // Bind metric nodes to all the metrics namespace prefixes.
-  for (unsigned i = 0; i < countof(prefixes); ++i) {
-    if (lua_metrics_new(prefixes[i], binding.lua) == 1) {
-      binding.bind_value(prefixes[i], -1);
-      lua_pop(binding.lua, 1);
-    }
-  }
-}
-
 bool
 metrics_binding_initialize(BindingInstance &binding)
 {
@@ -355,8 +327,9 @@ metrics_binding_initialize(BindingInstance &binding)
     mgmt_fatal(stderr, 0, "failed to initialize Lua runtime\n");
   }
 
-  // Register the metrics bindings.
-  register_metrics_namespace(binding);
+  // Register the metrics userdata type.
+  lua_metrics_register(binding.lua);
+  update_metrics_namespace(binding.lua);
 
   // Register our own API.
   binding.bind_function("integer", metrics_create_integer);
@@ -371,7 +344,11 @@ metrics_binding_initialize(BindingInstance &binding)
   binding.attach_ptr("evaluators", new EvaluatorList());
 
   // Finally, execute the config file.
-  return binding.require(config.get());
+  if (binding.require(config.get())) {
+    return true;
+  }
+
+  return false;
 }
 
 void
@@ -392,7 +369,17 @@ metrics_binding_evaluate(BindingInstance &binding)
   evaluators = (EvaluatorList *)binding.retrieve_ptr("evaluators");
   ink_release_assert(evaluators != NULL);
 
+  // Keep updating the namespace until it settles (ie. we make 0 updates).
+  if (evaluators->update) {
+    evaluators->update = update_metrics_namespace(binding.lua) ? true : false;
+  }
+
   binding.bind_constant("metrics.now.msec", timestamp_now_msec());
   binding.bind_constant("metrics.update.pass", ++evaluators->passes);
   evaluators->evaluate(binding.lua);
+
+  // Periodically refresh the namespace to catch newly added metrics.
+  if (evaluators->passes % 10 == 0) {
+    evaluators->update = true;
+  }
 }

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/b547b651/lib/bindings/bindings.cc
----------------------------------------------------------------------
diff --git a/lib/bindings/bindings.cc b/lib/bindings/bindings.cc
index 9cd01b8..d189e52 100644
--- a/lib/bindings/bindings.cc
+++ b/lib/bindings/bindings.cc
@@ -56,36 +56,49 @@ BindingInstance::retrieve_ptr(const char *name)
   return (ptr == this->attachments.end()) ? NULL : ptr->second;
 }
 
-void
+bool
 BindingInstance::bind_constant(const char *name, lua_Integer value)
 {
+  bool bound;
+
   lua_pushinteger(this->lua, value);
-  this->bind_value(name, -1);
+  bound = this->bind_value(name, -1);
   lua_pop(this->lua, 1);
+
+  return bound;
 }
 
-void
+bool
 BindingInstance::bind_constant(const char *name, const char *value)
 {
+  bool bound;
+
   lua_pushlstring(this->lua, value, strlen(value));
-  this->bind_value(name, -1);
+  bound = this->bind_value(name, -1);
   lua_pop(this->lua, 1);
+
+  return bound;
 }
 
-void
+bool
 BindingInstance::bind_function(const char *name, int (*value)(lua_State *))
 {
+  bool bound;
+
   lua_pushcfunction(this->lua, value);
-  this->bind_value(name, -1);
+  bound = this->bind_value(name, -1);
   lua_pop(this->lua, 1);
+
+  return bound;
 }
 
 // Bind an arbitrary Lua value from the give stack position.
-void
+bool
 BindingInstance::bind_value(const char *name, int value)
 {
-  const char * start = name;
-  const char * end = name;
+  const char *start = name;
+  const char *end = name;
+  bool bound = false;
 
   int depth = 0;
 
@@ -161,18 +174,48 @@ BindingInstance::bind_value(const char *name, int value)
   // If we pushed a series of tables onto the stack, bind the name to a table
   // entry. otherwise bind it as a global name.
   if (depth) {
+    bool isnil;
+
+    // At this point the top of stack should be something indexable.
+    ink_assert(is_indexable(this->lua, -1));
+
+    Debug("lua", "stack depth is %d (expected %d)\n", lua_gettop(this->lua), depth);
+    // Push the index name.
     lua_pushstring(this->lua, start);
-    lua_pushvalue(this->lua, value);
 
-    ink_assert(is_indexable(this->lua, -3));
+    Debug("lua", "stack depth is %d (expected %d)\n", lua_gettop(this->lua), depth);
+    // Fetch the index (without metamethods);
+    lua_gettable(this->lua, -2);
+
+    // Only push the value if it is currently nil.
+    isnil = lua_isnil(this->lua, -1);
+    lua_pop(this->lua, 1);
+    Debug("lua", "isnil? %s", isnil ? "yes" : "no");
+
+    if (isnil) {
+      lua_pushstring(this->lua, start);
+      lua_pushvalue(this->lua, value);
+      lua_settable(this->lua, -3);
+      bound = true;
+    }
 
-    lua_settable(this->lua, -3);
     Debug("lua", "stack depth is %d (expected %d)\n", lua_gettop(this->lua), depth);
     lua_pop(this->lua, depth);
   } else {
-    lua_pushvalue(this->lua, value);
-    lua_setglobal(this->lua, start);
+    bool isnil;
+
+    lua_getglobal(this->lua, start);
+    isnil = lua_isnil(this->lua, -1);
+    lua_pop(this->lua, 1);
+
+    if (isnil) {
+      lua_pushvalue(this->lua, value);
+      lua_setglobal(this->lua, start);
+      bound = true;
+    }
   }
+
+  return bound;
 }
 
 bool
@@ -271,5 +314,3 @@ BindingInstance::register_metatable(lua_State *lua, const char *name, const luaL
 
   ink_assert(lua_gettop(lua) == 0);
 }
-
-/* vim: set sw=4 ts=4 tw=79 et: */

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/b547b651/lib/bindings/bindings.h
----------------------------------------------------------------------
diff --git a/lib/bindings/bindings.h b/lib/bindings/bindings.h
index 525cb60..55f78a0 100644
--- a/lib/bindings/bindings.h
+++ b/lib/bindings/bindings.h
@@ -41,10 +41,10 @@ struct BindingInstance {
   // Bind values to the specified global name. If the name contains '.'
   // separators, intermediate tables are constucted and the value is bound
   // to the final path component.
-  void bind_constant(const char *name, lua_Integer value);
-  void bind_constant(const char *name, const char *value);
-  void bind_function(const char *name, int (*value)(lua_State *));
-  void bind_value(const char *name, int value);
+  bool bind_constant(const char *name, lua_Integer value);
+  bool bind_constant(const char *name, const char *value);
+  bool bind_function(const char *name, int (*value)(lua_State *));
+  bool bind_value(const char *name, int value);
 
   // Attach a named pointer that we can later fish out from a Lua state.
   void attach_ptr(const char *, void *);

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/b547b651/lib/bindings/metrics.cc
----------------------------------------------------------------------
diff --git a/lib/bindings/metrics.cc b/lib/bindings/metrics.cc
index 66dbacf..ae148ee 100644
--- a/lib/bindings/metrics.cc
+++ b/lib/bindings/metrics.cc
@@ -26,6 +26,7 @@
 #include "P_RecCore.h"
 #include "ts/ink_memory.h"
 #include <map>
+#include <set>
 
 #define BINDING "lua.metrics"
 
@@ -199,3 +200,44 @@ lua_metrics_register(lua_State *L)
 
   BindingInstance::register_metatable(L, BINDING, metatable);
 }
+
+static void
+install_metrics_object(RecT rec_type, void *edata, int registered, const char *name, int data_type, RecData *datum)
+{
+  std::set<std::string> *prefixes = (std::set<std::string> *)edata;
+
+  if (likely(registered)) {
+    const char *end = strrchr(name, '.');
+    ptrdiff_t len = end - name;
+    prefixes->insert(std::string(name, len));
+  }
+}
+
+int
+lua_metrics_install(lua_State *L)
+{
+  int count = 0;
+  int metrics_type = RECT_NODE | RECT_PROCESS | RECT_CLUSTER | RECT_PLUGIN;
+  BindingInstance *binding = BindingInstance::self(L);
+  std::set<std::string> prefixes;
+
+  // Gather all the metrics namespace prefixes into a sorted set. We want to install
+  // metrics objects as the last branch of the namespace so that leaf metrics lookup
+  // end up indexing metrics objects.
+  RecDumpRecords((RecT)metrics_type, install_metrics_object, &prefixes);
+
+  for (std::set<std::string>::const_iterator p = prefixes.cbegin(); p != prefixes.cend(); ++p) {
+    if (lua_metrics_new(p->c_str(), binding->lua) == 1) {
+      if (binding->bind_value(p->c_str(), -1)) {
+        Debug("lua", "installed metrics object at prefix %s", p->c_str());
+        ++count;
+      }
+
+      lua_pop(binding->lua, 1);
+    }
+  }
+
+  // Return the number of metrics we installed;
+  lua_pushinteger(L, count);
+  return 1;
+}

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/b547b651/lib/bindings/metrics.h
----------------------------------------------------------------------
diff --git a/lib/bindings/metrics.h b/lib/bindings/metrics.h
index e0d39ac..9e42c16 100644
--- a/lib/bindings/metrics.h
+++ b/lib/bindings/metrics.h
@@ -30,4 +30,11 @@ int lua_metrics_new(const char *prefix, lua_State *L);
 // Register metrics binding type metatable.
 void lua_metrics_register(lua_State *L);
 
+// Install new metrics objects into the global namespace. This function
+// iterates over all the registered metrics and installs a metrics
+// object at the global name given by the metric's prefix. For example,
+// if the metric is named "proxy.my.great.counter", it would install
+// a metrics object at the global name "proxy.my.great".
+int lua_metrics_install(lua_State *L);
+
 #endif /* METRICS_H_FED1F5EA_9EDE_48E6_B05A_5DCAFD8DC319 */


[10/10] trafficserver git commit: Make the version of clang-format changeable.

Posted by jp...@apache.org.
Make the version of clang-format changeable.


Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo
Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/e7a4dc62
Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/e7a4dc62
Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/e7a4dc62

Branch: refs/heads/master
Commit: e7a4dc62ab5bd718ee869e6041c90062d1548140
Parents: 62d15ed
Author: James Peach <jp...@apache.org>
Authored: Thu Jan 21 18:51:40 2016 -0800
Committer: James Peach <jp...@apache.org>
Committed: Thu Jan 21 19:21:36 2016 -0800

----------------------------------------------------------------------
 tools/clang-format.sh | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e7a4dc62/tools/clang-format.sh
----------------------------------------------------------------------
diff --git a/tools/clang-format.sh b/tools/clang-format.sh
index 7f6478d..f6d31b9 100755
--- a/tools/clang-format.sh
+++ b/tools/clang-format.sh
@@ -19,8 +19,9 @@
 #  limitations under the License.
 
 DIR=${1:-.}
+FORMAT=${FORMAT:-clang-format}
 
 for file in $(find $DIR -iname \*.[ch] -o -iname \*.cc); do
     echo $file
-    clang-format -i $file
+    $FORMAT -i $file
 done


[05/10] trafficserver git commit: TS-4099: add core library infrastructure for Lua bindings

Posted by jp...@apache.org.
TS-4099: add core library infrastructure for Lua bindings

This adds a libbindings.la library with a convenience wrapper class
for dealing with a Lua state and binding APIs into it. We also add
some low-level Lua convenience APIs that end up being useful.


Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo
Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/5942c420
Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/5942c420
Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/5942c420

Branch: refs/heads/master
Commit: 5942c42020fde09e348c418ae0aec41cd8e4cf91
Parents: 4e2f0b8
Author: James Peach <jp...@apache.org>
Authored: Tue Nov 24 15:59:54 2015 -0800
Committer: James Peach <jp...@apache.org>
Committed: Thu Jan 21 18:52:18 2016 -0800

----------------------------------------------------------------------
 configure.ac             |   1 +
 lib/Makefile.am          |   2 +-
 lib/bindings/Makefile.am |  40 ++++++
 lib/bindings/bindings.cc | 275 ++++++++++++++++++++++++++++++++++++++++++
 lib/bindings/bindings.h  |  72 +++++++++++
 lib/bindings/lua.cc      |  63 ++++++++++
 lib/bindings/lua.h       |  68 +++++++++++
 lib/bindings/repl.cc     |  60 +++++++++
 lib/bindings/repl.h      |  30 +++++
 9 files changed, 610 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/5942c420/configure.ac
----------------------------------------------------------------------
diff --git a/configure.ac b/configure.ac
index 5712cf8..56793a1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1846,6 +1846,7 @@ AC_CONFIG_FILES([
   iocore/net/Makefile
   iocore/utils/Makefile
   lib/Makefile
+  lib/bindings/Makefile
   lib/perl/Makefile
   lib/perl/lib/Apache/TS.pm
   lib/records/Makefile

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/5942c420/lib/Makefile.am
----------------------------------------------------------------------
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 3306483..685b6be 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -16,7 +16,7 @@
 #  See the License for the specific language governing permissions and
 #  limitations under the License.
 
-SUBDIRS = ts records tsconfig
+SUBDIRS = ts records tsconfig bindings
 
 if BUILD_PERL_LIB
 SUBDIRS += perl

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/5942c420/lib/bindings/Makefile.am
----------------------------------------------------------------------
diff --git a/lib/bindings/Makefile.am b/lib/bindings/Makefile.am
new file mode 100644
index 0000000..661411c
--- /dev/null
+++ b/lib/bindings/Makefile.am
@@ -0,0 +1,40 @@
+#  Makefile.am
+#
+#  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.
+
+AM_CPPFLAGS = \
+  $(LUAJIT_CPPFLAGS) \
+  -I$(top_srcdir)/lib \
+  -I$(top_srcdir)/lib/records
+
+AM_CXXFLAGS = \
+  $(LUAJIT_CFLAGS)
+
+if BUILD_LUAJIT
+
+noinst_LTLIBRARIES = libbindings.la
+
+libbindings_la_SOURCES = \
+  bindings.cc \
+  bindings.h \
+  lua.cc \
+  lua.h \
+  repl.cc \
+  repl.h
+
+endif
+

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/5942c420/lib/bindings/bindings.cc
----------------------------------------------------------------------
diff --git a/lib/bindings/bindings.cc b/lib/bindings/bindings.cc
new file mode 100644
index 0000000..9cd01b8
--- /dev/null
+++ b/lib/bindings/bindings.cc
@@ -0,0 +1,275 @@
+/** @file
+ *
+ *  A brief file description
+ *
+ *  @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 "bindings.h"
+#include "ts/Diags.h"
+
+static const char selfkey[] = "bb3ecc8d-de6b-4f48-9aca-b3a3f14bdbad";
+
+static bool
+is_indexable(lua_State *L, int index)
+{
+  return lua_istable(L, index) || lua_isuserdata(L, index);
+}
+
+BindingInstance::BindingInstance() : lua(NULL)
+{
+}
+
+BindingInstance::~BindingInstance()
+{
+  if (this->lua) {
+    lua_close(this->lua);
+  }
+}
+
+void
+BindingInstance::attach_ptr(const char *name, void *ptr)
+{
+  this->attachments[name] = ptr;
+}
+
+void *
+BindingInstance::retrieve_ptr(const char *name)
+{
+  auto ptr = this->attachments.find(name);
+  return (ptr == this->attachments.end()) ? NULL : ptr->second;
+}
+
+void
+BindingInstance::bind_constant(const char *name, lua_Integer value)
+{
+  lua_pushinteger(this->lua, value);
+  this->bind_value(name, -1);
+  lua_pop(this->lua, 1);
+}
+
+void
+BindingInstance::bind_constant(const char *name, const char *value)
+{
+  lua_pushlstring(this->lua, value, strlen(value));
+  this->bind_value(name, -1);
+  lua_pop(this->lua, 1);
+}
+
+void
+BindingInstance::bind_function(const char *name, int (*value)(lua_State *))
+{
+  lua_pushcfunction(this->lua, value);
+  this->bind_value(name, -1);
+  lua_pop(this->lua, 1);
+}
+
+// Bind an arbitrary Lua value from the give stack position.
+void
+BindingInstance::bind_value(const char *name, int value)
+{
+  const char * start = name;
+  const char * end = name;
+
+  int depth = 0;
+
+  // Make the value an absolute stack inde because we are going to
+  // invalidate relative indices.
+  value = lua_absolute_index(this->lua, value);
+
+  // XXX extract this code so that we can using it for binding constants
+  // into an arbitrary table path ...
+  Debug("lua", "binding %s value at %d to %s\n", luaL_typename(this->lua, value), value, name);
+
+  for (; (end = ::strchr(start, '.')); start = end + 1) {
+    std::string name(start, end);
+
+    Debug("lua", "checking for table '%s'\n", name.c_str());
+    if (depth == 0) {
+      lua_getglobal(this->lua, name.c_str());
+      if (lua_isnil(this->lua, -1)) {
+        // No table with this name, construct one.
+        Debug("lua", "creating global table '%s'\n", name.c_str());
+
+        lua_pop(this->lua, 1); // Pop the nil.
+        lua_newtable(this->lua);
+        lua_setglobal(this->lua, name.c_str());
+        lua_getglobal(this->lua, name.c_str());
+
+        // Top of stack MUST be a table now.
+        ink_assert(lua_istable(this->lua, -1));
+      }
+
+      ink_assert(is_indexable(this->lua, -1));
+    } else {
+      ink_assert(is_indexable(this->lua, -1));
+
+      Debug("lua", "checking for table key '%s'\n", name.c_str());
+
+      // Push the string key.
+      lua_pushlstring(this->lua, &name[0], name.size());
+      // Get the table entry (now on top of the stack).
+      lua_gettable(this->lua, -2);
+
+      if (lua_isnil(this->lua, -1)) {
+        Debug("lua", "creating table key '%s'\n", name.c_str());
+
+        lua_pop(this->lua, 1); // Pop the nil.
+        lua_pushlstring(this->lua, &name[0], name.size());
+        lua_newtable(this->lua);
+
+        // Set the table entry. The stack now looks like:
+        //  -1  value (the new table)
+        //  -2  index (string)
+        //  -3  target (the table to add the index to)
+        lua_settable(this->lua, -3);
+
+        // Get the table entry we just created.
+        lua_pushlstring(this->lua, &name[0], name.size());
+        lua_gettable(this->lua, -2);
+
+        // Top of stack MUST be a table now.
+        ink_assert(lua_istable(this->lua, -1));
+      }
+
+      // The new entry is on top of the stack.
+      ink_assert(is_indexable(this->lua, -1));
+    }
+
+    ++depth;
+  }
+
+  Debug("lua", "stack depth is %d (expected %d)\n", lua_gettop(this->lua), depth);
+  Debug("lua", "last name token is '%s'\n", start);
+
+  // If we pushed a series of tables onto the stack, bind the name to a table
+  // entry. otherwise bind it as a global name.
+  if (depth) {
+    lua_pushstring(this->lua, start);
+    lua_pushvalue(this->lua, value);
+
+    ink_assert(is_indexable(this->lua, -3));
+
+    lua_settable(this->lua, -3);
+    Debug("lua", "stack depth is %d (expected %d)\n", lua_gettop(this->lua), depth);
+    lua_pop(this->lua, depth);
+  } else {
+    lua_pushvalue(this->lua, value);
+    lua_setglobal(this->lua, start);
+  }
+}
+
+bool
+BindingInstance::construct()
+{
+  ink_release_assert(this->lua == NULL);
+
+  if ((this->lua = luaL_newstate())) {
+    luaL_openlibs(this->lua);
+
+    // Push a pointer to ourself into the well-known registry key.
+    lua_pushlightuserdata(this->lua, this);
+    lua_setfield(this->lua, LUA_REGISTRYINDEX, selfkey);
+
+    ink_release_assert(BindingInstance::self(this->lua) == this);
+  }
+
+  return this->lua;
+}
+
+bool
+BindingInstance::require(const char *path)
+{
+  ink_release_assert(this->lua != NULL);
+
+  if (luaL_dofile(this->lua, path) != 0) {
+    Warning("%s", lua_tostring(this->lua, -1));
+    lua_pop(this->lua, 1);
+    return false;
+  }
+
+  return true;
+}
+
+BindingInstance *
+BindingInstance::self(lua_State *lua)
+{
+  BindingInstance *binding;
+
+  lua_getfield(lua, LUA_REGISTRYINDEX, selfkey);
+  binding = (BindingInstance *)lua_touserdata(lua, -1);
+
+  ink_release_assert(binding != NULL);
+  ink_release_assert(binding->lua == lua);
+
+  lua_pop(lua, 1);
+  return binding;
+}
+
+void
+BindingInstance::typecheck(lua_State *lua, const char *name, ...)
+{
+  int nargs = lua_gettop(lua);
+  int seen = 0;
+  va_list ap;
+
+  va_start(ap, name);
+
+  for (; seen < nargs; ++seen) {
+    int expected = va_arg(ap, int);
+
+    if (expected == LUA_TNONE) {
+      va_end(ap);
+      luaL_error(lua, "too many arguments to '%s'", name);
+      return;
+    }
+
+    if (lua_type(lua, seen + 1) != expected) {
+      va_end(ap);
+      luaL_error(lua, "bad argument #%d to '%s' (expected %s, received %s)", seen + 1, name, lua_typename(lua, expected),
+                 lua_typename(lua, lua_type(lua, seen + 1)));
+      return;
+    }
+  }
+
+  va_end(ap);
+
+  if (seen != nargs) {
+    luaL_error(lua, "too few arguments to '%s' (seen %d, nargs %d)", name, seen, nargs);
+  }
+}
+
+void
+BindingInstance::register_metatable(lua_State *lua, const char *name, const luaL_reg *metatable)
+{
+  // Create a metatable, adding it to the Lua registry.
+  luaL_newmetatable(lua, name);
+  // Dup the metatable.
+  lua_pushvalue(lua, -1);
+  // Pop one of those copies and assign it to __index field on the 1st metatable
+  lua_setfield(lua, -2, "__index");
+  // register functions in the metatable
+  luaL_register(lua, NULL, metatable);
+
+  lua_pop(lua, 1); /* drop metatable */
+
+  ink_assert(lua_gettop(lua) == 0);
+}
+
+/* vim: set sw=4 ts=4 tw=79 et: */

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/5942c420/lib/bindings/bindings.h
----------------------------------------------------------------------
diff --git a/lib/bindings/bindings.h b/lib/bindings/bindings.h
new file mode 100644
index 0000000..525cb60
--- /dev/null
+++ b/lib/bindings/bindings.h
@@ -0,0 +1,72 @@
+/** @file
+ *
+ *  Lua bindings object.
+ *
+ *  @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.
+ */
+
+#ifndef BINDINGS_H_02DF784C_94BD_4A5C_B57A_F986F5493C6A
+#define BINDINGS_H_02DF784C_94BD_4A5C_B57A_F986F5493C6A
+
+#include <string>
+#include <map>
+#include "lua.h"
+
+struct BindingInstance {
+  BindingInstance();
+  ~BindingInstance();
+
+  // Construct this Lua bindings instance.
+  bool construct();
+
+  // Import a Lua file.
+  bool require(const char *path);
+
+  // Bind values to the specified global name. If the name contains '.'
+  // separators, intermediate tables are constucted and the value is bound
+  // to the final path component.
+  void bind_constant(const char *name, lua_Integer value);
+  void bind_constant(const char *name, const char *value);
+  void bind_function(const char *name, int (*value)(lua_State *));
+  void bind_value(const char *name, int value);
+
+  // Attach a named pointer that we can later fish out from a Lua state.
+  void attach_ptr(const char *, void *);
+  void *retrieve_ptr(const char *);
+
+  // Generic typecheck helper for Lua APIs. Pass in a list of Lua type IDs
+  // (ie. LUA_Txxx) terminated by LUA_TNONE. Throws a Lua error string on
+  // failure.
+  static void typecheck(lua_State *, const char *name, ...);
+
+  // Given a Lua state, return the binding instance that owns it.
+  static BindingInstance *self(lua_State *);
+
+  // Register a Lua metatable for a custom type.
+  static void register_metatable(lua_State *, const char *, const luaL_reg *);
+
+  lua_State *lua;
+
+private:
+  std::map<std::string, void *> attachments;
+  BindingInstance(const BindingInstance &);            // noncopyable
+  BindingInstance &operator=(const BindingInstance &); // noncopyable
+};
+
+#endif /* BINDINGS_H_02DF784C_94BD_4A5C_B57A_F986F5493C6A */

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/5942c420/lib/bindings/lua.cc
----------------------------------------------------------------------
diff --git a/lib/bindings/lua.cc b/lib/bindings/lua.cc
new file mode 100644
index 0000000..57be614
--- /dev/null
+++ b/lib/bindings/lua.cc
@@ -0,0 +1,63 @@
+/** @file
+ *
+ *  Lua utilities and extensions.
+ *
+ *  @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 "lua.h"
+
+int
+lua_absolute_index(lua_State *L, int relative)
+{
+  return (relative > 0 || relative <= LUA_REGISTRYINDEX) ? relative : lua_gettop(L) + relative + 1;
+}
+
+// Check the type at the given index. Error if it is not the expected type.
+void
+lua_checktype(lua_State *L, int index, int ltype)
+{
+  if (lua_type(L, index) != ltype) {
+    luaL_error(L, "bad type, expected '%s' but found '%s'", lua_typename(L, ltype), lua_typename(L, lua_type(L, index)));
+  }
+}
+
+// luaL_checkudata() throws an exception if it fails, so to accept variadic
+// user types, we need to non-destructively test whether a userdata is an
+// instance of the type we want.
+bool
+lua_is_userdata(lua_State *L, int index, const char *metatype)
+{
+  int target = lua_absolute_index(L, index);
+  bool result = false;
+
+  // Get the metatable of the target.
+  if (lua_getmetatable(L, target) != 0) {
+    // If there was one, get the metatable of the target type.
+    luaL_getmetatable(L, metatype);
+
+    // Compare them.
+    result = lua_equal(L, -1, -2) == 1;
+
+    // Pop the 2 metatables.
+    lua_pop(L, 2);
+  }
+
+  return result;
+}

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/5942c420/lib/bindings/lua.h
----------------------------------------------------------------------
diff --git a/lib/bindings/lua.h b/lib/bindings/lua.h
new file mode 100644
index 0000000..8314df6
--- /dev/null
+++ b/lib/bindings/lua.h
@@ -0,0 +1,68 @@
+/** @file
+ *
+ *  Lua utilities and extensions.
+ *
+ *  @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.
+ */
+
+#ifndef LUA_H_7A9F5CCE_01C6_45C3_987A_FDCC1F437AA2
+#define LUA_H_7A9F5CCE_01C6_45C3_987A_FDCC1F437AA2
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "lua.h"
+#include "lualib.h"
+#include "lauxlib.h"
+
+// Redeclare luaL_error with format string checking.
+LUALIB_API int(luaL_error)(lua_State *L, const char *fmt, ...) __attribute__((format(printf, 2, 3)));
+
+#ifdef __cplusplus
+}
+#endif
+
+// Our version of abs_index() from lauxlib.c. Converts a absolute or relative
+// stack index into an absolute index. This is helpful for functions that
+// accepts an index but are going to do stack manipulation themselves.
+int lua_absolute_index(lua_State *L, int relative);
+
+// Check the type at the given index. Error if it is not the expected type.
+void lua_checktype(lua_State *L, int index, int ltype);
+
+// luaL_checkudata() throws an exception if it fails, so to accept variadic
+// user types, we need to non-destructively test whether a userdata is an
+// instance of the type we want.
+bool lua_is_userdata(lua_State *L, int index, const char *metatype);
+
+// Like lua_newuserdata() but for C++ objects.
+template <typename T>
+T *
+lua_newuserobject(lua_State *L)
+{
+  T *ptr = (T *)lua_newuserdata(L, sizeof(T));
+  if (ptr) {
+    return new (ptr) T();
+  }
+
+  return nullptr;
+}
+
+#endif /* LUA_H_7A9F5CCE_01C6_45C3_987A_FDCC1F437AA2 */

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/5942c420/lib/bindings/repl.cc
----------------------------------------------------------------------
diff --git a/lib/bindings/repl.cc b/lib/bindings/repl.cc
new file mode 100644
index 0000000..2931db8
--- /dev/null
+++ b/lib/bindings/repl.cc
@@ -0,0 +1,60 @@
+/** @file
+ *
+ *  Lua bindings REPL.
+ *
+ *  @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_autoconf.h"
+#include "bindings.h"
+#include <stdlib.h>
+
+#if HAVE_READLINE_H
+#include <readline.h>
+#endif
+
+void
+repl(BindingInstance &binding)
+{
+#if HAVE_READLINE_H
+  for (;;) {
+    char *line;
+
+    line = readline("> ");
+    if (line == NULL) {
+      exit(0);
+    }
+
+    if (*line) {
+      ::add_history(line);
+
+      if (luaL_loadbuffer(this->lua, line, ::strlen(line), "@stdin" /* source */) != 0 ||
+          lua_pcall(this->lua, 0, LUA_MULTRET, 0) != 0) {
+        // Pop the error message off the top of the stack and show it ...
+        error("%s\n", lua_tostring(this->lua, -1));
+        lua_pop(this->lua, 1);
+      }
+    }
+
+    ::free(line);
+  }
+
+#endif /*  HAVE_READLINE_H */
+  ::exit(0);
+}

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/5942c420/lib/bindings/repl.h
----------------------------------------------------------------------
diff --git a/lib/bindings/repl.h b/lib/bindings/repl.h
new file mode 100644
index 0000000..944a344
--- /dev/null
+++ b/lib/bindings/repl.h
@@ -0,0 +1,30 @@
+/** @file
+ *
+ *  Lua bindings REPL.
+ *
+ *  @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.
+ */
+
+#ifndef REPL_H_DB690467_F8FE_4797_8B08_7FD1F090DBA2
+#define REPL_H_DB690467_F8FE_4797_8B08_7FD1F090DBA2
+
+// Drop this binding instance into a Lua REPL (and never come out).
+void repl(BindingInstance &binding) TS_NORETURN;
+
+#endif /* REPL_H_DB690467_F8FE_4797_8B08_7FD1F090DBA2 */


[09/10] trafficserver git commit: TS-4099: fix a couple of metrics syntax problems

Posted by jp...@apache.org.
TS-4099: fix a couple of metrics syntax problems


Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo
Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/62d15eda
Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/62d15eda
Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/62d15eda

Branch: refs/heads/master
Commit: 62d15eda3febff41b6cfc81e79fc3f8c6977a720
Parents: b547b65
Author: James Peach <jp...@apache.org>
Authored: Thu Dec 31 17:33:05 2015 -0800
Committer: James Peach <jp...@apache.org>
Committed: Thu Jan 21 19:21:36 2016 -0800

----------------------------------------------------------------------
 proxy/config/metrics.config.default | 37 ++++++++++++++++----------------
 1 file changed, 19 insertions(+), 18 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/62d15eda/proxy/config/metrics.config.default
----------------------------------------------------------------------
diff --git a/proxy/config/metrics.config.default b/proxy/config/metrics.config.default
index f5559d4..4488d63 100644
--- a/proxy/config/metrics.config.default
+++ b/proxy/config/metrics.config.default
@@ -927,20 +927,21 @@ float 'proxy.node.http.transaction_frac_avg_10s.miss_cold' [[
 
 float 'proxy.node.http.transaction_frac_avg_10s.miss_changed' [[
   return interval_of_10s(..., function()
-    proxy.node.http.transaction_counts_avg_10s.miss_changed /
-    (
-    proxy.node.http.transaction_counts_avg_10s.hit_fresh                 +
-    proxy.node.http.transaction_counts_avg_10s.hit_revalidated           +
-    proxy.node.http.transaction_counts_avg_10s.miss_cold                 +
-    proxy.node.http.transaction_counts_avg_10s.miss_changed              +
-    proxy.node.http.transaction_counts_avg_10s.miss_client_no_cache      +
-    proxy.node.http.transaction_counts_avg_10s.miss_not_cacheable        +
-    proxy.node.http.transaction_counts_avg_10s.errors.connect_failed     +
-    proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
-    proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
-    proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
-    proxy.node.http.transaction_counts_avg_10s.errors.other
-    )
+    return
+      proxy.node.http.transaction_counts_avg_10s.miss_changed /
+      (
+      proxy.node.http.transaction_counts_avg_10s.hit_fresh                 +
+      proxy.node.http.transaction_counts_avg_10s.hit_revalidated           +
+      proxy.node.http.transaction_counts_avg_10s.miss_cold                 +
+      proxy.node.http.transaction_counts_avg_10s.miss_changed              +
+      proxy.node.http.transaction_counts_avg_10s.miss_client_no_cache      +
+      proxy.node.http.transaction_counts_avg_10s.miss_not_cacheable        +
+      proxy.node.http.transaction_counts_avg_10s.errors.connect_failed     +
+      proxy.node.http.transaction_counts_avg_10s.errors.aborts             +
+      proxy.node.http.transaction_counts_avg_10s.errors.possible_aborts    +
+      proxy.node.http.transaction_counts_avg_10s.errors.pre_accept_hangups +
+      proxy.node.http.transaction_counts_avg_10s.errors.other
+      )
   end)
 ]]
 
@@ -1182,7 +1183,7 @@ integer 'proxy.node.http.transaction_msec_avg_10s.miss_cold' [[
     return
       sec_to_msec   *
       delta_of(self, function()
-        proxy.process.http.transaction_totaltime.miss_cold
+        return proxy.process.http.transaction_totaltime.miss_cold
       end) /
       (
       proxy.node.http.transaction_counts_avg_10s.hit_fresh                 +
@@ -1253,7 +1254,7 @@ integer 'proxy.node.http.transaction_msec_avg_10s.miss_not_cacheable' [[
   return interval_of_10s(self, function()
     return
       sec_to_msec            *
-      delta_of)self, function()
+      delta_of(self, function()
         return proxy.process.http.transaction_totaltime.miss_not_cacheable
       end) /
       (
@@ -1637,6 +1638,6 @@ integer 'proxy.cluster.log.bytes_received_from_network_avg_10s' [[
   return cluster('proxy.node.log.bytes_received_from_network_avg_10s')
 ]]
 
-counter 'proxy.process.ssl.total_success_handshake_count_in' [[
-  return proxy.process.ssl.total_success_handshake_count
+counter 'proxy.process.ssl.total_success_handshake_count' [[
+  return proxy.process.ssl.total_success_handshake_count_in
 ]]