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

zwoop 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 e6182d9ac9 New API Metrics, and start of a libtsapi.so structure 
(#9988)
e6182d9ac9 is described below

commit e6182d9ac9c3f611cb33b3ef6dc98327df41c3d6
Author: Leif Hedstrom <zw...@apache.org>
AuthorDate: Fri Jul 28 16:48:46 2023 -0600

    New API Metrics, and start of a libtsapi.so structure (#9988)
    
    * New API Metrics, and start of a libtapi.so structure
    
    The new API metrics are backwards compatible with previous APIs,
    since the old API wraps these new APIs. New plugins / code could
    chose to use the Metrics.h API directly.
    
    Work to be finished here includes
    
       1. Decide what goes into include/api ? Do we have one new
          include file to #include all the include/api/*.h files?
    
       2. What should be moved to src/api and include/api.
    
    Lost in this merge is all the work from Chris McFarlen. Thanks!
    
    Co-Author: Chris McFarlen <ch...@mcfarlen.us>
    
    * Fixes make check
    
    * Fixes type mismatch, shouldn't use apidefs.h symbols
    
    * More Makefile fixes
    
    * Adds missing include files
    
    * Updates the regression tests, adds to Makefile
    
    * Fixes install CMake targets
    
    * Fix the expensive checks
    
    * Fixes for H3 and HPACK
    
    * Adds API metrics supports for the RecCore matchers
    
    * Trying to fix some build concerns
    
    * Removes the -fPIE from hardening
    
    * Undo some of the fPIC stuff and deps
---
 .gitignore                                      |   1 +
 CMakeLists.txt                                  |   1 +
 configure.ac                                    |   1 +
 include/api/Metrics.h                           | 237 ++++++++++++++++++++++++
 include/records/I_RecordsConfig.h               |   3 -
 include/records/P_RecCore.h                     |   2 +-
 include/records/P_RecDefs.h                     |  10 +-
 iocore/aio/Makefile.am                          |   1 +
 iocore/cache/Makefile.am                        |   1 +
 iocore/eventsystem/Makefile.am                  |   1 +
 iocore/hostdb/Makefile.am                       |   1 +
 iocore/net/Makefile.am                          |  10 +-
 mgmt/rpc/Makefile.am                            |   1 +
 plugins/experimental/remap_stats/remap_stats.cc |   3 -
 proxy/hdrs/Makefile.am                          |   2 +
 proxy/http/Makefile.am                          |   2 +
 proxy/http/remap/Makefile.am                    |   5 +
 proxy/http/unit_tests/CMakeLists.txt            |   1 +
 proxy/http2/Makefile.am                         |   2 +
 proxy/http3/Makefile.am                         |   1 +
 proxy/logging/unit-tests/benchmark_LogObject.cc |   2 +-
 src/Makefile.am                                 |   2 +-
 src/{traffic_crashlog => api}/CMakeLists.txt    |  20 +-
 src/{ => api}/Makefile.am                       |  52 +++---
 src/api/Metrics.cc                              | 139 ++++++++++++++
 src/api/test_Metrics.cc                         |  65 +++++++
 src/records/Makefile.am                         |   2 +
 src/records/RecCore.cc                          |  73 ++++++--
 src/records/RecUtils.cc                         |   4 +-
 src/tests/CMakeLists.txt                        |   2 +
 src/traffic_crashlog/CMakeLists.txt             |   1 +
 src/traffic_crashlog/Makefile.inc               |   1 +
 src/traffic_layout/CMakeLists.txt               |   4 +
 src/traffic_layout/Makefile.inc                 |   1 +
 src/traffic_logcat/Makefile.inc                 |   1 +
 src/traffic_logstats/Makefile.inc               |   5 +-
 src/traffic_server/CMakeLists.txt               |   1 +
 src/traffic_server/InkAPI.cc                    |  86 ++-------
 src/traffic_server/Makefile.inc                 |   1 +
 src/traffic_server/traffic_server.cc            |   2 -
 tools/benchmark/Makefile.am                     |   1 +
 41 files changed, 607 insertions(+), 144 deletions(-)

diff --git a/.gitignore b/.gitignore
index a4983d434b..c288e1470e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -102,6 +102,7 @@ src/tscore/test_tscore
 src/tscpp/util/test_tscpputil
 src/records/test_librecords
 src/records/test_librecords_on_eventsystem
+src/api/test_Metrics
 lib/perl/lib/Apache/TS.pm
 
 iocore/net/test_certlookup
diff --git a/CMakeLists.txt b/CMakeLists.txt
index d771148036..eda1b79b23 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -355,6 +355,7 @@ configure_file(include/ts/apidefs.h.in include/ts/apidefs.h)
 
 enable_testing()
 
+add_subdirectory(src/api)
 add_subdirectory(src/tscpp/util)
 add_subdirectory(src/tscpp/api)
 add_subdirectory(src/tscore)
diff --git a/configure.ac b/configure.ac
index 0eb8249053..73d8a2c587 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2400,6 +2400,7 @@ AC_CONFIG_FILES([
   src/tscpp/util/Makefile
   src/tscore/Makefile
   src/records/Makefile
+  src/api/Makefile
   tools/Makefile
   tools/trafficserver.pc
   tools/tsxs
diff --git a/include/api/Metrics.h b/include/api/Metrics.h
new file mode 100644
index 0000000000..6b79f43eb3
--- /dev/null
+++ b/include/api/Metrics.h
@@ -0,0 +1,237 @@
+/** @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.
+ */
+
+#pragma once
+
+#include <array>
+#include <unordered_map>
+#include <tuple>
+#include <mutex>
+#include <thread>
+#include <atomic>
+#include <cstdint>
+#include <string>
+#include <string_view>
+
+#include "tscore/ink_assert.h"
+
+namespace ts
+{
+class Metrics
+{
+private:
+  using self_type  = Metrics;
+  using IdType     = int32_t; // Could be a tuple, but one way or another, 
they have to be combined to an int32_t.
+  using AtomicType = std::atomic<int64_t>;
+
+public:
+  static constexpr uint16_t METRICS_MAX_BLOBS = 8192;
+  static constexpr uint16_t METRICS_MAX_SIZE  = 2048;                          
     // For a total of 16M metrics
+  static constexpr IdType NOT_FOUND           = 
std::numeric_limits<IdType>::min(); // <16-bit,16-bit> = <blob-index,offset>
+
+private:
+  using NameAndId       = std::tuple<std::string, IdType>;
+  using NameContainer   = std::array<NameAndId, METRICS_MAX_SIZE>;
+  using AtomicContainer = std::array<AtomicType, METRICS_MAX_SIZE>;
+  using MetricStorage   = std::tuple<NameContainer, AtomicContainer>;
+  using MetricBlobs     = std::array<MetricStorage *, METRICS_MAX_BLOBS>;
+  using LookupTable     = std::unordered_map<std::string_view, IdType>;
+
+public:
+  Metrics(const self_type &)              = delete;
+  self_type &operator=(const self_type &) = delete;
+  Metrics &operator=(Metrics &&)          = delete;
+  Metrics(Metrics &&)                     = delete;
+
+  virtual ~Metrics() = default;
+
+  Metrics()
+  {
+    _blobs[0] = new MetricStorage();
+    ink_release_assert(_blobs[0]);
+    ink_release_assert(0 == newMetric("proxy.node.api.metrics.bad_id")); // 
Reserve slot 0 for errors, this should always be 0
+  }
+
+  // Singleton
+  static Metrics &getInstance();
+
+  // Yes, we don't return objects here, but rather ID's and atomic's directly. 
Treat
+  // the std::atomic<int64_t> as the underlying class for a single metric, and 
be happy.
+  IdType newMetric(const std::string_view name);
+  IdType lookup(const std::string_view name) const;
+  AtomicType *lookup(IdType id, std::string_view *name = nullptr) const;
+
+  AtomicType &
+  operator[](IdType id)
+  {
+    return *lookup(id);
+  }
+
+  IdType
+  operator[](const std::string_view name) const
+  {
+    return lookup(name);
+  }
+
+  int64_t
+  increment(IdType id, uint64_t val = 1)
+  {
+    auto metric = lookup(id);
+
+    return (metric ? metric->fetch_add(val) : NOT_FOUND);
+  }
+
+  // ToDo: Do we even need these inc/dec functions?
+  int64_t
+  decrement(IdType id, uint64_t val = 1)
+  {
+    auto metric = lookup(id);
+
+    return (metric ? metric->fetch_sub(val) : NOT_FOUND);
+  }
+
+  std::string_view name(IdType id) const;
+
+  bool
+  valid(IdType id) const
+  {
+    auto [blob, entry] = _splitID(id);
+
+    return (id >= 0 && ((blob < _cur_blob && entry < METRICS_MAX_SIZE) || 
(blob == _cur_blob && entry <= _cur_off)));
+  }
+
+  class iterator
+  {
+  public:
+    using iterator_category = std::input_iterator_tag;
+    using value_type        = std::tuple<std::string_view, int64_t>;
+    using difference_type   = ptrdiff_t;
+    using pointer           = value_type *;
+    using reference         = value_type &;
+
+    iterator(const Metrics &m, IdType pos) : _metrics(m), _it(pos) {}
+
+    iterator &
+    operator++()
+    {
+      next();
+
+      return *this;
+    }
+
+    iterator
+    operator++(int)
+    {
+      iterator result = *this;
+
+      next();
+
+      return result;
+    }
+
+    value_type
+    operator*() const
+    {
+      std::string_view name;
+      auto metric = _metrics.lookup(_it, &name);
+
+      return std::make_tuple(name, metric->load());
+    }
+
+    bool
+    operator==(const iterator &o) const
+    {
+      return _it == o._it && std::addressof(_metrics) == 
std::addressof(o._metrics);
+    }
+
+    bool
+    operator!=(const iterator &o) const
+    {
+      return _it != o._it || std::addressof(_metrics) != 
std::addressof(o._metrics);
+    }
+
+  private:
+    void next();
+
+    const Metrics &_metrics;
+    IdType _it;
+  };
+
+  iterator
+  begin() const
+  {
+    return iterator(*this, 0);
+  }
+
+  iterator
+  end() const
+  {
+    _mutex.lock();
+    int16_t blob   = _cur_blob;
+    int16_t offset = _cur_off;
+    _mutex.unlock();
+
+    return iterator(*this, _makeId(blob, offset));
+  }
+
+  iterator
+  find(const std::string_view name) const
+  {
+    auto id = lookup(name);
+
+    if (id == NOT_FOUND) {
+      return end();
+    } else {
+      return iterator(*this, id);
+    }
+  }
+
+private:
+  static constexpr std::tuple<uint16_t, uint16_t>
+  _splitID(IdType value)
+  {
+    return std::make_tuple(static_cast<uint16_t>(value >> 16), 
static_cast<uint16_t>(value & 0xFFFF));
+  }
+
+  static constexpr IdType
+  _makeId(uint16_t blob, uint16_t offset)
+  {
+    return (blob << 16 | offset);
+  }
+
+  static constexpr IdType
+  _makeId(std::tuple<uint16_t, uint16_t> id)
+  {
+    return _makeId(std::get<0>(id), std::get<1>(id));
+  }
+
+  void _addBlob();
+
+  mutable std::mutex _mutex;
+  LookupTable _lookups;
+  MetricBlobs _blobs;
+  uint16_t _cur_blob = 0;
+  uint16_t _cur_off  = 0;
+}; // class Metrics
+
+} // namespace ts
diff --git a/include/records/I_RecordsConfig.h 
b/include/records/I_RecordsConfig.h
index 2b16f7c030..df9ea60254 100644
--- a/include/records/I_RecordsConfig.h
+++ b/include/records/I_RecordsConfig.h
@@ -25,9 +25,6 @@
 
 #include "records/P_RecCore.h"
 
-// This is to manage the librecords table sizes. Not awesome, but better than 
the earlier recompiling of ATS requirement...
-extern int max_records_entries;
-
 enum RecordRequiredType {
   RR_NULL,    // config is _not_ required to be defined in records.yaml
   RR_REQUIRED // config _is_ required to be defined in record.config
diff --git a/include/records/P_RecCore.h b/include/records/P_RecCore.h
index 062bdec9df..1818ddd2a6 100644
--- a/include/records/P_RecCore.h
+++ b/include/records/P_RecCore.h
@@ -37,7 +37,7 @@
 #include <swoc/Errata.h>
 
 // records, record hash-table, and hash-table rwlock
-extern RecRecord *g_records;
+extern RecRecord g_records[REC_MAX_RECORDS];
 extern std::unordered_map<std::string, RecRecord *> g_records_ht;
 extern ink_rwlock g_records_rwlock;
 extern int g_num_records;
diff --git a/include/records/P_RecDefs.h b/include/records/P_RecDefs.h
index f4da85e75a..6755494a97 100644
--- a/include/records/P_RecDefs.h
+++ b/include/records/P_RecDefs.h
@@ -27,12 +27,10 @@
 
 #define REC_MESSAGE_ELE_MAGIC 0xF00DF00D
 
-// We need at least this many internal record entries for our configurations 
and metrics. Any
-// additional slots in librecords will be allocated to the plugin metrics. 
These should be
-// updated if we change the internal librecords size significantly.
-#define REC_INTERNAL_RECORDS    1100
-#define REC_DEFAULT_API_RECORDS 1400
-
+// We need at least this many internal record entries for our configurations 
and metrics.
+// This may need adjustments if we make significant additions to librecords. 
Note that
+// plugins are using their own metrics systems.
+#define REC_MAX_RECORDS               1500
 #define REC_CONFIG_UPDATE_INTERVAL_MS 3000
 #define REC_REMOTE_SYNC_INTERVAL_MS   5000
 
diff --git a/iocore/aio/Makefile.am b/iocore/aio/Makefile.am
index 0f767f235f..f816f97298 100644
--- a/iocore/aio/Makefile.am
+++ b/iocore/aio/Makefile.am
@@ -56,6 +56,7 @@ test_AIO_LDADD = \
        $(top_builddir)/src/records/librecords_p.a \
        $(top_builddir)/iocore/eventsystem/libinkevent.a \
        $(top_builddir)/src/tscore/libtscore.a \
+       $(top_builddir)/src/api/libtsapi.la \
        $(top_builddir)/src/tscpp/util/libtscpputil.la \
        @SWOC_LIBS@ @HWLOC_LIBS@ @YAMLCPP_LIBS@ @LIBPCRE@ @LIBCAP@
 
diff --git a/iocore/cache/Makefile.am b/iocore/cache/Makefile.am
index c021764d6e..34e65c2bbc 100644
--- a/iocore/cache/Makefile.am
+++ b/iocore/cache/Makefile.am
@@ -99,6 +99,7 @@ test_LDADD = \
        $(top_builddir)/iocore/utils/libinkutils.a \
        $(top_builddir)/iocore/aio/libinkaio.a \
        $(top_builddir)/src/records/librecords_p.a \
+       $(top_builddir)/src/api/libtsapi.la \
        $(top_builddir)/src/tscore/libtscore.a \
        $(top_builddir)/lib/fastlz/libfastlz.a \
        $(top_builddir)/iocore/eventsystem/libinkevent.a \
diff --git a/iocore/eventsystem/Makefile.am b/iocore/eventsystem/Makefile.am
index bb7965b167..082aac58fb 100644
--- a/iocore/eventsystem/Makefile.am
+++ b/iocore/eventsystem/Makefile.am
@@ -97,6 +97,7 @@ test_LD_ADD = \
        $(top_builddir)/src/records/librecords_p.a \
        $(top_builddir)/iocore/eventsystem/libinkevent.a \
        $(top_builddir)/src/tscore/libtscore.a \
+       $(top_builddir)/src/api/libtsapi.la \
        $(top_builddir)/src/tscpp/util/libtscpputil.la \
        @HWLOC_LIBS@ @SWOC_LIBS@ @YAMLCPP_LIBS@ @LIBPCRE@ @LIBCAP@
 
diff --git a/iocore/hostdb/Makefile.am b/iocore/hostdb/Makefile.am
index 6db40ac3de..87333102a7 100644
--- a/iocore/hostdb/Makefile.am
+++ b/iocore/hostdb/Makefile.am
@@ -67,6 +67,7 @@ test_LD_ADD = \
        $(top_builddir)/src/records/librecords_p.a \
        $(top_builddir)/iocore/eventsystem/libinkevent.a \
        $(top_builddir)/src/tscore/libtscore.a \
+       $(top_builddir)/src/api/libtsapi.la \
        $(top_builddir)/src/tscpp/util/libtscpputil.la \
        @SWOC_LIBS@ @HWLOC_LIBS@ @YAMLCPP_LIBS@ @OPENSSL_LIBS@ @LIBPCRE@ 
@LIBCAP@
 
diff --git a/iocore/net/Makefile.am b/iocore/net/Makefile.am
index 929dc79a86..b4c0c3895e 100644
--- a/iocore/net/Makefile.am
+++ b/iocore/net/Makefile.am
@@ -51,12 +51,13 @@ test_certlookup_SOURCES = \
        SSLCertLookup.cc
 
 test_certlookup_LDADD = \
-       @OPENSSL_LIBS@ \
-       $(top_builddir)/src/tscore/libtscore.a 
$(top_builddir)/src/tscpp/util/libtscpputil.la \
+       $(top_builddir)/src/tscore/libtscore.a \
+       $(top_builddir)/src/tscpp/util/libtscpputil.la \
        $(top_builddir)/iocore/eventsystem/libinkevent.a \
        $(top_builddir)/proxy/ParentSelectionStrategy.o \
        @YAMLCPP_LIBS@ \
        @SWOC_LIBS@ \
+       @OPENSSL_LIBS@ \
        @LIBPCRE@ \
        @LIBCAP@
 
@@ -84,7 +85,9 @@ test_UDPNet_LDADD = \
        $(top_builddir)/iocore/eventsystem/libinkevent.a \
        $(top_builddir)/src/records/librecords_p.a \
        $(top_builddir)/proxy/hdrs/libhdrs.a \
-       $(top_builddir)/src/tscore/libtscore.a 
$(top_builddir)/src/tscpp/util/libtscpputil.la \
+       $(top_builddir)/src/tscore/libtscore.a \
+       $(top_builddir)/src/tscpp/util/libtscpputil.la \
+       $(top_builddir)/src/api/libtsapi.la \
        $(top_builddir)/proxy/ParentSelectionStrategy.o \
        @HWLOC_LIBS@ @OPENSSL_LIBS@ @LIBPCRE@ @YAMLCPP_LIBS@ @SWOC_LIBS@ 
@LIBPCRE@ @LIBCAP@
 if ENABLE_QUIC
@@ -125,6 +128,7 @@ test_libinknet_LDADD = \
        $(top_builddir)/src/records/librecords_p.a \
        $(top_builddir)/proxy/hdrs/libhdrs.a \
        $(top_builddir)/src/tscore/libtscore.a \
+       $(top_builddir)/src/api/libtsapi.la \
        $(top_builddir)/src/tscpp/util/libtscpputil.la \
        $(top_builddir)/proxy/ParentSelectionStrategy.o \
        @HWLOC_LIBS@ @OPENSSL_LIBS@ @LIBPCRE@ @YAMLCPP_LIBS@ @SWOC_LIBS@ 
@LIBCAP@
diff --git a/mgmt/rpc/Makefile.am b/mgmt/rpc/Makefile.am
index 9ad923155e..7fe8c015d2 100644
--- a/mgmt/rpc/Makefile.am
+++ b/mgmt/rpc/Makefile.am
@@ -106,6 +106,7 @@ test_jsonrpcserver_LDADD = \
        $(top_builddir)/src/tscore/libtscore.a \
        $(top_builddir)/iocore/eventsystem/libinkevent.a \
        $(top_builddir)/src/records/librecords_p.a \
+       $(top_builddir)/src/api/libtsapi.la \
        $(top_builddir)/src/tscpp/util/libtscpputil.la \
        $(top_builddir)/src/tscore/libtscore.a \
        @YAMLCPP_LIBS@ @HWLOC_LIBS@  @SWOC_LIBS@ @YAMLCPP_LIBS@ @LIBPCRE@ 
@LIBCAP@
diff --git a/plugins/experimental/remap_stats/remap_stats.cc 
b/plugins/experimental/remap_stats/remap_stats.cc
index 71e2c628bd..27924404e3 100644
--- a/plugins/experimental/remap_stats/remap_stats.cc
+++ b/plugins/experimental/remap_stats/remap_stats.cc
@@ -46,9 +46,6 @@ struct config_t {
   int txn_slot{-1};
 };
 
-// From "core".... sigh, but we need it for now at least.
-extern int max_records_entries;
-
 namespace
 {
 void
diff --git a/proxy/hdrs/Makefile.am b/proxy/hdrs/Makefile.am
index 8b9cf9b9b2..70b9c2e118 100644
--- a/proxy/hdrs/Makefile.am
+++ b/proxy/hdrs/Makefile.am
@@ -89,6 +89,7 @@ test_proxy_hdrs_LDADD = \
        $(top_builddir)/src/records/librecords_p.a \
        $(top_builddir)/src/tscore/libtscore.a \
        $(top_builddir)/src/tscpp/util/libtscpputil.la \
+       $(top_builddir)/src/api/libtsapi.la \
        @SWOC_LIBS@ @YAMLCPP_LIBS@ @HWLOC_LIBS@ @LIBPCRE@ @OPENSSL_LIBS@ 
@LIBCAP@
 
 test_hdr_heap_CPPFLAGS = $(AM_CPPFLAGS) \
@@ -104,6 +105,7 @@ test_hdr_heap_LDADD = \
        $(top_builddir)/src/records/librecords_p.a \
        $(top_builddir)/src/tscore/libtscore.a \
        $(top_builddir)/src/tscpp/util/libtscpputil.la \
+       $(top_builddir)/src/api/libtsapi.la \
        @SWOC_LIBS@ @HWLOC_LIBS@ \
        @LIBPCRE@ @OPENSSL_LIBS@ @LIBCAP@
 
diff --git a/proxy/http/Makefile.am b/proxy/http/Makefile.am
index ae6493d87f..1184ff21be 100644
--- a/proxy/http/Makefile.am
+++ b/proxy/http/Makefile.am
@@ -110,6 +110,7 @@ test_proxy_http_LDADD = \
        $(top_builddir)/iocore/eventsystem/libinkevent.a \
        $(top_builddir)/iocore/utils/libinkutils.a \
        $(top_builddir)/src/tscore/libtscore.a \
+       $(top_builddir)/src/api/libtsapi.la \
        $(top_builddir)/src/tscpp/util/libtscpputil.la \
        @SWOC_LIBS@ @HWLOC_LIBS@ \
        @LIBCAP@ \
@@ -158,6 +159,7 @@ test_HttpTransact_LDADD  =  \
        $(top_builddir)/iocore/net/libinknet.a \
        $(top_builddir)/src/records/librecords_p.a \
        $(top_builddir)/src/tscore/libtscore.a \
+       $(top_builddir)/src/api/libtsapi.la \
        $(top_builddir)/iocore/eventsystem/libinkevent.a \
        -lz -llzma -lcrypto -lresolv -lssl \
        @LIBPCRE@ @HWLOC_LIBS@ @SWOC_LIBS@ @YAMLCPP_LIBS@ @LIBCAP@
diff --git a/proxy/http/remap/Makefile.am b/proxy/http/remap/Makefile.am
index 3bb9da1ff3..e61c0aeb4d 100644
--- a/proxy/http/remap/Makefile.am
+++ b/proxy/http/remap/Makefile.am
@@ -68,6 +68,7 @@ libhttp_remap_a_SOURCES = \
 COMMON_PLUGINDSO_LDADDS = \
        $(top_builddir)/iocore/eventsystem/libinkevent.a \
        $(top_builddir)/src/records/librecords_p.a \
+       $(top_builddir)/src/api/libtsapi.la \
        $(top_builddir)/iocore/eventsystem/libinkevent.a \
        $(top_builddir)/src/tscore/libtscore.a \
        $(top_builddir)/src/tscpp/util/libtscpputil.la \
@@ -137,6 +138,7 @@ test_NextHopStrategyFactory_LDADD = \
   $(top_builddir)/proxy/hdrs/libhdrs.a \
   $(top_builddir)/iocore/eventsystem/libinkevent.a \
   $(top_builddir)/src/records/librecords_p.a \
+  $(top_builddir)/src/api/libtsapi.la \
   $(top_builddir)/iocore/utils/libinkutils.a \
   $(top_builddir)/src/tscore/libtscore.a \
   $(top_builddir)/proxy/logging/liblogging.a \
@@ -171,6 +173,7 @@ test_NextHopRoundRobin_LDADD = \
   $(top_builddir)/proxy/hdrs/libhdrs.a \
   $(top_builddir)/iocore/eventsystem/libinkevent.a \
   $(top_builddir)/src/records/librecords_p.a \
+  $(top_builddir)/src/api/libtsapi.la \
   $(top_builddir)/proxy/logging/liblogging.a \
   $(top_builddir)/iocore/utils/libinkutils.a \
   $(top_builddir)/src/tscore/libtscore.a \
@@ -205,6 +208,7 @@ test_NextHopConsistentHash_LDADD = \
   $(top_builddir)/proxy/hdrs/libhdrs.a \
   $(top_builddir)/iocore/eventsystem/libinkevent.a \
   $(top_builddir)/src/records/librecords_p.a \
+  $(top_builddir)/src/api/libtsapi.la \
   $(top_builddir)/proxy/logging/liblogging.a \
   $(top_builddir)/iocore/utils/libinkutils.a \
   $(top_builddir)/src/tscore/libtscore.a \
@@ -247,6 +251,7 @@ pkglib_LTLIBRARIES = \
        unit-tests/plugin_missing_init.la \
        unit-tests/plugin_missing_newinstance.la \
        unit-tests/plugin_testing_calls.la
+
 unit_tests_plugin_v1_la_SOURCES = unit-tests/plugin_misc_cb.cc
 unit_tests_plugin_v1_la_LDFLAGS = $(DSO_LDFLAGS)
 unit_tests_plugin_v1_la_CPPFLAGS = -DPLUGINDSOVER=1 $(AM_CPPFLAGS)
diff --git a/proxy/http/unit_tests/CMakeLists.txt 
b/proxy/http/unit_tests/CMakeLists.txt
index 64cc7d3d1b..1f9ef16c43 100644
--- a/proxy/http/unit_tests/CMakeLists.txt
+++ b/proxy/http/unit_tests/CMakeLists.txt
@@ -35,6 +35,7 @@ target_link_libraries(test_http
     PRIVATE
         catch2::catch2
         ts::http
+        ts::tsapi
         ts::hdrs # transitive
         logging # transitive
         http_remap # transitive
diff --git a/proxy/http2/Makefile.am b/proxy/http2/Makefile.am
index 02ed791f32..6d385fd82f 100644
--- a/proxy/http2/Makefile.am
+++ b/proxy/http2/Makefile.am
@@ -72,6 +72,7 @@ test_libhttp2_LDADD = \
        Http2Frame.o \
        HPACK.o \
        $(top_builddir)/src/records/librecords_p.a \
+       $(top_builddir)/src/api/libtsapi.la \
        $(top_builddir)/iocore/eventsystem/libinkevent.a \
        $(top_builddir)/proxy/hdrs/libhdrs.a \
        $(top_builddir)/iocore/eventsystem/libinkevent.a \
@@ -129,6 +130,7 @@ test_HPACK_LDADD = \
        $(top_builddir)/iocore/eventsystem/libinkevent.a \
        $(top_builddir)/src/records/librecords_p.a \
        $(top_builddir)/src/tscore/libtscore.a \
+       $(top_builddir)/src/api/libtsapi.la \
        @SWOC_LIBS@ @HWLOC_LIBS@ @LIBPCRE@ @OPENSSL_LIBS@ @YAMLCPP_LIBS@ 
@LIBCAP@
 
 test_HPACK_SOURCES = \
diff --git a/proxy/http3/Makefile.am b/proxy/http3/Makefile.am
index 7abeebccf6..34497dd125 100644
--- a/proxy/http3/Makefile.am
+++ b/proxy/http3/Makefile.am
@@ -72,6 +72,7 @@ test_LDADD = \
   $(top_builddir)/iocore/net/TLSKeyLogger.o \
   $(top_builddir)/iocore/eventsystem/libinkevent.a \
   $(top_builddir)/src/records/librecords_p.a \
+  $(top_builddir)/src/api/libtsapi.la \
   $(top_builddir)/src/tscpp/util/libtscpputil.la \
   $(top_builddir)/proxy/hdrs/libhdrs.a \
   $(top_builddir)/src/tscore/libtscore.a \
diff --git a/proxy/logging/unit-tests/benchmark_LogObject.cc 
b/proxy/logging/unit-tests/benchmark_LogObject.cc
index 3db7020a07..6735c1b2e2 100644
--- a/proxy/logging/unit-tests/benchmark_LogObject.cc
+++ b/proxy/logging/unit-tests/benchmark_LogObject.cc
@@ -31,7 +31,7 @@ benchmark_LogObject_CPPFLAGS = \
        $(AM_CPPFLAGS) \
        -I$(abs_top_srcdir)/tests/include
 benchmark_LogObject_LDADD = \
-       $(top_builddir)/src/tscore/libtscore.la \
+       $(top_builddir)/src/tscore/libtscore.a \
        $(top_builddir)/src/tscpp/util/libtscpputil.la \
        $(top_builddir)/iocore/eventsystem/libinkevent.a \
        $(top_builddir)/proxy/logging/liblogging.a \
diff --git a/src/Makefile.am b/src/Makefile.am
index 8e95c0c4a9..e6aaddec1d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -23,7 +23,7 @@ TESTS =
 lib_LTLIBRARIES =
 noinst_PROGRAMS =
 
-SUBDIRS = tscpp/api
+SUBDIRS = tscpp/api api
 
 if BUILD_WCCP
 SUBDIRS += wccp
diff --git a/src/traffic_crashlog/CMakeLists.txt b/src/api/CMakeLists.txt
similarity index 69%
copy from src/traffic_crashlog/CMakeLists.txt
copy to src/api/CMakeLists.txt
index 3f43c20ba6..7d4cbe58eb 100644
--- a/src/traffic_crashlog/CMakeLists.txt
+++ b/src/api/CMakeLists.txt
@@ -15,13 +15,17 @@
 #
 #######################
 
-add_executable(traffic_crashlog procinfo.cc traffic_crashlog.cc)
+add_library(tsapi SHARED Metrics.cc)
+add_library(ts::tsapi ALIAS tsapi)
 
-target_link_libraries(traffic_crashlog
-    PRIVATE
-        ts::inkevent
-        ts::records
-        ts::tscore
-)
+install(TARGETS tsapi)
 
-install(TARGETS traffic_crashlog)
+
+add_executable(test_Metrics
+        test_Metrics.cc
+        )
+
+target_link_libraries(test_Metrics PRIVATE tsapi tscore)
+target_include_directories(test_Metrics PRIVATE ${CMAKE_SOURCE_DIR}/include 
${CATCH_INCLUDE_DIR})
+
+add_test(NAME test_Metrics COMMAND $<TARGET_FILE:test_Metrics>)
diff --git a/src/Makefile.am b/src/api/Makefile.am
similarity index 62%
copy from src/Makefile.am
copy to src/api/Makefile.am
index 8e95c0c4a9..4c1326b6ad 100644
--- a/src/Makefile.am
+++ b/src/api/Makefile.am
@@ -1,3 +1,4 @@
+# libts Makefile.am
 #
 #  Licensed to the Apache Software Foundation (ASF) under one
 #  or more contributor license agreements.  See the NOTICE file
@@ -17,28 +18,35 @@
 
 include $(top_srcdir)/mk/tidy.mk
 
-bin_PROGRAMS =
-check_PROGRAMS =
-TESTS =
-lib_LTLIBRARIES =
-noinst_PROGRAMS =
-
-SUBDIRS = tscpp/api
-
-if BUILD_WCCP
-SUBDIRS += wccp
-include traffic_wccp/Makefile.inc
-endif
-
-include traffic_cache_tool/Makefile.inc
-include traffic_via/Makefile.inc
-include traffic_top/Makefile.inc
-include traffic_server/Makefile.inc
-include traffic_logstats/Makefile.inc
-include traffic_crashlog/Makefile.inc
-include traffic_layout/Makefile.inc
-include traffic_logcat/Makefile.inc
-include traffic_ctl/Makefile.inc
+check_PROGRAMS = test_Metrics
+
+TESTS = $(check_PROGRAMS)
+
+lib_LTLIBRARIES = libtsapi.la
+
+AM_CPPFLAGS += \
+       -I$(abs_top_srcdir)/include \
+       @SWOC_INCLUDES@ \
+       $(TS_INCLUDES)
+
+libtsapi_la_LDFLAGS = @AM_LDFLAGS@ -version-info @TS_LIBTOOL_VERSION@ 
@SWOC_LDFLAGS@
+
+libtsapi_la_LIBADD = \
+       @SWOC_LIBS@
+
+
+libtsapi_la_SOURCES = \
+       Metrics.cc
+
+test_Metrics_SOURCES = test_Metrics.cc
+
+test_Metrics_CPPFLAGS = $(AM_CPPFLAGS)\
+       -I$(abs_top_srcdir)/lib/catch2
+
+test_Metrics_LDADD = \
+       $(top_builddir)/src/tscore/libtscore.a \
+       libtsapi.la
+
 
 clang-tidy-local: $(DIST_SOURCES)
        $(CXX_Clang_Tidy)
diff --git a/src/api/Metrics.cc b/src/api/Metrics.cc
new file mode 100644
index 0000000000..1d38e04ea2
--- /dev/null
+++ b/src/api/Metrics.cc
@@ -0,0 +1,139 @@
+/** @file
+
+  The implementations of the Metrics API class.
+
+  @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 "api/Metrics.h"
+
+namespace ts
+{
+
+// This is the singleton instance of the metrics class.
+Metrics &
+Metrics::getInstance()
+{
+  static ts::Metrics _instance;
+
+  return _instance;
+}
+
+void
+Metrics::_addBlob() // The mutex must be held before calling this!
+{
+  auto blob = new Metrics::MetricStorage();
+
+  ink_assert(blob);
+  ink_assert(_cur_blob < Metrics::METRICS_MAX_BLOBS);
+
+  _blobs[++_cur_blob] = blob;
+  _cur_off            = 0;
+}
+
+Metrics::IdType
+Metrics::newMetric(std::string_view name)
+{
+  std::lock_guard<std::mutex> lock(_mutex);
+  auto it = _lookups.find(name);
+
+  if (it != _lookups.end()) {
+    return it->second;
+  }
+
+  Metrics::IdType id                = _makeId(_cur_blob, _cur_off);
+  Metrics::MetricStorage *blob      = _blobs[_cur_blob];
+  Metrics::NameContainer &names     = std::get<0>(*blob);
+  Metrics::AtomicContainer &atomics = std::get<1>(*blob);
+
+  atomics[_cur_off].store(0);
+  names[_cur_off] = std::make_tuple(std::string(name), id);
+  _lookups.emplace(std::get<0>(names[_cur_off]), id);
+
+  if (++_cur_off >= Metrics::METRICS_MAX_SIZE) {
+    _addBlob(); // This resets _cur_off to 0 as well
+  }
+
+  return id;
+}
+
+Metrics::IdType
+Metrics::lookup(const std::string_view name) const
+{
+  std::lock_guard<std::mutex> lock(_mutex);
+  auto it = _lookups.find(name);
+
+  if (it != _lookups.end()) {
+    return it->second;
+  }
+
+  return NOT_FOUND;
+}
+
+Metrics::AtomicType *
+Metrics::lookup(IdType id, std::string_view *name) const
+{
+  auto [blob_ix, offset]       = _splitID(id);
+  Metrics::MetricStorage *blob = _blobs[blob_ix];
+
+  // Do a sanity check on the ID, to make sure we don't index outside of the 
realm of possibility.
+  if (!blob || (blob_ix == _cur_blob && offset > _cur_off)) {
+    blob   = _blobs[0];
+    offset = 0;
+  }
+
+  if (name) {
+    *name = std::get<0>(std::get<0>(*blob)[offset]);
+  }
+
+  return &((std::get<1>(*blob)[offset]));
+}
+
+std::string_view
+Metrics::name(Metrics::IdType id) const
+{
+  auto [blob_ix, offset]       = _splitID(id);
+  Metrics::MetricStorage *blob = _blobs[blob_ix];
+
+  // Do a sanity check on the ID, to make sure we don't index outside of the 
realm of possibility.
+  if (!blob || (blob_ix == _cur_blob && offset > _cur_off)) {
+    blob   = _blobs[0];
+    offset = 0;
+  }
+
+  const std::string &result = std::get<0>(std::get<0>(*blob)[offset]);
+
+  return result;
+}
+
+// Iterator implementation
+void
+Metrics::iterator::next()
+{
+  auto [blob, offset] = _metrics._splitID(_it);
+
+  if (++offset == METRICS_MAX_SIZE) {
+    ++blob;
+    offset = 0;
+  }
+
+  _it = _makeId(blob, offset);
+}
+
+} // namespace ts
diff --git a/src/api/test_Metrics.cc b/src/api/test_Metrics.cc
new file mode 100644
index 0000000000..6556754c84
--- /dev/null
+++ b/src/api/test_Metrics.cc
@@ -0,0 +1,65 @@
+/** @file
+
+    TextView unit tests.
+
+    @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.
+*/
+
+#define CATCH_CONFIG_MAIN
+#include "catch.hpp"
+
+#include "api/Metrics.h"
+
+TEST_CASE("Metrics", "[libtsapi][Metrics]")
+{
+  ts::Metrics m;
+
+  SECTION("iterator")
+  {
+    auto [name, value] = *m.begin();
+    REQUIRE(value == 0);
+    REQUIRE(name == "proxy.node.api.metrics.bad_id");
+
+    REQUIRE(m.begin() != m.end());
+    REQUIRE(++m.begin() == m.end());
+
+    auto it = m.begin();
+    it++;
+    REQUIRE(it == m.end());
+  }
+
+  SECTION("New metric")
+  {
+    auto fooid = m.newMetric("foo");
+
+    REQUIRE(fooid == 1);
+    REQUIRE(m.name(fooid) == "foo");
+
+    REQUIRE(m[fooid].load() == 0);
+    m.increment(fooid);
+    REQUIRE(m[fooid].load() == 1);
+  }
+
+  SECTION("operator[]")
+  {
+    m[0].store(42);
+
+    REQUIRE(m[0].load() == 42);
+  }
+}
diff --git a/src/records/Makefile.am b/src/records/Makefile.am
index c2188a73bd..62325ea907 100644
--- a/src/records/Makefile.am
+++ b/src/records/Makefile.am
@@ -72,6 +72,7 @@ test_librecords_LDADD = \
        $(top_builddir)/iocore/eventsystem/libinkevent.a \
        $(top_builddir)/src/tscpp/util/libtscpputil.la \
        $(top_builddir)/src/tscore/libtscore.a \
+       $(top_builddir)/src/api/libtsapi.la \
        @SWOC_LIBS@ @HWLOC_LIBS@ @LIBCAP@ @YAMLCPP_LIBS@ @LIBPCRE@ 
@OPENSSL_LIBS@
 
 test_librecords_on_eventsystem_CPPFLAGS = $(AM_CPPFLAGS)\
@@ -86,6 +87,7 @@ test_librecords_on_eventsystem_LDADD = \
        $(top_builddir)/iocore/eventsystem/libinkevent.a \
        $(top_builddir)/src/tscpp/util/libtscpputil.la \
        $(top_builddir)/src/tscore/libtscore.a \
+       $(top_builddir)/src/api/libtsapi.la \
        @HWLOC_LIBS@ @LIBCAP@ @YAMLCPP_LIBS@ @SWOC_LIBS@ @LIBPCRE@ 
@OPENSSL_LIBS@
 
 clang-tidy-local: $(sort $(DIST_SOURCES))
diff --git a/src/records/RecCore.cc b/src/records/RecCore.cc
index 8fa774aadd..54e0b93aa5 100644
--- a/src/records/RecCore.cc
+++ b/src/records/RecCore.cc
@@ -34,14 +34,11 @@
 #include "records/P_RecUtils.h"
 #include "tscore/I_Layout.h"
 #include "tscpp/util/ts_errata.h"
-
-// This is needed to manage the size of the librecords record. It can't be 
static, because it needs to be modified
-// and used (read) from several binaries / modules.
-int max_records_entries = REC_INTERNAL_RECORDS + REC_DEFAULT_API_RECORDS;
+#include "api/Metrics.h"
 
 static bool g_initialized = false;
 
-RecRecord *g_records = nullptr;
+RecRecord g_records[REC_MAX_RECORDS];
 std::unordered_map<std::string, RecRecord *> g_records_ht;
 ink_rwlock g_records_rwlock;
 int g_num_records = 0;
@@ -205,9 +202,6 @@ RecCoreInit(Diags *_diags)
 
   g_num_records = 0;
 
-  // initialize record array for our internal stats (this can be reallocated 
later)
-  g_records = static_cast<RecRecord *>(ats_malloc(max_records_entries * 
sizeof(RecRecord)));
-
   // initialize record rwlock
   ink_rwlock_init(&g_records_rwlock);
 
@@ -488,23 +482,38 @@ RecGetRecordBool(const char *name, RecBool *rec_bool, 
bool lock)
 RecErrT
 RecLookupRecord(const char *name, void (*callback)(const RecRecord *, void *), 
void *data, bool lock)
 {
-  RecErrT err = REC_ERR_FAIL;
+  RecErrT err              = REC_ERR_FAIL;
+  ts::Metrics &api_metrics = ts::Metrics::getInstance();
+  auto it                  = api_metrics.find(name);
 
-  if (lock) {
-    ink_rwlock_rdlock(&g_records_rwlock);
-  }
+  if (it != api_metrics.end()) {
+    RecRecord r;
+    auto &&[name, val] = *it;
 
-  if (auto it = g_records_ht.find(name); it != g_records_ht.end()) {
-    RecRecord *r = it->second;
+    r.rec_type     = RECT_PLUGIN;
+    r.data_type    = RECD_INT;
+    r.name         = name.data();
+    r.data.rec_int = val;
 
-    rec_mutex_acquire(&(r->lock));
-    callback(r, data);
+    callback(&r, data);
     err = REC_ERR_OKAY;
-    rec_mutex_release(&(r->lock));
-  }
+  } else {
+    if (lock) {
+      ink_rwlock_rdlock(&g_records_rwlock);
+    }
 
-  if (lock) {
-    ink_rwlock_unlock(&g_records_rwlock);
+    if (auto it = g_records_ht.find(name); it != g_records_ht.end()) {
+      RecRecord *r = it->second;
+
+      rec_mutex_acquire(&(r->lock));
+      callback(r, data);
+      err = REC_ERR_OKAY;
+      rec_mutex_release(&(r->lock));
+    }
+
+    if (lock) {
+      ink_rwlock_unlock(&g_records_rwlock);
+    }
   }
 
   return err;
@@ -520,6 +529,21 @@ RecLookupMatchingRecords(unsigned rec_type, const char 
*match, void (*callback)(
     return REC_ERR_FAIL;
   }
 
+  if (rec_type & RECT_PLUGIN) { // ToDo: This should change if we use the new 
metrics for core metrics
+    RecRecord r;
+
+    r.rec_type  = RECT_PLUGIN;
+    r.data_type = RECD_INT;
+
+    for (auto &&[name, val] : ts::Metrics::getInstance()) {
+      if (regex.match(name.data()) >= 0) {
+        r.name         = name.data();
+        r.data.rec_int = val;
+        callback(&r, data);
+      }
+    }
+  }
+
   num_records = g_num_records;
   for (int i = 0; i < num_records; i++) {
     RecRecord *r = &(g_records[i]);
@@ -1062,6 +1086,15 @@ RecDumpRecords(RecT rec_type, RecDumpEntryCb callback, 
void *edata)
       rec_mutex_release(&(r->lock));
     }
   }
+  // Also dump the new ts::Metrics if asked for
+  if (rec_type & RECT_PLUGIN) { // ToDo: This should change if we use the new 
metrics for core metrics
+    RecData datum;
+
+    for (auto &&[name, val] : ts::Metrics::getInstance()) {
+      datum.rec_int = val;
+      callback(RECT_PLUGIN, edata, true, name.data(), TS_RECORDDATATYPE_INT, 
&datum);
+    }
+  }
 }
 
 void
diff --git a/src/records/RecUtils.cc b/src/records/RecUtils.cc
index e229a41f6f..53f27afcbf 100644
--- a/src/records/RecUtils.cc
+++ b/src/records/RecUtils.cc
@@ -50,8 +50,8 @@ RecRecordFree(RecRecord *r)
 RecRecord *
 RecAlloc(RecT rec_type, const char *name, RecDataT data_type)
 {
-  if (g_num_records >= max_records_entries) {
-    Warning("too many stats/configs, please increase max_records_entries using 
the --maxRecords command line option");
+  if (g_num_records >= REC_MAX_RECORDS) {
+    Warning("too many stats/configs, please report a bug to 
d...@trafficserver.apache.org");
     return nullptr;
   }
 
diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt
index 3e59226c69..6ba08015e3 100644
--- a/src/tests/CMakeLists.txt
+++ b/src/tests/CMakeLists.txt
@@ -46,7 +46,9 @@ link_libraries(
         inkcache
         fastlz
         aio
+        records
         tscore
+        tsapi
         tscpputil
         proxy
         inknet
diff --git a/src/traffic_crashlog/CMakeLists.txt 
b/src/traffic_crashlog/CMakeLists.txt
index 3f43c20ba6..13df48df1b 100644
--- a/src/traffic_crashlog/CMakeLists.txt
+++ b/src/traffic_crashlog/CMakeLists.txt
@@ -22,6 +22,7 @@ target_link_libraries(traffic_crashlog
         ts::inkevent
         ts::records
         ts::tscore
+        ts::tsapi
 )
 
 install(TARGETS traffic_crashlog)
diff --git a/src/traffic_crashlog/Makefile.inc 
b/src/traffic_crashlog/Makefile.inc
index f7c69fe6d8..e73314ab6c 100644
--- a/src/traffic_crashlog/Makefile.inc
+++ b/src/traffic_crashlog/Makefile.inc
@@ -41,4 +41,5 @@ traffic_crashlog_traffic_crashlog_LDADD = \
        $(top_builddir)/iocore/net/libinknet.a \
        $(top_builddir)/src/tscore/libtscore.a \
        $(top_builddir)/src/tscpp/util/libtscpputil.la \
+       $(top_builddir)/src/api/libtsapi.la \
        @HWLOC_LIBS@ @SWOC_LIBS@ @YAMLCPP_LIBS@ @LIBPCRE@ @LIBCAP@
diff --git a/src/traffic_layout/CMakeLists.txt 
b/src/traffic_layout/CMakeLists.txt
index e898d65cba..7a02a6a507 100644
--- a/src/traffic_layout/CMakeLists.txt
+++ b/src/traffic_layout/CMakeLists.txt
@@ -28,6 +28,10 @@ target_link_libraries(traffic_layout
         ts::records
         OpenSSL::Crypto
         yaml-cpp::yaml-cpp
+        ts::tscore
+        ts::tsapi
+        PCRE::PCRE
+        ${OPENSSL_LIBRARY}
 )
 
 if(TS_USE_HWLOC)
diff --git a/src/traffic_layout/Makefile.inc b/src/traffic_layout/Makefile.inc
index 6f7409c9d0..d4f2637a90 100644
--- a/src/traffic_layout/Makefile.inc
+++ b/src/traffic_layout/Makefile.inc
@@ -45,4 +45,5 @@ traffic_layout_traffic_layout_LDADD = \
        $(top_builddir)/src/records/librecords_p.a \
        $(top_builddir)/src/tscore/libtscore.a \
        $(top_builddir)/src/tscpp/util/libtscpputil.la \
+       $(top_builddir)/src/api/libtsapi.la \
        @SWOC_LIBS@ @HWLOC_LIBS@ @YAMLCPP_LIBS@ @LIBLZMA@ @LIBPCRE@ @LIBCAP@
diff --git a/src/traffic_logcat/Makefile.inc b/src/traffic_logcat/Makefile.inc
index 44677d66f3..199c851b1f 100644
--- a/src/traffic_logcat/Makefile.inc
+++ b/src/traffic_logcat/Makefile.inc
@@ -46,6 +46,7 @@ traffic_logcat_traffic_logcat_LDADD = \
        $(top_builddir)/iocore/utils/libinkutils.a \
        $(top_builddir)/src/tscore/libtscore.a \
        $(top_builddir)/src/tscpp/util/libtscpputil.la \
+       $(top_builddir)/src/api/libtsapi.la \
        @SWOC_LIBS@ @HWLOC_LIBS@ \
        @YAMLCPP_LIBS@ @LIBPCRE@ @OPENSSL_LIBS@ @LIBCAP@ \
        @LIBPROFILER@ -lm
diff --git a/src/traffic_logstats/Makefile.inc 
b/src/traffic_logstats/Makefile.inc
index 3afd3960d8..f446f49735 100644
--- a/src/traffic_logstats/Makefile.inc
+++ b/src/traffic_logstats/Makefile.inc
@@ -50,11 +50,12 @@ traffic_logstats_traffic_logstats_LDADD = \
        $(top_builddir)/iocore/eventsystem/libinkevent.a \
        $(top_builddir)/iocore/utils/libinkutils.a \
        $(top_builddir)/src/tscore/libtscore.a \
+       $(top_builddir)/src/api/libtsapi.la \
        $(top_builddir)/src/tscpp/util/libtscpputil.la \
+       @OPENSSL_LIBS@ \
        @SWOC_LIBS@ \
        @HWLOC_LIBS@ \
-       @OPENSSL_LIBS@ \
+       @LIBCAP@ \
        @LIBPCRE@ \
        @YAMLCPP_LIBS@ \
-       @LIBCAP@ \
        @LIBPROFILER@ -lm
diff --git a/src/traffic_server/CMakeLists.txt 
b/src/traffic_server/CMakeLists.txt
index 390c8edefd..35325b9026 100644
--- a/src/traffic_server/CMakeLists.txt
+++ b/src/traffic_server/CMakeLists.txt
@@ -35,6 +35,7 @@ target_include_directories(traffic_server PRIVATE
 target_link_libraries(traffic_server
     PRIVATE
         ts::tscore
+        ts::tsapi
         ts::http
         ts::http_remap
         ts::http2
diff --git a/src/traffic_server/InkAPI.cc b/src/traffic_server/InkAPI.cc
index a400fc3d36..3ad360b06a 100644
--- a/src/traffic_server/InkAPI.cc
+++ b/src/traffic_server/InkAPI.cc
@@ -34,6 +34,7 @@
 #include "tscore/I_Layout.h"
 #include "tscore/I_Version.h"
 #include "tscore/Diags.h"
+#include "api/Metrics.h"
 
 #include "InkAPIInternal.h"
 #include "Log.h"
@@ -102,10 +103,6 @@
 
 extern AppVersionInfo appVersionInfo;
 
-// Globals for new librecords stats
-static int api_rsb_index;
-static RecRawStatBlock *api_rsb;
-
 /** Reservation for a user arg.
  */
 struct UserArg {
@@ -389,6 +386,7 @@ HttpAPIHooks *http_global_hooks        = nullptr;
 SslAPIHooks *ssl_hooks                 = nullptr;
 LifecycleAPIHooks *lifecycle_hooks     = nullptr;
 ConfigUpdateCbTable *global_config_cbs = nullptr;
+static ts::Metrics &global_api_metrics = ts::Metrics::getInstance();
 
 static char traffic_server_version[128] = "";
 static int ts_major_version             = 0;
@@ -752,11 +750,7 @@ sdk_sanity_check_null_ptr(void const *ptr)
 static TSReturnCode
 sdk_sanity_check_stat_id(int id)
 {
-  if (id < 0 || id >= api_rsb->max_stats) {
-    return TS_ERROR;
-  }
-
-  return TS_SUCCESS;
+  return (global_api_metrics.valid(id) ? TS_SUCCESS : TS_ERROR);
 }
 
 static TSReturnCode
@@ -1829,18 +1823,6 @@ api_init()
     lifecycle_hooks   = new LifecycleAPIHooks;
     global_config_cbs = new ConfigUpdateCbTable;
 
-    int api_metrics = max_records_entries - REC_INTERNAL_RECORDS;
-    if (api_metrics > 0) {
-      api_rsb = RecAllocateRawStatBlock(api_metrics);
-      if (nullptr == api_rsb) {
-        Warning("Can't allocate API stats block");
-      } else {
-        Debug("sdk", "initialized SDK stats APIs with %d slots", api_metrics);
-      }
-    } else {
-      api_rsb = nullptr;
-    }
-
     // Setup the version string for returning to plugins
     ink_strlcpy(traffic_server_version, appVersionInfo.VersionStr, 
sizeof(traffic_server_version));
     // Extract the elements.
@@ -7511,40 +7493,9 @@ TSCacheScan(TSCont contp, TSCacheKey key, int 
KB_per_second)
 int
 TSStatCreate(const char *the_name, TSRecordDataType the_type, 
TSStatPersistence persist, TSStatSync sync)
 {
-  int id                  = ink_atomic_increment(&api_rsb_index, 1);
-  RecRawStatSyncCb syncer = RecRawStatSyncCount;
-
-  // TODO: This only supports "int" data types at this point, since the "Raw" 
stats
-  // interfaces only supports integers. Going forward, we could extend either 
the "Raw"
-  // stats APIs, or make non-int use the direct (synchronous) stats APIs 
(slower).
-  if ((sdk_sanity_check_null_ptr((void *)the_name) != TS_SUCCESS) || 
(sdk_sanity_check_null_ptr((void *)api_rsb) != TS_SUCCESS) ||
-      (id >= api_rsb->max_stats)) {
-    return TS_ERROR;
-  }
-
-  switch (sync) {
-  case TS_STAT_SYNC_SUM:
-    syncer = RecRawStatSyncSum;
-    break;
-  case TS_STAT_SYNC_AVG:
-    syncer = RecRawStatSyncAvg;
-    break;
-  case TS_STAT_SYNC_TIMEAVG:
-    syncer = RecRawStatSyncHrTimeAvg;
-    break;
-  default:
-    syncer = RecRawStatSyncCount;
-    break;
-  }
+  int id = global_api_metrics.newMetric(the_name);
 
-  switch (persist) {
-  case TS_STAT_PERSISTENT:
-    RecRegisterRawStat(api_rsb, RECT_PLUGIN, the_name, (RecDataT)the_type, 
RECP_PERSISTENT, id, syncer);
-    break;
-  case TS_STAT_NON_PERSISTENT:
-    RecRegisterRawStat(api_rsb, RECT_PLUGIN, the_name, (RecDataT)the_type, 
RECP_NON_PERSISTENT, id, syncer);
-    break;
-  default:
+  if (id == ts::Metrics::NOT_FOUND) {
     return TS_ERROR;
   }
 
@@ -7555,49 +7506,44 @@ void
 TSStatIntIncrement(int id, TSMgmtInt amount)
 {
   sdk_assert(sdk_sanity_check_stat_id(id) == TS_SUCCESS);
-  RecIncrRawStat(api_rsb, nullptr, id, amount);
+  global_api_metrics[id].fetch_add(amount);
 }
 
 void
 TSStatIntDecrement(int id, TSMgmtInt amount)
 {
-  RecDecrRawStat(api_rsb, nullptr, id, amount);
+  sdk_assert(sdk_sanity_check_stat_id(id) == TS_SUCCESS);
+  global_api_metrics[id].fetch_sub(amount);
 }
 
 TSMgmtInt
 TSStatIntGet(int id)
 {
-  TSMgmtInt value;
-
   sdk_assert(sdk_sanity_check_stat_id(id) == TS_SUCCESS);
-  RecGetGlobalRawStatSum(api_rsb, id, &value);
-  return value;
+  return global_api_metrics[id].load();
 }
 
 void
 TSStatIntSet(int id, TSMgmtInt value)
 {
   sdk_assert(sdk_sanity_check_stat_id(id) == TS_SUCCESS);
-  RecSetGlobalRawStatSum(api_rsb, id, value);
+  global_api_metrics[id].store(value);
 }
 
 TSReturnCode
 TSStatFindName(const char *name, int *idp)
 {
-  int id;
-
   sdk_assert(sdk_sanity_check_null_ptr((void *)name) == TS_SUCCESS);
+  sdk_assert(sdk_sanity_check_null_ptr((void *)idp) == TS_SUCCESS);
 
-  if (RecGetRecordOrderAndId(name, nullptr, &id, true, true) != REC_ERR_OKAY) {
-    return TS_ERROR;
-  }
+  int id = global_api_metrics.lookup(name);
 
-  if (RecGetGlobalRawStatPtr(api_rsb, id) == nullptr) {
+  if (id == ts::Metrics::NOT_FOUND) {
     return TS_ERROR;
+  } else {
+    *idp = id;
+    return TS_SUCCESS;
   }
-
-  *idp = id;
-  return TS_SUCCESS;
 }
 
 /**************************   Tracing API   ****************************/
diff --git a/src/traffic_server/Makefile.inc b/src/traffic_server/Makefile.inc
index 136c1a52aa..4926ce79e6 100644
--- a/src/traffic_server/Makefile.inc
+++ b/src/traffic_server/Makefile.inc
@@ -78,6 +78,7 @@ traffic_server_traffic_server_LDADD = \
        $(top_builddir)/iocore/cache/libinkcache.a \
        $(top_builddir)/lib/fastlz/libfastlz.a \
        $(top_builddir)/iocore/aio/libinkaio.a \
+       $(top_builddir)/src/api/libtsapi.la \
        $(top_builddir)/proxy/libproxy.a \
        $(top_builddir)/iocore/net/libinknet.a \
        $(top_builddir)/src/records/librecords_p.a \
diff --git a/src/traffic_server/traffic_server.cc 
b/src/traffic_server/traffic_server.cc
index fd9a3635b0..cd52b915a7 100644
--- a/src/traffic_server/traffic_server.cc
+++ b/src/traffic_server/traffic_server.cc
@@ -207,8 +207,6 @@ static ArgumentDescription argument_descriptions[] = {
   {"disable_freelist",  'f', "Disable the freelist memory allocator",          
                                                     "T",     
&cmd_disable_freelist,           "PROXY_DPRINTF_LEVEL",     nullptr},
   {"disable_pfreelist", 'F', "Disable the freelist memory allocator in 
ProxyAllocator",                                             "T",     
&cmd_disable_pfreelist,
    "PROXY_DPRINTF_LEVEL",                                                      
                                                                                
                                          nullptr},
-  {"maxRecords",        'm', "Max number of librecords metrics and 
configurations (default & minimum: 1600)",                       "I",     
&max_records_entries,
-   "PROXY_MAX_RECORDS",                                                        
                                                                                
                                          nullptr},
 
 #if TS_HAS_TESTS
   {"regression",        'R', "Regression Level (quick:1..long:3)",             
                                                     "I",     
&regression_level,               "PROXY_REGRESSION",        nullptr},
diff --git a/tools/benchmark/Makefile.am b/tools/benchmark/Makefile.am
index 93417a0fff..772fe19208 100644
--- a/tools/benchmark/Makefile.am
+++ b/tools/benchmark/Makefile.am
@@ -49,6 +49,7 @@ benchmark_LD_ADD = \
        $(top_builddir)/iocore/eventsystem/libinkevent.a \
        $(top_builddir)/src/records/librecords_p.a \
        $(top_builddir)/src/tscore/libtscore.a \
+       $(top_builddir)/src/api/libtsapi.la \
        $(top_builddir)/src/tscpp/util/libtscpputil.la \
        @HWLOC_LIBS@ \
     @LIBPCRE@ \


Reply via email to