Skip to content

Commit 662d742

Browse files
committed
MB-51413: Move StatDef to separate files
Preparation for moving to json definitions for stats. Allows StatDef to be included elsewhere. Change-Id: Icc96f8edb76387905d50a8e120a937fd3adb026f Reviewed-on: https://review.couchbase.org/c/kv_engine/+/172720 Reviewed-by: Richard de Mellow <[email protected]> Tested-by: Build Bot <[email protected]>
1 parent 83f12ac commit 662d742

File tree

5 files changed

+230
-188
lines changed

5 files changed

+230
-188
lines changed

include/statistics/definitions.h

Lines changed: 1 addition & 162 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
#pragma once
1313

14+
#include "statdef.h"
1415
#include "units.h"
1516

1617
#include <string>
@@ -19,168 +20,6 @@
1920

2021
namespace cb::stats {
2122

22-
/**
23-
* Small wrapper to track whether a key from stats.def.h needs to be formatted.
24-
*
25-
* This is used to distinguish:
26-
*
27-
* STAT(foo_bar, "foo_bar",...)
28-
* -> StatDef("foo_bar", ...)
29-
* from
30-
* STAT(foo_bar, FMT("{scope}:foo_bar"),...)
31-
* -> StatDef( CBStatsKey("{scope}:foo_bar", NeedsFormattingTag{}), ...)
32-
*/
33-
class CBStatsKey {
34-
public:
35-
// default constructor required for stats.def.h if cbstats name is not given
36-
CBStatsKey() = default;
37-
38-
CBStatsKey(std::string_view key) : key(key) {
39-
}
40-
41-
struct NeedsFormattingTag {};
42-
43-
CBStatsKey(std::string_view key, NeedsFormattingTag)
44-
: key(key), needsFormatting(true) {
45-
}
46-
47-
operator std::string_view() const {
48-
return key;
49-
}
50-
51-
bool empty() const {
52-
return key.empty();
53-
}
54-
55-
const std::string_view key;
56-
const bool needsFormatting = false;
57-
};
58-
59-
/**
60-
* Type representing the key under which a stat should be reported.
61-
*
62-
* StatCollector implementations which support labelled stats with
63-
* shared names may use the metricFamilyKey and labels, if present -
64-
* for example PrometheusStatCollector.
65-
*
66-
* Implementations which do not support labels should use the cbstatsKey.
67-
* These keys should be unique per-bucket.
68-
*
69-
* For example, "cmd_get" and "cmd_set". CBStats must report them under
70-
* unique names, but Prometheus could report them under the same metric
71-
* name (e.g., "cmd") but with a label to distinguish them.
72-
* This is not a necessity, but is a nice-to-have to make Prometheus
73-
* querying more expressive.
74-
*
75-
* This type should mainly be constructed from the definitions in
76-
* stats.def.h, but can also be created directly as a fallback until
77-
* all stats have been transitioned to stats.def.h.
78-
*/
79-
struct StatDef {
80-
using Labels = std::unordered_map<const char*, std::string_view>;
81-
/**
82-
* Construct from char* to minimize code change while migrating to
83-
* the StatCollector interface.
84-
*
85-
* Ideally stats would specify a StatKey to lookup a StatDef,
86-
* but until all stats have been added to stats.def.h, this
87-
* allows convenient construction of a basic StatDef.
88-
*
89-
* StatDefs created in this manner will _not_ be formatted. Code which
90-
* is unaware of StatCollectors may generate stat keys which are not
91-
* safe to provide to fmt::format (e.g., may happen to contain invalid
92-
* replacement specifiers).
93-
*/
94-
StatDef(const char* uniqueKey) : StatDef(std::string_view(uniqueKey)) {
95-
}
96-
97-
StatDef(std::string_view uniqueKey) : cbstatsKey(CBStatsKey(uniqueKey)) {
98-
}
99-
100-
/**
101-
* Construct a stat definition for use by CBStats and Prometheus.
102-
*
103-
* Constructs a stat specification including the information needed to
104-
* expose a stat through either CBStats or Prometheus.
105-
*
106-
* @param cbstatsKey name of stat which is unique within a bucket. Used by
107-
* CBStats.
108-
* @param unit the quantity this stat represents (bytes, seconds etc.) and
109-
* the scale prefix (kilo, micro etc.). Used by PrometheusStatCollector to
110-
* normalise stats into their base units, and suffix them correctly.
111-
* @param metricFamilyKey name which may be shared by multiple stats with
112-
* distinguishing labels. Used to group stats.
113-
* @param labels key/value pairs used by Prometheus to filter/aggregate
114-
* stats
115-
*/
116-
StatDef(CBStatsKey cbstatsKey,
117-
cb::stats::Unit unit = cb::stats::units::none,
118-
std::string_view metricFamilyKey = "",
119-
Labels&& labels = {});
120-
121-
/**
122-
* Tag struct used to explicitly identify stats which should not be exposed
123-
* to Prometheus.
124-
*/
125-
struct CBStatsOnlyTag {};
126-
127-
/**
128-
* Tag struct used to explicitly identify stats which should not be exposed
129-
* for cbstats.
130-
*/
131-
struct PrometheusOnlyTag {};
132-
133-
/**
134-
* Construct a CBStats-only stat definition.
135-
*
136-
* Constructs a stat specification including the information needed to
137-
* expose a stat only through CBStats. The stat will _not_ be exposed over
138-
* Prometheus.
139-
*
140-
* @param cbstatsKey name of stat which is unique within a bucket.
141-
*/
142-
StatDef(CBStatsKey cbstatsKey, CBStatsOnlyTag);
143-
144-
/**
145-
* Construct a Prometheus-only stat definition.
146-
*
147-
* Constructs a stat specification including the information needed to
148-
* expose a stat only for Prometheus. The stat will _not_ be exposed over
149-
* cbstats.
150-
*
151-
* @param metricFamilyKey name of stat which is unique within a bucket.
152-
*/
153-
StatDef(std::string_view metricFamilyKey,
154-
cb::stats::Unit unit,
155-
Labels&& labels,
156-
PrometheusOnlyTag);
157-
158-
bool isCBStat() const {
159-
return !cbstatsKey.empty();
160-
}
161-
162-
bool isPrometheusStat() const {
163-
return !metricFamily.empty();
164-
}
165-
166-
bool needsFormatting() const {
167-
return cbstatsKey.needsFormatting;
168-
}
169-
170-
// Key which should be unique per bucket, possibly after being formatted
171-
// with values from `labels`. Used by CBStats.
172-
const CBStatsKey cbstatsKey;
173-
// The unit this stat represents, e.g., microseconds.
174-
// Used to scale to base units and name the stat correctly for Prometheus,
175-
const cb::stats::Unit unit = cb::stats::units::none;
176-
// Metric name used by Prometheus. Used to "group"
177-
// stats in combination with distinguishing labels.
178-
std::string metricFamily;
179-
// Labels for this metric. Labels set here will
180-
// override defaults labels set in the StatCollector
181-
const Labels labels;
182-
};
183-
18423
// don't need labels for the enum
18524
#define LABEL(...)
18625
// don't need formatted cbstats keys for the enum, only the enum key is needed.

include/statistics/statdef.h

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2+
/*
3+
* Copyright 2022-Present Couchbase, Inc.
4+
*
5+
* Use of this software is governed by the Business Source License included
6+
* in the file licenses/BSL-Couchbase.txt. As of the Change Date specified
7+
* in that file, in accordance with the Business Source License, use of this
8+
* software will be governed by the Apache License, Version 2.0, included in
9+
* the file licenses/APL2.txt.
10+
*/
11+
#pragma once
12+
13+
#include <string>
14+
#include <string_view>
15+
#include <unordered_map>
16+
17+
#include "units.h"
18+
19+
namespace cb::stats {
20+
21+
/**
22+
* Small wrapper to track whether a key from stats.def.h needs to be formatted.
23+
*
24+
* This is used to distinguish:
25+
*
26+
* STAT(foo_bar, "foo_bar",...)
27+
* -> StatDef("foo_bar", ...)
28+
* from
29+
* STAT(foo_bar, FMT("{scope}:foo_bar"),...)
30+
* -> StatDef( CBStatsKey("{scope}:foo_bar", NeedsFormattingTag{}), ...)
31+
*/
32+
class CBStatsKey {
33+
public:
34+
// default constructor required for stats.def.h if cbstats name is not given
35+
CBStatsKey() = default;
36+
37+
CBStatsKey(std::string_view key) : key(key) {
38+
}
39+
40+
struct NeedsFormattingTag {};
41+
42+
CBStatsKey(std::string_view key, NeedsFormattingTag)
43+
: key(key), needsFormatting(true) {
44+
}
45+
46+
operator std::string_view() const {
47+
return key;
48+
}
49+
50+
bool empty() const {
51+
return key.empty();
52+
}
53+
54+
const std::string_view key;
55+
const bool needsFormatting = false;
56+
};
57+
58+
/**
59+
* Type representing the key under which a stat should be reported.
60+
*
61+
* StatCollector implementations which support labelled stats with
62+
* shared names may use the metricFamilyKey and labels, if present -
63+
* for example PrometheusStatCollector.
64+
*
65+
* Implementations which do not support labels should use the cbstatsKey.
66+
* These keys should be unique per-bucket.
67+
*
68+
* For example, "cmd_get" and "cmd_set". CBStats must report them under
69+
* unique names, but Prometheus could report them under the same metric
70+
* name (e.g., "cmd") but with a label to distinguish them.
71+
* This is not a necessity, but is a nice-to-have to make Prometheus
72+
* querying more expressive.
73+
*
74+
* This type should mainly be constructed from the definitions in
75+
* stats.def.h, but can also be created directly as a fallback until
76+
* all stats have been transitioned to stats.def.h.
77+
*/
78+
struct StatDef {
79+
using Labels = std::unordered_map<const char*, std::string_view>;
80+
/**
81+
* Construct from char* to minimize code change while migrating to
82+
* the StatCollector interface.
83+
*
84+
* Ideally stats would specify a StatKey to lookup a StatDef,
85+
* but until all stats have been added to stats.def.h, this
86+
* allows convenient construction of a basic StatDef.
87+
*
88+
* StatDefs created in this manner will _not_ be formatted. Code which
89+
* is unaware of StatCollectors may generate stat keys which are not
90+
* safe to provide to fmt::format (e.g., may happen to contain invalid
91+
* replacement specifiers).
92+
*/
93+
StatDef(const char* uniqueKey) : StatDef(std::string_view(uniqueKey)) {
94+
}
95+
96+
StatDef(std::string_view uniqueKey) : cbstatsKey(CBStatsKey(uniqueKey)) {
97+
}
98+
99+
/**
100+
* Construct a stat definition for use by CBStats and Prometheus.
101+
*
102+
* Constructs a stat specification including the information needed to
103+
* expose a stat through either CBStats or Prometheus.
104+
*
105+
* @param cbstatsKey name of stat which is unique within a bucket. Used by
106+
* CBStats.
107+
* @param unit the quantity this stat represents (bytes, seconds etc.) and
108+
* the scale prefix (kilo, micro etc.). Used by PrometheusStatCollector to
109+
* normalise stats into their base units, and suffix them correctly.
110+
* @param metricFamilyKey name which may be shared by multiple stats with
111+
* distinguishing labels. Used to group stats.
112+
* @param labels key/value pairs used by Prometheus to filter/aggregate
113+
* stats
114+
*/
115+
StatDef(CBStatsKey cbstatsKey,
116+
cb::stats::Unit unit = cb::stats::units::none,
117+
std::string_view metricFamilyKey = "",
118+
Labels&& labels = {});
119+
120+
/**
121+
* Tag struct used to explicitly identify stats which should not be exposed
122+
* to Prometheus.
123+
*/
124+
struct CBStatsOnlyTag {};
125+
126+
/**
127+
* Tag struct used to explicitly identify stats which should not be exposed
128+
* for cbstats.
129+
*/
130+
struct PrometheusOnlyTag {};
131+
132+
/**
133+
* Construct a CBStats-only stat definition.
134+
*
135+
* Constructs a stat specification including the information needed to
136+
* expose a stat only through CBStats. The stat will _not_ be exposed over
137+
* Prometheus.
138+
*
139+
* @param cbstatsKey name of stat which is unique within a bucket.
140+
*/
141+
StatDef(CBStatsKey cbstatsKey, CBStatsOnlyTag);
142+
143+
/**
144+
* Construct a Prometheus-only stat definition.
145+
*
146+
* Constructs a stat specification including the information needed to
147+
* expose a stat only for Prometheus. The stat will _not_ be exposed over
148+
* cbstats.
149+
*
150+
* @param metricFamilyKey name of stat which is unique within a bucket.
151+
*/
152+
StatDef(std::string_view metricFamilyKey,
153+
cb::stats::Unit unit,
154+
Labels&& labels,
155+
PrometheusOnlyTag);
156+
157+
bool isCBStat() const {
158+
return !cbstatsKey.empty();
159+
}
160+
161+
bool isPrometheusStat() const {
162+
return !metricFamily.empty();
163+
}
164+
165+
bool needsFormatting() const {
166+
return cbstatsKey.needsFormatting;
167+
}
168+
169+
// Key which should be unique per bucket, possibly after being formatted
170+
// with values from `labels`. Used by CBStats.
171+
const CBStatsKey cbstatsKey;
172+
// The unit this stat represents, e.g., microseconds.
173+
// Used to scale to base units and name the stat correctly for Prometheus,
174+
const cb::stats::Unit unit = cb::stats::units::none;
175+
// Metric name used by Prometheus. Used to "group"
176+
// stats in combination with distinguishing labels.
177+
std::string metricFamily;
178+
// Labels for this metric. Labels set here will
179+
// override defaults labels set in the StatCollector
180+
const Labels labels;
181+
};
182+
183+
} // namespace cb::stats

statistics/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ add_library(statistics STATIC
55
labelled_collector.cc
66
prometheus.cc
77
prometheus_collector.cc
8+
statdef.cc
89
)
910
kv_enable_pch(statistics)
1011
add_sanitizers(statistics)

0 commit comments

Comments
 (0)