Add basic metrics to INFO command

This commit is contained in:
Roman Gershman 2022-02-19 08:59:58 +02:00
parent e1c852dfcc
commit b82fb72fc5
9 changed files with 75 additions and 32 deletions

View File

@ -23,7 +23,7 @@ jobs:
image: ghcr.io/${{ github.actor }}/ubuntu-dev:latest image: ghcr.io/${{ github.actor }}/ubuntu-dev:latest
credentials: credentials:
username: ${{ github.actor }} username: ${{ github.actor }}
password: ${{ secrets.GHCR_TOKEN }} password: ${{ secrets.GITHUB_TOKEN }}
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
with: with:

View File

@ -634,7 +634,7 @@ int Interpreter::RedisGenericCommand(bool raise_error) {
for (int j = 0; j < argc; j++) { for (int j = 0; j < argc; j++) {
unsigned idx = j + 1; unsigned idx = j + 1;
size_t len; size_t len = 0;
if (lua_isinteger(lua_, idx)) { if (lua_isinteger(lua_, idx)) {
char* next = absl::numbers_internal::FastIntToBuffer(lua_tointeger(lua_, idx), cur); char* next = absl::numbers_internal::FastIntToBuffer(lua_tointeger(lua_, idx), cur);
len = next - cur; len = next - cur;

2
helio

@ -1 +1 @@
Subproject commit 847c612488e152e8e12df98c3c26f222d6e7ac13 Subproject commit 84c1b2ca38d077eaae347098e56f451aad2caa2b

View File

@ -23,8 +23,6 @@ using namespace std;
namespace { namespace {
DEFINE_VARZ(VarzQps, ping_qps);
class Renamer { class Renamer {
public: public:
Renamer(DbIndex dind, ShardId source_id) : db_indx_(dind), src_sid_(source_id) { Renamer(DbIndex dind, ShardId source_id) : db_indx_(dind), src_sid_(source_id) {
@ -152,11 +150,9 @@ const char* ObjTypeName(int type) {
} // namespace } // namespace
void GenericFamily::Init(util::ProactorPool* pp) { void GenericFamily::Init(util::ProactorPool* pp) {
ping_qps.Init(pp);
} }
void GenericFamily::Shutdown() { void GenericFamily::Shutdown() {
ping_qps.Shutdown();
} }
void GenericFamily::Del(CmdArgList args, ConnectionContext* cntx) { void GenericFamily::Del(CmdArgList args, ConnectionContext* cntx) {
@ -184,7 +180,6 @@ void GenericFamily::Ping(CmdArgList args, ConnectionContext* cntx) {
if (args.size() > 2) { if (args.size() > 2) {
return (*cntx)->SendError("wrong number of arguments for 'ping' command"); return (*cntx)->SendError("wrong number of arguments for 'ping' command");
} }
ping_qps.Inc();
// We synchronously block here until the engine sends us the payload and notifies that // We synchronously block here until the engine sends us the payload and notifies that
// the I/O operation has been processed. // the I/O operation has been processed.

View File

@ -43,7 +43,6 @@ namespace this_fiber = ::boost::this_fiber;
namespace { namespace {
DEFINE_VARZ(VarzMapAverage, request_latency_usec); DEFINE_VARZ(VarzMapAverage, request_latency_usec);
DEFINE_VARZ(VarzQps, ping_qps);
std::optional<VarzFunction> engine_varz; std::optional<VarzFunction> engine_varz;
metrics::CounterFamily cmd_req("requests_total", "Number of served redis requests"); metrics::CounterFamily cmd_req("requests_total", "Number of served redis requests");
@ -311,7 +310,6 @@ void Service::Init(util::AcceptServer* acceptor, const InitOpts& opts) {
}); });
request_latency_usec.Init(&pp_); request_latency_usec.Init(&pp_);
ping_qps.Init(&pp_);
StringFamily::Init(&pp_); StringFamily::Init(&pp_);
GenericFamily::Init(&pp_); GenericFamily::Init(&pp_);
cmd_req.Init(&pp_, {"type"}); cmd_req.Init(&pp_, {"type"});
@ -327,7 +325,6 @@ void Service::Shutdown() {
engine_varz.reset(); engine_varz.reset();
request_latency_usec.Shutdown(); request_latency_usec.Shutdown();
ping_qps.Shutdown();
pp_.AwaitFiberOnAll([](ProactorBase* pb) { ServerState::tlocal()->Shutdown(); }); pp_.AwaitFiberOnAll([](ProactorBase* pb) { ServerState::tlocal()->Shutdown(); });
@ -352,7 +349,8 @@ void Service::DispatchCommand(CmdArgList args, ConnectionContext* cntx) {
bool is_trans_cmd = (cmd_str == "EXEC" || cmd_str == "MULTI"); bool is_trans_cmd = (cmd_str == "EXEC" || cmd_str == "MULTI");
const CommandId* cid = registry_.Find(cmd_str); const CommandId* cid = registry_.Find(cmd_str);
ServerState& etl = *ServerState::tlocal(); ServerState& etl = *ServerState::tlocal();
++etl.connection_stats.command_cnt;
etl.RecordCmd();
absl::Cleanup multi_error = [cntx] { absl::Cleanup multi_error = [cntx] {
if (cntx->conn_state.exec_state != ConnectionState::EXEC_INACTIVE) { if (cntx->conn_state.exec_state != ConnectionState::EXEC_INACTIVE) {

View File

@ -86,10 +86,10 @@ class Service {
util::ProactorPool& pp_; util::ProactorPool& pp_;
CommandRegistry registry_;
EngineShardSet shard_set_; EngineShardSet shard_set_;
ServerFamily server_family_; ServerFamily server_family_;
CommandRegistry registry_;
util::HttpListenerBase* http_listener_ = nullptr; util::HttpListenerBase* http_listener_ = nullptr;
}; };

View File

@ -7,6 +7,7 @@
#include <absl/cleanup/cleanup.h> #include <absl/cleanup/cleanup.h>
#include <absl/random/random.h> // for master_id_ generation. #include <absl/random/random.h> // for master_id_ generation.
#include <absl/strings/match.h> #include <absl/strings/match.h>
#include <malloc.h>
#include <filesystem> #include <filesystem>
@ -15,6 +16,7 @@ extern "C" {
} }
#include "base/logging.h" #include "base/logging.h"
#include "io/proc_reader.h"
#include "server/command_registry.h" #include "server/command_registry.h"
#include "server/conn_context.h" #include "server/conn_context.h"
#include "server/debugcmd.h" #include "server/debugcmd.h"
@ -23,8 +25,8 @@ extern "C" {
#include "server/main_service.h" #include "server/main_service.h"
#include "server/rdb_save.h" #include "server/rdb_save.h"
#include "server/replica.h" #include "server/replica.h"
#include "server/server_state.h"
#include "server/script_mgr.h" #include "server/script_mgr.h"
#include "server/server_state.h"
#include "server/transaction.h" #include "server/transaction.h"
#include "strings/human_readable.h" #include "strings/human_readable.h"
#include "util/accept_server.h" #include "util/accept_server.h"
@ -40,8 +42,8 @@ namespace dfly {
using namespace std; using namespace std;
using namespace util; using namespace util;
namespace fibers = ::boost::fibers; namespace fibers = ::boost::fibers;
namespace fs = std::filesystem; namespace fs = std::filesystem;
using strings::HumanReadableNumBytes;
namespace { namespace {
@ -69,7 +71,8 @@ error_code CreateDirs(fs::path dir_path) {
ServerFamily::ServerFamily(Service* engine) ServerFamily::ServerFamily(Service* engine)
: engine_(*engine), pp_(engine->proactor_pool()), ess_(engine->shard_set()) { : engine_(*engine), pp_(engine->proactor_pool()), ess_(engine->shard_set()) {
last_save_.store(time(NULL), memory_order_release); start_time_ = time(NULL);
last_save_.store(start_time_, memory_order_release);
script_mgr_.reset(new ScriptMgr(&engine->shard_set())); script_mgr_.reset(new ScriptMgr(&engine->shard_set()));
} }
@ -230,16 +233,24 @@ Metrics ServerFamily::GetMetrics() const {
fibers::mutex mu; fibers::mutex mu;
auto cb = [&](EngineShard* shard) { auto cb = [&](ProactorBase* pb) {
auto local_stats = shard->db_slice().GetStats(); EngineShard* shard = EngineShard::tlocal();
ServerState* ss = ServerState::tlocal();
lock_guard<fibers::mutex> lk(mu); lock_guard<fibers::mutex> lk(mu);
result.db += local_stats.db; result.conn_stats += ss->connection_stats;
result.events += local_stats.events; result.qps += uint64_t(ss->MovingSum6());
result.conn_stats += *ServerState::tl_connection_stats();
if (shard) {
auto shard_stats = shard->db_slice().GetStats();
result.db += shard_stats.db;
result.events += shard_stats.events;
}
}; };
ess_.RunBlockingInParallel(std::move(cb)); pp_.AwaitFiberOnAll(std::move(cb));
result.qps /= 6;
return result; return result;
} }
@ -251,29 +262,53 @@ redis_version:1.9.9
redis_mode:standalone redis_mode:standalone
arch_bits:64 arch_bits:64
multiplexing_api:iouring multiplexing_api:iouring
atomicvar_api:atomic-builtin
tcp_port:)"; tcp_port:)";
string info = absl::StrCat(kInfo1, FLAGS_port, "\n"); string info = absl::StrCat(kInfo1, FLAGS_port, "\n");
size_t uptime = time(NULL) - start_time_;
absl::StrAppend(&info, "uptime_in_seconds:", uptime, "\n");
absl::StrAppend(&info, "uptime_in_days:", uptime / (3600 * 24), "\n");
auto sdata_res = io::ReadStatusInfo();
Metrics m = GetMetrics(); Metrics m = GetMetrics();
// Clients
absl::StrAppend(&info, "\n# Clients\n");
absl::StrAppend(&info, "connected_clients:", m.conn_stats.num_conns, "\n");
absl::StrAppend(&info, "client_read_buf_capacity:", m.conn_stats.read_buf_capacity, "\n");
absl::StrAppend(&info, "blocked_clients:", 0, "\n");
size_t db_size = m.db.table_mem_usage + m.db.obj_memory_usage;
absl::StrAppend(&info, "\n# Memory\n"); absl::StrAppend(&info, "\n# Memory\n");
// TODO: should be extracted from mimalloc heaps instead of using table stats.
absl::StrAppend(&info, "used_memory:", db_size, "\n");
absl::StrAppend(&info, "used_memory_human:", HumanReadableNumBytes(db_size), "\n");
if (sdata_res.has_value()) {
absl::StrAppend(&info, "used_memory_rss:", sdata_res->vm_rss, "\n");
absl::StrAppend(&info, "used_memory_rss_human:", HumanReadableNumBytes(sdata_res->vm_rss),
"\n");
} else {
LOG(ERROR) << "Error fetching /proc/self/status stats";
}
// TBD: should be the max of all seen used_memory values.
absl::StrAppend(&info, "used_memory_peak:", -1, "\n");
absl::StrAppend(&info, "object_used_memory:", m.db.obj_memory_usage, "\n"); absl::StrAppend(&info, "object_used_memory:", m.db.obj_memory_usage, "\n");
absl::StrAppend(&info, "table_used_memory:", m.db.table_mem_usage, "\n"); absl::StrAppend(&info, "table_used_memory:", m.db.table_mem_usage, "\n");
absl::StrAppend(&info, "used_memory_human:",
strings::HumanReadableNumBytes(m.db.table_mem_usage + m.db.obj_memory_usage),
"\n");
absl::StrAppend(&info, "num_entries:", m.db.key_count, "\n"); absl::StrAppend(&info, "num_entries:", m.db.key_count, "\n");
absl::StrAppend(&info, "inline_keys:", m.db.inline_keys, "\n"); absl::StrAppend(&info, "inline_keys:", m.db.inline_keys, "\n");
// Stats
absl::StrAppend(&info, "\n# Stats\n"); absl::StrAppend(&info, "\n# Stats\n");
absl::StrAppend(&info, "instantaneous_ops_per_sec:", m.qps, "\n");
absl::StrAppend(&info, "total_commands_processed:", m.conn_stats.command_cnt, "\n"); absl::StrAppend(&info, "total_commands_processed:", m.conn_stats.command_cnt, "\n");
absl::StrAppend(&info, "total_pipelined_commands:", m.conn_stats.pipelined_cmd_cnt, "\n"); absl::StrAppend(&info, "total_pipelined_commands:", m.conn_stats.pipelined_cmd_cnt, "\n");
absl::StrAppend(&info, "total_reads_processed:", m.conn_stats.io_reads_cnt, "\n"); absl::StrAppend(&info, "total_reads_processed:", m.conn_stats.io_reads_cnt, "\n");
absl::StrAppend(&info, "\n# Clients\n");
absl::StrAppend(&info, "connected_clients:", m.conn_stats.num_conns, "\n");
absl::StrAppend(&info, "client_read_buf_capacity:", m.conn_stats.read_buf_capacity, "\n");
absl::StrAppend(&info, "\n# Replication\n"); absl::StrAppend(&info, "\n# Replication\n");
ServerState& etl = *ServerState::tlocal(); ServerState& etl = *ServerState::tlocal();
@ -412,8 +447,7 @@ void ServerFamily::Register(CommandRegistry* registry) {
<< CI{"REPLICAOF", kReplicaOpts, 3, 0, 0, 0}.HFUNC(ReplicaOf) << CI{"REPLICAOF", kReplicaOpts, 3, 0, 0, 0}.HFUNC(ReplicaOf)
<< CI{"SYNC", CO::ADMIN | CO::GLOBAL_TRANS, 1, 0, 0, 0}.HFUNC(Sync) << CI{"SYNC", CO::ADMIN | CO::GLOBAL_TRANS, 1, 0, 0, 0}.HFUNC(Sync)
<< CI{"PSYNC", CO::ADMIN | CO::GLOBAL_TRANS, 3, 0, 0, 0}.HFUNC(Psync) << CI{"PSYNC", CO::ADMIN | CO::GLOBAL_TRANS, 3, 0, 0, 0}.HFUNC(Psync)
<< CI{"SCRIPT", CO::NOSCRIPT, -2, 0, 0, 0}.HFUNC(Script) << CI{"SCRIPT", CO::NOSCRIPT, -2, 0, 0, 0}.HFUNC(Script);
;
} }
} // namespace dfly } // namespace dfly

View File

@ -24,6 +24,8 @@ struct Metrics {
DbStats db; DbStats db;
SliceEvents events; SliceEvents events;
size_t qps = 0;
ConnectionStats conn_stats; ConnectionStats conn_stats;
}; };
@ -79,6 +81,7 @@ class ServerFamily {
std::atomic<int64_t> last_save_; // in seconds. std::atomic<int64_t> last_save_; // in seconds.
GlobalState global_state_; GlobalState global_state_;
time_t start_time_ = 0; // in seconds, epoch time.
}; };
} // namespace dfly } // namespace dfly

View File

@ -10,6 +10,7 @@
#include "core/interpreter.h" #include "core/interpreter.h"
#include "server/common_types.h" #include "server/common_types.h"
#include "server/global_state.h" #include "server/global_state.h"
#include "util/sliding_counter.h"
namespace dfly { namespace dfly {
@ -62,11 +63,23 @@ class ServerState { // public struct - to allow initialization.
Interpreter& GetInterpreter(); Interpreter& GetInterpreter();
// Returns sum of all requests in the last 6 seconds
// (not including the current one).
uint32_t MovingSum6() const { return qps_.SumTail(); }
void RecordCmd() {
++connection_stats.command_cnt;
qps_.Inc();
}
private: private:
int64_t live_transactions_ = 0; int64_t live_transactions_ = 0;
std::optional<Interpreter> interpreter_; std::optional<Interpreter> interpreter_;
GlobalState::S gstate_ = GlobalState::IDLE; GlobalState::S gstate_ = GlobalState::IDLE;
using Counter = util::SlidingCounter<7>;
Counter qps_;
static thread_local ServerState state_; static thread_local ServerState state_;
}; };