This is an automated email from the ASF dual-hosted git repository.

moonchen pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git


The following commit(s) were added to refs/heads/master by this push:
     new c6ec3adbb3 header_rewrite: count operators and conditions run (#13286)
c6ec3adbb3 is described below

commit c6ec3adbb3e44ee47068112b16908e54cc6b22d7
Author: Mo Chen <[email protected]>
AuthorDate: Sat Jun 20 16:00:53 2026 -0500

    header_rewrite: count operators and conditions run (#13286)
    
    The per-hook invocation count cannot tell a small ruleset from a large one,
    so it does not reflect how much work header_rewrite does per transaction.
    Add proxy.process.plugin.header_rewrite.{operators,conditions}, incremented
    in the inline Operator::do_exec and Condition::do_eval chain walkers, to 
make
    that workload visible.  do_eval short-circuits, so only conditions actually
    evaluated are counted.  The counters are created once, from both 
TSPluginInit
    and TSRemapInit.
---
 plugins/header_rewrite/condition.h                 |  4 +++
 plugins/header_rewrite/header_rewrite.cc           |  4 +++
 plugins/header_rewrite/operator.h                  |  3 +++
 plugins/header_rewrite/statement.cc                | 18 +++++++++++++
 plugins/header_rewrite/statement.h                 |  8 ++++++
 tests/gold_tests/autest-site/ats_replay.test.ext   | 30 ++++++++++++++++------
 .../header_rewrite_bundle.replay.yaml              |  6 +++++
 7 files changed, 65 insertions(+), 8 deletions(-)

diff --git a/plugins/header_rewrite/condition.h 
b/plugins/header_rewrite/condition.h
index 1400f3433a..63f2da6773 100644
--- a/plugins/header_rewrite/condition.h
+++ b/plugins/header_rewrite/condition.h
@@ -49,6 +49,10 @@ public:
   bool
   do_eval(const Resources &res)
   {
+    // In do_eval, so AND/OR short-circuited conditions aren't counted.
+    if (hrw_stat_conditions != nullptr) {
+      ts::Metrics::Counter::increment(hrw_stat_conditions);
+    }
     bool rt = eval(res);
 
     if (has_modifier(_mods, CondModifiers::NOT)) {
diff --git a/plugins/header_rewrite/header_rewrite.cc 
b/plugins/header_rewrite/header_rewrite.cc
index 16f8b0c617..9a43a73813 100644
--- a/plugins/header_rewrite/header_rewrite.cc
+++ b/plugins/header_rewrite/header_rewrite.cc
@@ -569,6 +569,8 @@ TSPluginInit(int argc, const char *argv[])
     return;
   }
 
+  init_hrw_work_stats();
+
   std::string geoDBpath;
   int         inboundIpSource = 0;
   int         timezone        = 0;
@@ -663,6 +665,8 @@ TSRemapInit(TSRemapInterface *api_info, char *errbuf, int 
errbuf_size)
   CHECK_REMAP_API_COMPATIBILITY(api_info, errbuf, errbuf_size);
   Dbg(pi_dbg_ctl, "Remap plugin is successfully initialized");
 
+  init_hrw_work_stats();
+
   return TS_SUCCESS;
 }
 
diff --git a/plugins/header_rewrite/operator.h 
b/plugins/header_rewrite/operator.h
index bc23c93aab..a44211ba97 100644
--- a/plugins/header_rewrite/operator.h
+++ b/plugins/header_rewrite/operator.h
@@ -78,6 +78,9 @@ public:
   unsigned
   do_exec(const Resources &res) const
   {
+    if (hrw_stat_operators != nullptr) {
+      ts::Metrics::Counter::increment(hrw_stat_operators);
+    }
     unsigned no_reenable{exec(res) ? 0U : 1U};
     if (nullptr != _next) {
       no_reenable += static_cast<Operator *>(_next)->do_exec(res);
diff --git a/plugins/header_rewrite/statement.cc 
b/plugins/header_rewrite/statement.cc
index 6e2607da63..8bce404a2d 100644
--- a/plugins/header_rewrite/statement.cc
+++ b/plugins/header_rewrite/statement.cc
@@ -21,6 +21,24 @@
 //
 #include "statement.h"
 
+ts::Metrics::Counter::AtomicType *hrw_stat_operators  = nullptr;
+ts::Metrics::Counter::AtomicType *hrw_stat_conditions = nullptr;
+
+void
+init_hrw_work_stats()
+{
+  // createPtr() is idempotent and internally synchronized: it returns the 
existing counter when
+  // one already has the given name. header_rewrite.so can be loaded both 
globally (TSPluginInit)
+  // and as a remap plugin (TSRemapInit), so init runs more than once; every 
call resolves to the
+  // same process-wide counter regardless of ordering or which thread runs it.
+  if (nullptr == hrw_stat_operators) {
+    hrw_stat_operators = 
ts::Metrics::Counter::createPtr("proxy.process.plugin.header_rewrite.operators");
+  }
+  if (nullptr == hrw_stat_conditions) {
+    hrw_stat_conditions = 
ts::Metrics::Counter::createPtr("proxy.process.plugin.header_rewrite.conditions");
+  }
+}
+
 void
 Statement::append(Statement *stmt)
 {
diff --git a/plugins/header_rewrite/statement.h 
b/plugins/header_rewrite/statement.h
index 2557d4482c..1f16c24246 100644
--- a/plugins/header_rewrite/statement.h
+++ b/plugins/header_rewrite/statement.h
@@ -27,11 +27,19 @@
 #include <vector>
 
 #include "ts/ts.h"
+#include "tsutil/Metrics.h"
 
 #include "resources.h"
 #include "parser.h"
 #include "lulu.h"
 
+// Counters for the number of header_rewrite operators executed and conditions 
evaluated; the
+// bare hook invocation count cannot tell a small ruleset from a large one. 
Created once via
+// init_hrw_work_stats(); both are null until then, so increments are guarded.
+extern ts::Metrics::Counter::AtomicType *hrw_stat_operators;
+extern ts::Metrics::Counter::AtomicType *hrw_stat_conditions;
+void                                     init_hrw_work_stats();
+
 namespace header_rewrite_ns
 {
 constexpr int NUM_STATE_FLAGS = 16;
diff --git a/tests/gold_tests/autest-site/ats_replay.test.ext 
b/tests/gold_tests/autest-site/ats_replay.test.ext
index d6379025b2..b34e30ed2e 100644
--- a/tests/gold_tests/autest-site/ats_replay.test.ext
+++ b/tests/gold_tests/autest-site/ats_replay.test.ext
@@ -323,14 +323,28 @@ def ATSReplayTest(obj, replay_file: str):
 
         for check in metric_checks:
             metric_name = check['metric']
-            expected_value = check['value']
-            check_tr = obj.AddTestRun(f'Verify {metric_name} == 
{expected_value}')
-            check_tr.Processes.Default.Command = f'traffic_ctl metric get 
{metric_name}'
-            check_tr.Processes.Default.Env = ts.Env
-            check_tr.Processes.Default.ReturnCode = 0
-            check_tr.Processes.Default.Streams.All = 
Testers.ContainsExpression(
-                f'^{re.escape(metric_name)}\\s+{expected_value}$', 
f'{metric_name} should be {expected_value}')
-            check_tr.StillRunningAfter = ts
+            if 'value' in check:
+                expected_value = check['value']
+                check_tr = obj.AddTestRun(f'Verify {metric_name} == 
{expected_value}')
+                check_tr.Processes.Default.Command = f'traffic_ctl metric get 
{metric_name}'
+                check_tr.Processes.Default.Env = ts.Env
+                check_tr.Processes.Default.ReturnCode = 0
+                check_tr.Processes.Default.Streams.All = 
Testers.ContainsExpression(
+                    f'^{re.escape(metric_name)}\\s+{expected_value}$', 
f'{metric_name} should be {expected_value}')
+                check_tr.StillRunningAfter = ts
+            elif 'min' in check:
+                minimum = check['min']
+                check_tr = obj.AddTestRun(f'Verify {metric_name} >= {minimum}')
+                # Fail if the metric value (field 2) is below the minimum, or 
absent.
+                # $$ escapes the awk field ref from autest's command 
templating.
+                check_tr.Processes.Default.Command = (
+                    f"traffic_ctl metric get {metric_name} | "
+                    f"awk 'BEGIN {{ rc = 1 }} {{ if ($$2 + 0 >= {minimum}) rc 
= 0 }} END {{ exit rc }}'")
+                check_tr.Processes.Default.Env = ts.Env
+                check_tr.Processes.Default.ReturnCode = 0
+                check_tr.StillRunningAfter = ts
+            else:
+                raise ValueError(f"metric_checks entry for '{metric_name}' 
must specify 'value' or 'min'")
 
     # wait for error log
     if log_validation and log_validation.get('error_log'):
diff --git 
a/tests/gold_tests/pluginTest/header_rewrite/header_rewrite_bundle.replay.yaml 
b/tests/gold_tests/pluginTest/header_rewrite/header_rewrite_bundle.replay.yaml
index 97e1d6d285..b444acaae8 100644
--- 
a/tests/gold_tests/pluginTest/header_rewrite/header_rewrite_bundle.replay.yaml
+++ 
b/tests/gold_tests/pluginTest/header_rewrite/header_rewrite_bundle.replay.yaml
@@ -176,6 +176,12 @@ autest:
             args:
               - "rules/rule_session_vars.conf"
 
+    metric_checks:
+      - metric: "proxy.process.plugin.header_rewrite.operators"
+        min: 1
+      - metric: "proxy.process.plugin.header_rewrite.conditions"
+        min: 1
+
     log_validation:
       traffic_out:
         excludes:

Reply via email to