bryancall commented on code in PR #13505:
URL: https://github.com/apache/trafficserver/pull/13505#discussion_r3805661018


##########
src/records/RecCore.cc:
##########
@@ -612,6 +612,27 @@ RecLookupMatchingRecords(unsigned rec_type, const char 
*match, void (*callback)(
     });
   }
 
+  if (rec_type & RECT_HIDDEN_METRIC) {
+    // Opt-in only: hidden metrics are never reachable through RECT_ALL, see 
RecDefs.h.
+    for (auto &&[name, type, val] : ts::Metrics::hidden_instance()) {
+      if (regex.exec(name.data())) {
+        RecRecord tmp;

Review Comment:
   `RecRecord tmp;` leaves `version`, `registered`, `rsb_id`, `order` and 
`data_default` indeterminate, and `convert<RecRecord>::encode` reads all of 
them unconditionally (`convert.h` lines 121-126, plus `data_default` in the 
RECD_INT and RECD_COUNTER cases). The path is reachable: `RecordsUtils.cc` 
hands each callback record straight to the encoder, so `traffic_ctl --format 
json metric match --include-hidden` can emit different version, rsb and order 
values on successive runs. Reading `registered`, an indeterminate `bool`, is 
undefined behavior that a MemorySanitizer build would flag.
   
   Your comment correctly explains why no `stat_meta` block is emitted, which 
covers the fields Copilot was most concerned about, but it does not cover these 
five. `RecRecord tmp{};` zero-initializes the whole struct and costs nothing.
   
   Not blocking, because the published-metric loop about 25 lines up has had 
the identical pattern for years, so this is not a regression. Since you are 
already in the file, worth fixing in both places.



##########
src/tsutil/Metrics.cc:
##########
@@ -64,6 +76,13 @@ Metrics::Storage::create(std::string_view name, const 
MetricType type)
     return it->second;
   }
 
+  // The slot is written below and the bookkeeping only then advances, calling 
addBlob() once
+  // _cur_off reaches MAX_SIZE. Refusing the final slot of the final blob 
keeps addBlob() from
+  // ever being reached in an exhausted store, at a cost of one slot out of 
MAX_BLOBS * MAX_SIZE.
+  if (_cur_blob >= MAX_BLOBS - 1 && _cur_off >= MAX_SIZE - 1) {

Review Comment:
   The new guard covers `create()` only. `createSpan()` does `if (_cur_off + 
size > MAX_SIZE) addBlob();` and then `_cur_off += size`, so a span landing 
exactly on the boundary leaves `_cur_off == MAX_SIZE` without allocating a new 
blob. The next `create()` then indexes `names[1024]` on a 
`std::array<NameAndId, 1024>`. `end()` also becomes `_makeId(blob, MAX_SIZE)`, 
which `iterator::next()` can never reach because it wraps on `++offset == 
MAX_SIZE`.
   
   Latent today, since the `Gauge::createSpan` and `Counter::createSpan` 
wrappers have no callers in the tree outside the unit tests. I raise it because 
it is the same class of bookkeeping off-by-one this PR is hardening against, 
and the new blob-growth-boundary test only drives `create()`. Either a matching 
guard or a comment noting `createSpan` is currently unused would close it.



##########
doc/appendices/command-line/traffic_ctl.en.rst:
##########
@@ -949,13 +949,20 @@ traffic_ctl metric
    Display the current value of the specified statistics.
 
 .. program:: traffic_ctl metric
-.. option:: match REGEX [REGEX...]
+.. option:: match [--include-hidden] REGEX [REGEX...]
 
    :ref:`admin_lookup_records`
 
    Display the current values of all statistics whose names match
    the given regular expression.
 
+.. option:: --include-hidden

Review Comment:
   `--include-hidden` is a sibling `.. option::` under `.. program:: 
traffic_ctl metric`, so it renders as another subcommand alongside `match`, 
`describe` and `get` rather than as a flag on `match`. A reader cannot tell it 
only applies to `match`.
   
   The synopsis on the line above also puts the flag before the regex, while 
`add_example_usage` in `traffic_ctl.cc` writes `traffic_ctl metric match METRIC 
[--include-hidden]`. Worth making the two spellings agree.



##########
src/records/RecCore.cc:
##########
@@ -612,6 +612,27 @@ RecLookupMatchingRecords(unsigned rec_type, const char 
*match, void (*callback)(
     });
   }
 
+  if (rec_type & RECT_HIDDEN_METRIC) {
+    // Opt-in only: hidden metrics are never reachable through RECT_ALL, see 
RecDefs.h.
+    for (auto &&[name, type, val] : ts::Metrics::hidden_instance()) {

Review Comment:
   The hidden-store iteration starts at `begin()`, which is the reserved 
`bad_id` slot every `Storage` constructor creates. So `traffic_ctl metric match 
--include-hidden bad_id` returns two records both named 
`proxy.process.api.metrics.bad_id`, one from each store, with different values. 
Cosmetic, but confusing in exactly the debugging situation this flag exists 
for. Skipping id 0 in this loop avoids it.



-- 
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