bneradt commented on code in PR #13666:
URL: https://github.com/apache/trafficserver/pull/13666#discussion_r4039843745


##########
src/iocore/net/ConnectionTracker.cc:
##########
@@ -485,33 +486,70 @@ ConnectionTracker::Group::Group(DirectionType direction, 
Key const &key, std::st
     std::string _host_metric_name = host_metric_name(key, fqdn, 
_global_config->metric_prefix);
     bool const  has_aggregate     = !_host_metric_name.empty();
 
-    if (has_aggregate && metric_aggregate != AGGREGATE_NONE) {
-      
Metrics::Derived::add_source("proxy.process.http.per_server.current_connection."
 + _host_metric_name,
-                                   Metrics::MetricType::GAUGE, _count_metric, 
Metrics::Derived::Op::SUM);
-      
Metrics::Derived::add_source("proxy.process.http.per_server.total_connection." 
+ _host_metric_name,
-                                   Metrics::MetricType::COUNTER, 
_count_total_metric, Metrics::Derived::Op::SUM);
-      
Metrics::Derived::add_source("proxy.process.http.per_server.blocked_connection."
 + _host_metric_name,
-                                   Metrics::MetricType::COUNTER, 
_blocked_metric, Metrics::Derived::Op::SUM);
+    // A plugin can set an out of range value through the overridable config, 
see
+    // METRIC_AGGREGATE_CONV. Anything unrecognized publishes everything.
+    if (metric_aggregate < AGGREGATE_NONE || metric_aggregate > AGGREGATE_SUM) 
{
+      metric_aggregate = AGGREGATE_GROUP;
+    }
+
+    // See MetricAggregate for the table these three implement. A group with 
no hostname to
+    // aggregate under keeps its own metrics whatever the setting says, since 
suppressing them would
+    // report nothing at all for that upstream.
+    bool const publish_sums  = has_aggregate && (metric_aggregate == 
AGGREGATE_GROUP || metric_aggregate == AGGREGATE_SUM);
+    bool const publish_max   = has_aggregate && metric_aggregate != 
AGGREGATE_NONE;
+    bool const publish_group = !has_aggregate || metric_aggregate == 
AGGREGATE_NONE || metric_aggregate == AGGREGATE_GROUP;
+
+    std::array<std::string, 3> const sum_names{
+      "proxy.process.http.per_server.current_connection." + _host_metric_name,
+      "proxy.process.http.per_server.total_connection." + _host_metric_name,
+      "proxy.process.http.per_server.blocked_connection." + _host_metric_name,
+    };
+    std::array<std::string, 3> const group_names{
+      "proxy.process.http.per_server.current_connection." + _metric_name,
+      "proxy.process.http.per_server.total_connection." + _metric_name,
+      "proxy.process.http.per_server.blocked_connection." + _metric_name,
+    };
+    std::string const max_name = 
"proxy.process.http.per_server.current_connection.max." + _host_metric_name;

Review Comment:
   [P2] Confirmed from the name builders and Derived::add_source: with an empty 
metric_prefix, MATCH_HOST for max.example.test and MATCH_BOTH for example.test 
both register 
proxy.process.http.per_server.current_connection.max.example.test. If the 
MATCH_HOST source (value 7) registers first, the entry retains SUM; adding two 
MATCH_BOTH sources with values 2 and 3 produces 12 instead of the expected 
hostname max of 3. In the reverse construction order it retains MAX and the 
unrelated host source can inflate that max to 7. Please make the max aggregate 
namespace distinct from valid per-group hostname names and cover both 
construction orders. This remains a correctness blocker.



##########
src/tsutil/Metrics.cc:
##########
@@ -358,6 +386,21 @@ Metrics::Derived::add_source(std::string_view 
derived_name, Metrics::MetricType
   details::DerivativeMetrics::instance().add_source(id, source, op);
 }
 
+void
+Metrics::Derived::remove_source(std::string_view derived_name, 
Metrics::AtomicType *source)
+{
+  auto &instance = Metrics::instance();
+  auto  id       = instance.lookup(derived_name);
+
+  if (id == Metrics::NOT_FOUND) {
+    return;
+  }
+
+  if (details::DerivativeMetrics::instance().remove_source(id, source)) {
+    instance.unlist(id);

Review Comment:
   [P2] Confirmed the interleaving in the new public Derived API: A removes the 
last source and returns true from the helper, releasing metrics_lock; B 
completes add_source for the same name (including relisting it and registering 
its source); A then calls unlist. The resulting metric has an active source and 
keeps being recomputed, but is absent from enumeration. Moving only unlist 
inside the lock is insufficient because add_source currently relists before 
acquiring that lock: both source membership and the listing transition need 
coordinated ordering. Please add a concurrent regression test. 
ConnectionTracker constructors are serialized by the outbound table lock, so 
that particular caller is protected; the new public Metrics API itself is not.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to