Skip to content

Commit 95ac751

Browse files
authored
Add support for storing and retrieving metric type (#12392)
* Add support for storing and retrieving metric type * remove UNKNOWN and use COUNTER as a default(0) value. cleanup. Fix max blobs * Only use 3 bits for metric type and restore max blobs
1 parent 347a5a3 commit 95ac751

File tree

5 files changed

+125
-65
lines changed

5 files changed

+125
-65
lines changed

include/tsutil/Metrics.h

Lines changed: 48 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -82,13 +82,17 @@ class Metrics
8282
std::atomic<int64_t> _value{0};
8383
};
8484

85+
enum class MetricType : int { COUNTER = 0, GAUGE };
86+
8587
using IdType = int32_t; // Could be a tuple, but one way or another, they have to be combined to an int32_t.
8688
using SpanType = swoc::MemSpan<AtomicType>;
8789

88-
static constexpr uint16_t MAX_BLOBS = 8192;
89-
static constexpr uint16_t MAX_SIZE = 1024; // For a total of 8M metrics
90-
static constexpr IdType NOT_FOUND = std::numeric_limits<IdType>::min(); // <16-bit,16-bit> = <blob-index,offset>
91-
static const auto MEMORY_ORDER = std::memory_order_relaxed;
90+
static constexpr uint16_t MAX_BLOBS = 8192;
91+
static constexpr uint16_t MAX_SIZE = 1024; // For a total of 8M metrics
92+
static constexpr IdType NOT_FOUND = std::numeric_limits<IdType>::min(); // <16-bit,16-bit> = <blob-index,offset>
93+
static const auto MEMORY_ORDER = std::memory_order_relaxed;
94+
static constexpr int METRIC_TYPE_BITS = 29;
95+
static constexpr int METRIC_TYPE_MASK = 0x1FFF;
9296

9397
private:
9498
using NameAndId = std::tuple<std::string, IdType>;
@@ -122,9 +126,9 @@ class Metrics
122126
return _storage->lookup(name, out_id);
123127
}
124128
AtomicType *
125-
lookup(IdType id, std::string_view *out_name = nullptr) const
129+
lookup(IdType id, std::string_view *out_name = nullptr, Metrics::MetricType *type = nullptr) const
126130
{
127-
return _storage->lookup(id, out_name);
131+
return _storage->lookup(id, out_name, type);
128132
}
129133
bool
130134
rename(IdType id, const std::string_view name)
@@ -166,6 +170,12 @@ class Metrics
166170
return _storage->name(id);
167171
}
168172

173+
MetricType
174+
type(IdType id) const
175+
{
176+
return _storage->type(id);
177+
}
178+
169179
bool
170180
valid(IdType id) const
171181
{
@@ -177,7 +187,7 @@ class Metrics
177187
{
178188
public:
179189
using iterator_category = std::input_iterator_tag;
180-
using value_type = std::tuple<std::string_view, int64_t>;
190+
using value_type = std::tuple<std::string_view, MetricType, int64_t>;
181191
using difference_type = ptrdiff_t;
182192
using pointer = value_type *;
183193
using reference = value_type &;
@@ -206,9 +216,10 @@ class Metrics
206216
operator*() const
207217
{
208218
std::string_view name;
209-
auto metric = _metrics.lookup(_it, &name);
219+
MetricType type;
220+
auto metric = _metrics.lookup(_it, &name, &type);
210221

211-
return std::make_tuple(name, metric->_value.load());
222+
return std::make_tuple(name, type, metric->_value.load());
212223
}
213224

214225
bool
@@ -241,7 +252,7 @@ class Metrics
241252
{
242253
auto [blob, offset] = _storage->current();
243254

244-
return iterator(*this, _makeId(blob, offset));
255+
return iterator(*this, _makeId(blob, offset, MetricType::COUNTER));
245256
}
246257

247258
iterator
@@ -259,34 +270,35 @@ class Metrics
259270
private:
260271
// These are private, to assure that we don't use them by accident creating naked metrics
261272
IdType
262-
_create(const std::string_view name)
273+
_create(const std::string_view name, MetricType type)
263274
{
264-
return _storage->create(name);
275+
return _storage->create(name, type);
265276
}
266277

267278
SpanType
268-
_createSpan(size_t size, IdType *id = nullptr)
279+
_createSpan(size_t size, MetricType type, IdType *id = nullptr)
269280
{
270-
return _storage->createSpan(size, id);
281+
return _storage->createSpan(size, type, id);
271282
}
272283

273284
// These are little helpers around managing the ID's
274285
static constexpr std::tuple<uint16_t, uint16_t>
275286
_splitID(IdType value)
276287
{
277-
return std::make_tuple(static_cast<uint16_t>(value >> 16), static_cast<uint16_t>(value & 0xFFFF));
288+
return std::make_tuple(static_cast<uint16_t>(value >> 16) & METRIC_TYPE_MASK, static_cast<uint16_t>(value & 0xFFFF));
278289
}
279290

280-
static constexpr IdType
281-
_makeId(uint16_t blob, uint16_t offset)
291+
static constexpr MetricType
292+
_extractType(IdType value)
282293
{
283-
return (blob << 16 | offset);
294+
return MetricType{value >> METRIC_TYPE_BITS};
284295
}
285296

286297
static constexpr IdType
287-
_makeId(std::tuple<uint16_t, uint16_t> id)
298+
_makeId(uint16_t blob, uint16_t offset, const MetricType type)
288299
{
289-
return _makeId(std::get<0>(id), std::get<1>(id));
300+
int t = static_cast<int>(type);
301+
return (t << METRIC_TYPE_BITS | blob << 16 | offset);
290302
}
291303

292304
class Storage
@@ -305,18 +317,20 @@ class Metrics
305317
{
306318
_blobs[0] = std::make_unique<NamesAndAtomics>();
307319
release_assert(_blobs[0]);
308-
release_assert(0 == create("proxy.process.api.metrics.bad_id")); // Reserve slot 0 for errors, this should always be 0
320+
// Reserve slot 0 for errors, this should always be 0
321+
release_assert(0 == create("proxy.process.api.metrics.bad_id", MetricType::COUNTER));
309322
}
310323

311324
~Storage() {}
312325

313-
IdType create(const std::string_view name);
326+
IdType create(const std::string_view name, const MetricType type = MetricType::COUNTER);
314327
void addBlob();
315328
IdType lookup(const std::string_view name) const;
316-
AtomicType *lookup(const std::string_view name, IdType *out_id) const;
317-
AtomicType *lookup(Metrics::IdType id, std::string_view *out_name = nullptr) const;
329+
AtomicType *lookup(const std::string_view name, IdType *out_id, MetricType *out_type = nullptr) const;
330+
AtomicType *lookup(Metrics::IdType id, std::string_view *out_name = nullptr, MetricType *out_type = nullptr) const;
318331
std::string_view name(IdType id) const;
319-
SpanType createSpan(size_t size, IdType *id = nullptr);
332+
MetricType type(IdType id) const;
333+
SpanType createSpan(size_t size, const MetricType type = MetricType::COUNTER, IdType *id = nullptr);
320334
bool rename(IdType id, const std::string_view name);
321335

322336
std::pair<int16_t, int16_t>
@@ -380,15 +394,15 @@ class Metrics
380394
{
381395
auto &instance = Metrics::instance();
382396

383-
return instance._create(name);
397+
return instance._create(name, MetricType::GAUGE);
384398
}
385399

386400
static AtomicType *
387401
createPtr(const std::string_view name)
388402
{
389403
auto &instance = Metrics::instance();
390404

391-
return reinterpret_cast<AtomicType *>(instance.lookup(instance._create(name)));
405+
return reinterpret_cast<AtomicType *>(instance.lookup(instance._create(name, MetricType::GAUGE)));
392406
}
393407

394408
static AtomicType *
@@ -397,15 +411,15 @@ class Metrics
397411
auto &instance = Metrics::instance();
398412
std::string tmpname = std::string(prefix) + std::string(name);
399413

400-
return reinterpret_cast<AtomicType *>(instance.lookup(instance._create(tmpname)));
414+
return reinterpret_cast<AtomicType *>(instance.lookup(instance._create(tmpname, MetricType::GAUGE)));
401415
}
402416

403417
static Metrics::Gauge::SpanType
404418
createSpan(size_t size, IdType *id = nullptr)
405419
{
406420
auto &instance = Metrics::instance();
407421

408-
return instance._createSpan(size, id);
422+
return instance._createSpan(size, MetricType::GAUGE, id);
409423
}
410424

411425
static void
@@ -477,15 +491,15 @@ class Metrics
477491
{
478492
auto &instance = Metrics::instance();
479493

480-
return instance._create(name);
494+
return instance._create(name, MetricType::COUNTER);
481495
}
482496

483497
static AtomicType *
484498
createPtr(const std::string_view name)
485499
{
486500
auto &instance = Metrics::instance();
487501

488-
return reinterpret_cast<AtomicType *>(instance.lookup(instance._create(name)));
502+
return reinterpret_cast<AtomicType *>(instance.lookup(instance._create(name, MetricType::COUNTER)));
489503
}
490504

491505
static AtomicType *
@@ -494,15 +508,15 @@ class Metrics
494508
auto &instance = Metrics::instance();
495509
std::string tmpname = std::string(prefix) + std::string(name);
496510

497-
return reinterpret_cast<AtomicType *>(instance.lookup(instance._create(tmpname)));
511+
return reinterpret_cast<AtomicType *>(instance.lookup(instance._create(tmpname, MetricType::COUNTER)));
498512
}
499513

500514
static Metrics::Counter::SpanType
501515
createSpan(size_t size, IdType *id = nullptr)
502516
{
503517
auto &instance = Metrics::instance();
504518

505-
return instance._createSpan(size, id);
519+
return instance._createSpan(size, MetricType::COUNTER, id);
506520
}
507521

508522
static void
@@ -531,6 +545,7 @@ class Metrics
531545
struct DerivedMetricSpec {
532546
using MetricSpec = std::variant<Metrics::AtomicType *, Metrics::IdType, std::string_view>;
533547
std::string_view derived_name;
548+
Metrics::MetricType derived_type;
534549
std::initializer_list<MetricSpec> derived_from;
535550
};
536551

src/proxy/http/HttpConfig.cc

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -596,43 +596,59 @@ register_stat_callbacks()
596596
Metrics::Derived::derive({
597597
// Total bytes of client request body + headers
598598
{"proxy.process.http.user_agent_total_request_bytes",
599-
{http_rsb.user_agent_request_document_total_size, http_rsb.user_agent_request_header_total_size} },
599+
Metrics::MetricType::COUNTER,
600+
{http_rsb.user_agent_request_document_total_size, http_rsb.user_agent_request_header_total_size} },
600601
// Total bytes of client response body + headers
601602
{"proxy.process.http.user_agent_total_response_bytes",
602-
{http_rsb.user_agent_response_document_total_size, http_rsb.user_agent_response_header_total_size} },
603+
Metrics::MetricType::COUNTER,
604+
{http_rsb.user_agent_response_document_total_size, http_rsb.user_agent_response_header_total_size} },
603605
// Total bytes of origin server request body + headers
604606
{"proxy.process.http.origin_server_total_request_bytes",
605-
{http_rsb.origin_server_request_document_total_size, http_rsb.origin_server_request_header_total_size} },
607+
Metrics::MetricType::COUNTER,
608+
{http_rsb.origin_server_request_document_total_size, http_rsb.origin_server_request_header_total_size} },
606609
// Total bytes of origin server response body + headers
607610
{"proxy.process.http.origin_server_total_response_bytes",
608-
{http_rsb.origin_server_response_document_total_size, http_rsb.origin_server_response_header_total_size} },
611+
Metrics::MetricType::COUNTER,
612+
{http_rsb.origin_server_response_document_total_size, http_rsb.origin_server_response_header_total_size} },
609613
// Total bytes of client request and response (total traffic to and from clients)
610614
{"proxy.process.user_agent_total_bytes",
611-
{"proxy.process.http.user_agent_total_request_bytes", "proxy.process.http.user_agent_total_response_bytes"} },
615+
Metrics::MetricType::COUNTER,
616+
{"proxy.process.http.user_agent_total_request_bytes", "proxy.process.http.user_agent_total_response_bytes"} },
612617
// Total bytes of origin/parent request and response
613618
{"proxy.process.origin_server_total_bytes",
619+
Metrics::MetricType::COUNTER,
614620
{"proxy.process.http.origin_server_total_request_bytes", "proxy.process.http.origin_server_total_response_bytes",
615-
http_rsb.parent_proxy_request_total_bytes, http_rsb.parent_proxy_response_total_bytes} },
621+
http_rsb.parent_proxy_request_total_bytes, http_rsb.parent_proxy_response_total_bytes} },
616622
// Total requests which are cache hits
617623
{"proxy.process.cache_total_hits",
618-
{http_rsb.cache_hit_fresh, http_rsb.cache_hit_reval, http_rsb.cache_hit_ims, http_rsb.cache_hit_stale_served} },
624+
Metrics::MetricType::COUNTER,
625+
{http_rsb.cache_hit_fresh, http_rsb.cache_hit_reval, http_rsb.cache_hit_ims, http_rsb.cache_hit_stale_served} },
619626
// Total requests which are cache misses
620627
{"proxy.process.cache_total_misses",
628+
Metrics::MetricType::COUNTER,
621629
{http_rsb.cache_miss_cold, http_rsb.cache_miss_changed, http_rsb.cache_miss_client_no_cache, http_rsb.cache_miss_ims,
622-
http_rsb.cache_miss_uncacheable} },
630+
http_rsb.cache_miss_uncacheable} },
623631
// Total of all server connections (sum of origins and parent connections)
624-
{"proxy.process.current_server_connections", {http_rsb.current_server_connections, http_rsb.current_parent_proxy_connections} },
632+
{"proxy.process.current_server_connections",
633+
Metrics::MetricType::GAUGE,
634+
{http_rsb.current_server_connections, http_rsb.current_parent_proxy_connections} },
625635
// Total requests, both hits and misses (this is slightly superfluous, but assures correct percentage calculations)
626-
{"proxy.process.cache_total_requests", {"proxy.process.cache_total_hits", "proxy.process.cache_total_misses"} },
636+
{"proxy.process.cache_total_requests",
637+
Metrics::MetricType::COUNTER,
638+
{"proxy.process.cache_total_hits", "proxy.process.cache_total_misses"} },
627639
// Total cache requests bytes which are cache hits
628640
{"proxy.process.cache_total_hits_bytes",
629-
{http_rsb.tcp_hit_user_agent_bytes, http_rsb.tcp_refresh_hit_user_agent_bytes, http_rsb.tcp_ims_hit_user_agent_bytes} },
641+
Metrics::MetricType::COUNTER,
642+
{http_rsb.tcp_hit_user_agent_bytes, http_rsb.tcp_refresh_hit_user_agent_bytes, http_rsb.tcp_ims_hit_user_agent_bytes}},
630643
// Total cache requests bytes which are cache misses
631644
{"proxy.process.cache_total_misses_bytes",
645+
Metrics::MetricType::COUNTER,
632646
{http_rsb.tcp_miss_user_agent_bytes, http_rsb.tcp_expired_miss_user_agent_bytes, http_rsb.tcp_refresh_miss_user_agent_bytes,
633-
http_rsb.tcp_ims_miss_user_agent_bytes} },
647+
http_rsb.tcp_ims_miss_user_agent_bytes} },
634648
// Total request bytes, both hits and misses
635-
{"proxy.process.cache_total_bytes", {"proxy.process.cache_total_hits_bytes", "proxy.process.cache_total_misses_bytes"}}
649+
{"proxy.process.cache_total_bytes",
650+
Metrics::MetricType::COUNTER,
651+
{"proxy.process.cache_total_hits_bytes", "proxy.process.cache_total_misses_bytes"} }
636652
});
637653
}
638654

src/records/RecCore.cc

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <utility>
2626
#include <iostream>
2727

28+
#include "records/RecDefs.h"
2829
#include "swoc/swoc_file.h"
2930

3031
#include "tscore/ink_platform.h"
@@ -520,10 +521,10 @@ RecLookupRecord(const char *name, void (*callback)(const RecRecord *, void *), v
520521

521522
if (it != metrics.end()) {
522523
RecRecord r;
523-
auto &&[name, val] = *it;
524+
auto &&[name, type, val] = *it;
524525

525526
r.rec_type = RECT_PLUGIN;
526-
r.data_type = RECD_INT;
527+
r.data_type = type == ts::Metrics::MetricType::COUNTER ? RECD_COUNTER : RECD_INT;
527528
r.name = name.data();
528529
r.data.rec_int = val;
529530

@@ -567,12 +568,12 @@ RecLookupMatchingRecords(unsigned rec_type, const char *match, void (*callback)(
567568
// librecords callback with a "pseudo" record.
568569
RecRecord tmp;
569570

570-
tmp.rec_type = RECT_PROCESS;
571-
tmp.data_type = RECD_INT;
571+
tmp.rec_type = RECT_PROCESS;
572572

573-
for (auto &&[name, val] : ts::Metrics::instance()) {
573+
for (auto &&[name, type, val] : ts::Metrics::instance()) {
574574
if (regex.match(name.data()) >= 0) {
575575
tmp.name = name.data();
576+
tmp.data_type = type == ts::Metrics::MetricType::COUNTER ? RECD_COUNTER : RECD_INT;
576577
tmp.data.rec_int = val;
577578
callback(&tmp, data);
578579
}
@@ -904,9 +905,10 @@ RecDumpRecords(RecT rec_type, RecDumpEntryCb callback, void *edata)
904905
// Dump all new metrics as well (no "type" for them)
905906
RecData datum;
906907

907-
for (auto &&[name, val] : ts::Metrics::instance()) {
908+
for (auto &&[name, type, val] : ts::Metrics::instance()) {
908909
datum.rec_int = val;
909-
callback(RECT_PLUGIN, edata, true, name.data(), TS_RECORDDATATYPE_INT, &datum);
910+
callback(RECT_PLUGIN, edata, true, name.data(),
911+
type == Metrics::MetricType::COUNTER ? TS_RECORDDATATYPE_COUNTER : TS_RECORDDATATYPE_INT, &datum);
910912
}
911913
}
912914

0 commit comments

Comments
 (0)