diff --git a/include/pika_define.h b/include/pika_define.h index 17a628df5c..a30c31632b 100644 --- a/include/pika_define.h +++ b/include/pika_define.h @@ -289,6 +289,8 @@ struct SlowlogEntry { int64_t start_time; int64_t duration; net::RedisCmdArgsType argv; + int64_t element_count; // 复杂数据类型的元素个数,-1表示不适用 + SlowlogEntry() : id(0), start_time(0), duration(0), element_count(-1) {} }; #define PIKA_MIN_RESERVED_FDS 5000 diff --git a/include/pika_server.h b/include/pika_server.h index df75229188..054b2f1894 100644 --- a/include/pika_server.h +++ b/include/pika_server.h @@ -240,7 +240,7 @@ class PikaServer : public pstd::noncopyable { void SlowlogTrim(); void SlowlogReset(); void SlowlogObtain(int64_t number, std::vector* slowlogs); - void SlowlogPushEntry(const std::vector& argv, int64_t time, int64_t duration); + void SlowlogPushEntry(const std::vector& argv, int64_t time, int64_t duration, int64_t element_count = -1); uint32_t SlowlogLen(); uint64_t SlowlogCount(); diff --git a/src/pika_admin.cc b/src/pika_admin.cc index 9bb40d6d0f..98196c0674 100644 --- a/src/pika_admin.cc +++ b/src/pika_admin.cc @@ -3336,7 +3336,12 @@ void SlowlogCmd::Do() { g_pika_server->SlowlogObtain(number_, &slowlogs); res_.AppendArrayLenUint64(slowlogs.size()); for (const auto& slowlog : slowlogs) { - res_.AppendArrayLen(4); + // 如果有元素个数信息,返回5个字段,否则返回4个字段 + if (slowlog.element_count >= 0) { + res_.AppendArrayLen(5); + } else { + res_.AppendArrayLen(4); + } res_.AppendInteger(slowlog.id); res_.AppendInteger(slowlog.start_time); res_.AppendInteger(slowlog.duration); @@ -3344,6 +3349,10 @@ void SlowlogCmd::Do() { for (const auto& arg : slowlog.argv) { res_.AppendString(arg); } + // 如果有元素个数信息,追加第5个字段 + if (slowlog.element_count >= 0) { + res_.AppendInteger(slowlog.element_count); + } } } } diff --git a/src/pika_client_conn.cc b/src/pika_client_conn.cc index 1919520c8c..2ba355cf51 100644 --- a/src/pika_client_conn.cc +++ b/src/pika_client_conn.cc @@ -232,7 +232,65 @@ std::shared_ptr PikaClientConn::DoCmd(const PikaCmdArgsType& argv, const st void PikaClientConn::ProcessSlowlog(const PikaCmdArgsType& argv, std::shared_ptr c_ptr) { if (time_stat_->total_time() > g_pika_conf->slowlog_slower_than()) { - g_pika_server->SlowlogPushEntry(argv, time_stat_->start_ts() / 1000000, time_stat_->total_time()); + // 获取复杂数据类型的元素个数 + int64_t element_count = -1; + std::string cmd_name = argv.empty() ? "" : argv[0]; + pstd::StringToLower(cmd_name); + + // 对于Hash和Set等复杂数据类型,获取元素个数 + if (!argv.empty() && argv.size() >= 2) { + std::string key = argv[1]; + std::shared_ptr db = c_ptr->GetDB(); + + if (db) { + // Hash命令 + if (cmd_name == "hset" || cmd_name == "hget" || cmd_name == "hdel" || + cmd_name == "hexists" || cmd_name == "hgetall" || cmd_name == "hkeys" || + cmd_name == "hvals" || cmd_name == "hlen" || cmd_name == "hmget" || + cmd_name == "hmset" || cmd_name == "hsetnx" || cmd_name == "hincrby" || + cmd_name == "hincrbyfloat" || cmd_name == "hstrlen" || cmd_name == "hscan") { + int32_t len = 0; + rocksdb::Status s = db->storage()->HLen(key, &len); + if (s.ok()) { + element_count = len; + } + } + // Set命令 + else if (cmd_name == "sadd" || cmd_name == "srem" || cmd_name == "spop" || + cmd_name == "scard" || cmd_name == "smembers" || cmd_name == "sismember" || + cmd_name == "srandmember" || cmd_name == "sscan") { + int32_t len = 0; + rocksdb::Status s = db->storage()->SCard(key, &len); + if (s.ok()) { + element_count = len; + } + } + // List命令 + else if (cmd_name == "lpush" || cmd_name == "rpush" || cmd_name == "lpop" || + cmd_name == "rpop" || cmd_name == "llen" || cmd_name == "lrange" || + cmd_name == "lindex" || cmd_name == "lset" || cmd_name == "lrem" || + cmd_name == "ltrim" || cmd_name == "linsert") { + uint64_t len = 0; + rocksdb::Status s = db->storage()->LLen(key, &len); + if (s.ok()) { + element_count = static_cast(len); + } + } + // ZSet命令 + else if (cmd_name == "zadd" || cmd_name == "zrem" || cmd_name == "zcard" || + cmd_name == "zcount" || cmd_name == "zincrby" || cmd_name == "zrange" || + cmd_name == "zrangebyscore" || cmd_name == "zrank" || cmd_name == "zrevrank" || + cmd_name == "zrevrange" || cmd_name == "zscore" || cmd_name == "zscan") { + int32_t len = 0; + rocksdb::Status s = db->storage()->ZCard(key, &len); + if (s.ok()) { + element_count = len; + } + } + } + } + + g_pika_server->SlowlogPushEntry(argv, time_stat_->start_ts() / 1000000, time_stat_->total_time(), element_count); if (g_pika_conf->slowlog_write_errorlog()) { bool trim = false; std::string slow_log; @@ -249,8 +307,15 @@ void PikaClientConn::ProcessSlowlog(const PikaCmdArgsType& argv, std::shared_ptr } } } + + std::string element_info; + if (element_count >= 0) { + element_info = ", element_count: " + std::to_string(element_count); + } + LOG(ERROR) << "ip_port: " << ip_port() << ", db: " << current_db_ << ", command:" << slow_log << ", command_size: " << cmd_size - 1 << ", arguments: " << argv.size() + << element_info << ", total_time(ms): " << time_stat_->total_time() / 1000 << ", before_queue_time(ms): " << time_stat_->before_queue_time() / 1000 << ", queue_time(ms): " << time_stat_->queue_time() / 1000 diff --git a/src/pika_server.cc b/src/pika_server.cc index b205f3e34b..230510ae3d 100644 --- a/src/pika_server.cc +++ b/src/pika_server.cc @@ -951,7 +951,7 @@ void PikaServer::SlowlogObtain(int64_t number, std::vector* slowlo } } -void PikaServer::SlowlogPushEntry(const PikaCmdArgsType& argv, int64_t time, int64_t duration) { +void PikaServer::SlowlogPushEntry(const PikaCmdArgsType& argv, int64_t time, int64_t duration, int64_t element_count) { SlowlogEntry entry; uint32_t slargc = (argv.size() < SLOWLOG_ENTRY_MAX_ARGC) ? argv.size() : SLOWLOG_ENTRY_MAX_ARGC; @@ -978,6 +978,7 @@ void PikaServer::SlowlogPushEntry(const PikaCmdArgsType& argv, int64_t time, int entry.id = static_cast(slowlog_entry_id_++); entry.start_time = time; entry.duration = duration; + entry.element_count = element_count; slowlog_list_.push_front(entry); slowlog_counter_++; }