mirror of
https://github.com/dragonflydb/dragonfly.git
synced 2025-05-11 18:35:46 +02:00
feat: add keyspace_mutations metric (#2329)
* feat: add keyspace_mutations metric Currently we expose hits/misses for read only commands only (compatible with redis). `keyyspace_mutations` complement this providing number of key operations for write commands. It's interesting because now we can learn the number of key_ops vs API ops, where key_ops = misses + hits + mutations Signed-off-by: Roman Gershman <roman@dragonflydb.io> * chore: address fixes Signed-off-by: Roman Gershman <roman@dragonflydb.io> --------- Signed-off-by: Roman Gershman <roman@dragonflydb.io>
This commit is contained in:
parent
4562fad737
commit
f90317a795
4 changed files with 39 additions and 17 deletions
|
@ -263,7 +263,7 @@ DbStats& DbStats::operator+=(const DbStats& o) {
|
|||
}
|
||||
|
||||
SliceEvents& SliceEvents::operator+=(const SliceEvents& o) {
|
||||
static_assert(sizeof(SliceEvents) == 88, "You should update this function with new fields");
|
||||
static_assert(sizeof(SliceEvents) == 96, "You should update this function with new fields");
|
||||
|
||||
ADD(evicted_keys);
|
||||
ADD(hard_evictions);
|
||||
|
@ -274,6 +274,7 @@ SliceEvents& SliceEvents::operator+=(const SliceEvents& o) {
|
|||
ADD(garbage_checked);
|
||||
ADD(hits);
|
||||
ADD(misses);
|
||||
ADD(mutations);
|
||||
ADD(insertion_rejections);
|
||||
ADD(update);
|
||||
|
||||
|
@ -399,7 +400,7 @@ DbSlice::AddOrFindResult& DbSlice::AddOrFindResult::operator=(ItAndUpdater&& o)
|
|||
}
|
||||
|
||||
DbSlice::ItAndUpdater DbSlice::FindMutable(const Context& cntx, string_view key) {
|
||||
auto [it, exp_it] = FindInternal(cntx, key, FindInternalMode::kDontUpdateCacheStats);
|
||||
auto [it, exp_it] = FindInternal(cntx, key, FindInternalMode::kUpdateMutableStats);
|
||||
|
||||
if (IsValid(it)) {
|
||||
PreUpdate(cntx.db_index, it);
|
||||
|
@ -413,7 +414,7 @@ DbSlice::ItAndUpdater DbSlice::FindMutable(const Context& cntx, string_view key)
|
|||
OpResult<DbSlice::ItAndUpdater> DbSlice::FindMutable(const Context& cntx, string_view key,
|
||||
unsigned req_obj_type) {
|
||||
// Don't use FindMutable() so that we don't call PreUpdate()
|
||||
auto [it, exp_it] = FindInternal(cntx, key, FindInternalMode::kDontUpdateCacheStats);
|
||||
auto [it, exp_it] = FindInternal(cntx, key, FindInternalMode::kUpdateMutableStats);
|
||||
|
||||
if (!IsValid(it))
|
||||
return OpStatus::KEY_NOTFOUND;
|
||||
|
@ -428,7 +429,7 @@ OpResult<DbSlice::ItAndUpdater> DbSlice::FindMutable(const Context& cntx, string
|
|||
}
|
||||
|
||||
DbSlice::ItAndExpConst DbSlice::FindReadOnly(const Context& cntx, std::string_view key) {
|
||||
auto res = FindInternal(cntx, key, FindInternalMode::kUpdateCacheStats);
|
||||
auto res = FindInternal(cntx, key, FindInternalMode::kUpdateReadStats);
|
||||
return {res.it, res.exp_it};
|
||||
}
|
||||
|
||||
|
@ -457,8 +458,14 @@ DbSlice::ItAndExp DbSlice::FindInternal(const Context& cntx, std::string_view ke
|
|||
res.it = db.prime.Find(key);
|
||||
FiberAtomicGuard fg;
|
||||
if (!IsValid(res.it)) {
|
||||
if (mode == FindInternalMode::kUpdateCacheStats)
|
||||
events_.misses++;
|
||||
switch (mode) {
|
||||
case FindInternalMode::kUpdateMutableStats:
|
||||
events_.mutations++;
|
||||
break;
|
||||
case FindInternalMode::kUpdateReadStats:
|
||||
events_.misses++;
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -483,14 +490,17 @@ DbSlice::ItAndExp DbSlice::FindInternal(const Context& cntx, std::string_view ke
|
|||
|
||||
db.top_keys.Touch(key);
|
||||
|
||||
if (mode == FindInternalMode::kUpdateCacheStats) {
|
||||
events_.hits++;
|
||||
|
||||
if (ClusterConfig::IsEnabled()) {
|
||||
db.slots_stats[ClusterConfig::KeySlot(key)].total_reads += 1;
|
||||
}
|
||||
switch (mode) {
|
||||
case FindInternalMode::kUpdateMutableStats:
|
||||
events_.mutations++;
|
||||
break;
|
||||
case FindInternalMode::kUpdateReadStats:
|
||||
events_.hits++;
|
||||
if (ClusterConfig::IsEnabled()) {
|
||||
db.slots_stats[ClusterConfig::KeySlot(key)].total_reads++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -517,7 +527,7 @@ DbSlice::AddOrFindResult DbSlice::AddOrFind(const Context& cntx, string_view key
|
|||
|
||||
DbTable& db = *db_arr_[cntx.db_index];
|
||||
|
||||
auto res = FindInternal(cntx, key, FindInternalMode::kDontUpdateCacheStats);
|
||||
auto res = FindInternal(cntx, key, FindInternalMode::kUpdateMutableStats);
|
||||
|
||||
if (IsValid(res.it)) {
|
||||
PreUpdate(cntx.db_index, res.it);
|
||||
|
|
|
@ -48,6 +48,7 @@ struct SliceEvents {
|
|||
// hits/misses on keys
|
||||
size_t hits = 0;
|
||||
size_t misses = 0;
|
||||
size_t mutations = 0;
|
||||
|
||||
// how many insertions were rejected due to OOM.
|
||||
size_t insertion_rejections = 0;
|
||||
|
@ -422,8 +423,8 @@ class DbSlice {
|
|||
size_t EvictObjects(size_t memory_to_free, PrimeIterator it, DbTable* table);
|
||||
|
||||
enum class FindInternalMode {
|
||||
kUpdateCacheStats,
|
||||
kDontUpdateCacheStats,
|
||||
kUpdateReadStats,
|
||||
kUpdateMutableStats,
|
||||
};
|
||||
ItAndExp FindInternal(const Context& cntx, std::string_view key, FindInternalMode mode);
|
||||
|
||||
|
|
|
@ -817,6 +817,8 @@ void PrintPrometheusMetrics(const Metrics& m, StringResponse* resp) {
|
|||
&resp->body());
|
||||
AppendMetricWithoutLabels("keyspace_misses_total", "", m.events.misses, MetricType::COUNTER,
|
||||
&resp->body());
|
||||
AppendMetricWithoutLabels("keyspace_mutations_total", "", m.events.mutations, MetricType::COUNTER,
|
||||
&resp->body());
|
||||
|
||||
// Net metrics
|
||||
AppendMetricWithoutLabels("net_input_bytes_total", "", conn_stats.io_read_bytes,
|
||||
|
@ -1666,6 +1668,7 @@ void ServerFamily::Info(CmdArgList args, ConnectionContext* cntx) {
|
|||
append("delete_ttl_sec", m.delete_ttl_per_sec);
|
||||
append("keyspace_hits", m.events.hits);
|
||||
append("keyspace_misses", m.events.misses);
|
||||
append("keyspace_mutations", m.events.mutations);
|
||||
append("total_reads_processed", m.conn_stats.io_read_cnt);
|
||||
append("total_writes_processed", m.conn_stats.io_write_cnt);
|
||||
append("defrag_attempt_total", m.shard_stats.defrag_attempt_total);
|
||||
|
|
|
@ -46,10 +46,14 @@ TEST_F(StringFamilyTest, SetGet) {
|
|||
EXPECT_EQ(Run({"get", "key1"}), "1");
|
||||
EXPECT_EQ(Run({"set", "key", "2"}), "OK");
|
||||
EXPECT_EQ(Run({"get", "key"}), "2");
|
||||
EXPECT_THAT(Run({"get", "key3"}), ArgType(RespExpr::NIL));
|
||||
|
||||
auto metrics = GetMetrics();
|
||||
auto tc = metrics.coordinator_stats.tx_type_cnt;
|
||||
EXPECT_EQ(6, tc[ServerState::QUICK] + tc[ServerState::INLINE]);
|
||||
EXPECT_EQ(7, tc[ServerState::QUICK] + tc[ServerState::INLINE]);
|
||||
EXPECT_EQ(3, metrics.events.hits);
|
||||
EXPECT_EQ(1, metrics.events.misses);
|
||||
EXPECT_EQ(3, metrics.events.mutations);
|
||||
}
|
||||
|
||||
TEST_F(StringFamilyTest, Incr) {
|
||||
|
@ -67,6 +71,10 @@ TEST_F(StringFamilyTest, Incr) {
|
|||
|
||||
ASSERT_THAT(Run({"incrby", "ne", "0"}), IntArg(0));
|
||||
ASSERT_THAT(Run({"decrby", "a", "-9223372036854775808"}), ErrArg("overflow"));
|
||||
auto metrics = GetMetrics();
|
||||
EXPECT_EQ(10, metrics.events.mutations);
|
||||
EXPECT_EQ(0, metrics.events.misses);
|
||||
EXPECT_EQ(0, metrics.events.hits);
|
||||
}
|
||||
|
||||
TEST_F(StringFamilyTest, Append) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue