mirror of
https://github.com/dragonflydb/dragonfly.git
synced 2025-05-10 18:05:44 +02:00
chore: expose the multi length in slowlog (#2339)
1. Fix AnalyzeTxQueue to stop crashing for various transaction types. 2. Pass exec command length to slowlog Signed-off-by: Roman Gershman <roman@dragonflydb.io>
This commit is contained in:
parent
5d67c95797
commit
5035d4e1e3
4 changed files with 34 additions and 11 deletions
|
@ -174,6 +174,9 @@ class ConnectionContext : public facade::ConnectionContext {
|
||||||
uint32_t shards_count = 0;
|
uint32_t shards_count = 0;
|
||||||
TxClock clock = 0;
|
TxClock clock = 0;
|
||||||
bool is_ooo = false;
|
bool is_ooo = false;
|
||||||
|
|
||||||
|
// number of commands in the last exec body.
|
||||||
|
unsigned exec_body_len = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
DebugInfo last_command_debug;
|
DebugInfo last_command_debug;
|
||||||
|
|
|
@ -735,17 +735,20 @@ auto EngineShard::AnalyzeTxQueue() -> TxQueueInfo {
|
||||||
if (trx->IsGlobal() || (trx->IsMulti() && trx->GetMultiMode() == Transaction::GLOBAL)) {
|
if (trx->IsGlobal() || (trx->IsMulti() && trx->GetMultiMode() == Transaction::GLOBAL)) {
|
||||||
info.tx_global++;
|
info.tx_global++;
|
||||||
} else {
|
} else {
|
||||||
KeyLockArgs lock_args = trx->GetLockArgs(sid);
|
|
||||||
DbTable* table = db_slice().GetDBTable(trx->GetDbIndex());
|
DbTable* table = db_slice().GetDBTable(trx->GetDbIndex());
|
||||||
bool can_run = true;
|
bool can_run = true;
|
||||||
for (size_t i = 0; i < lock_args.args.size(); i += lock_args.key_step) {
|
|
||||||
string_view s = KeyLockArgs::GetLockKey(lock_args.args[i]);
|
if (!trx->IsMulti()) {
|
||||||
auto it = table->trans_locks.find(s);
|
KeyLockArgs lock_args = trx->GetLockArgs(sid);
|
||||||
DCHECK(it != table->trans_locks.end());
|
for (size_t i = 0; i < lock_args.args.size(); i += lock_args.key_step) {
|
||||||
if (it != table->trans_locks.end()) {
|
string_view s = KeyLockArgs::GetLockKey(lock_args.args[i]);
|
||||||
if (it->second.IsContended()) {
|
auto it = table->trans_locks.find(s);
|
||||||
can_run = false;
|
DCHECK(it != table->trans_locks.end());
|
||||||
break;
|
if (it != table->trans_locks.end()) {
|
||||||
|
if (it->second.IsContended()) {
|
||||||
|
can_run = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -760,6 +763,9 @@ auto EngineShard::AnalyzeTxQueue() -> TxQueueInfo {
|
||||||
// Analyze locks
|
// Analyze locks
|
||||||
for (unsigned i = 0; i <= max_db_id; ++i) {
|
for (unsigned i = 0; i <= max_db_id; ++i) {
|
||||||
DbTable* table = db_slice().GetDBTable(i);
|
DbTable* table = db_slice().GetDBTable(i);
|
||||||
|
if (table == nullptr)
|
||||||
|
continue;
|
||||||
|
|
||||||
info.total_locks += table->trans_locks.size();
|
info.total_locks += table->trans_locks.size();
|
||||||
for (const auto& k_v : table->trans_locks) {
|
for (const auto& k_v : table->trans_locks) {
|
||||||
if (k_v.second.IsContended()) {
|
if (k_v.second.IsContended()) {
|
||||||
|
|
|
@ -1250,6 +1250,15 @@ bool Service::InvokeCmd(const CommandId* cid, CmdArgList tail_args, ConnectionCo
|
||||||
const auto* conn = cntx->conn();
|
const auto* conn = cntx->conn();
|
||||||
if (!(cid->opt_mask() & CO::BLOCKING) && conn != nullptr && etl.GetSlowLog().IsEnabled() &&
|
if (!(cid->opt_mask() & CO::BLOCKING) && conn != nullptr && etl.GetSlowLog().IsEnabled() &&
|
||||||
invoke_time_usec > etl.log_slower_than_usec) {
|
invoke_time_usec > etl.log_slower_than_usec) {
|
||||||
|
vector<string> aux_params;
|
||||||
|
CmdArgVec aux_slices;
|
||||||
|
|
||||||
|
if (tail_args.empty() && cid->name() == "EXEC") {
|
||||||
|
// abuse tail_args to pass more information about the slow EXEC.
|
||||||
|
aux_params.emplace_back(StrCat("CMDCOUNT/", cntx->last_command_debug.exec_body_len));
|
||||||
|
aux_slices.emplace_back(aux_params.back());
|
||||||
|
tail_args = absl::MakeSpan(aux_slices);
|
||||||
|
}
|
||||||
etl.GetSlowLog().Add(cid->name(), tail_args, conn->GetName(), conn->RemoteEndpointStr(),
|
etl.GetSlowLog().Add(cid->name(), tail_args, conn->GetName(), conn->RemoteEndpointStr(),
|
||||||
invoke_time_usec, absl::GetCurrentTimeNanos() / 1000);
|
invoke_time_usec, absl::GetCurrentTimeNanos() / 1000);
|
||||||
}
|
}
|
||||||
|
@ -2043,6 +2052,7 @@ void Service::Exec(CmdArgList args, ConnectionContext* cntx) {
|
||||||
return rb->SendNull();
|
return rb->SendNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cntx->last_command_debug.exec_body_len = exec_info.body.size();
|
||||||
const CommandId* const exec_cid = cntx->cid;
|
const CommandId* const exec_cid = cntx->cid;
|
||||||
CmdArgVec arg_vec;
|
CmdArgVec arg_vec;
|
||||||
ExecEvalState state = DetermineEvalPresense(exec_info.body);
|
ExecEvalState state = DetermineEvalPresense(exec_info.body);
|
||||||
|
|
|
@ -166,7 +166,6 @@ void Transaction::InitMultiData(KeyIndex key_index) {
|
||||||
IntentLock::Mode mode = Mode();
|
IntentLock::Mode mode = Mode();
|
||||||
|
|
||||||
auto& tmp_uniques = tmp_space.uniq_keys;
|
auto& tmp_uniques = tmp_space.uniq_keys;
|
||||||
tmp_uniques.clear();
|
|
||||||
|
|
||||||
auto lock_key = [this, mode, &tmp_uniques](string_view key) {
|
auto lock_key = [this, mode, &tmp_uniques](string_view key) {
|
||||||
if (auto [_, inserted] = tmp_uniques.insert(KeyLockArgs::GetLockKey(key)); !inserted)
|
if (auto [_, inserted] = tmp_uniques.insert(KeyLockArgs::GetLockKey(key)); !inserted)
|
||||||
|
@ -178,13 +177,16 @@ void Transaction::InitMultiData(KeyIndex key_index) {
|
||||||
// With EVAL, we call this function for EVAL itself as well as for each command
|
// With EVAL, we call this function for EVAL itself as well as for each command
|
||||||
// for eval. currently, we lock everything only during the eval call.
|
// for eval. currently, we lock everything only during the eval call.
|
||||||
if (!multi_->locks_recorded) {
|
if (!multi_->locks_recorded) {
|
||||||
|
tmp_uniques.clear();
|
||||||
|
|
||||||
for (size_t i = key_index.start; i < key_index.end; i += key_index.step)
|
for (size_t i = key_index.start; i < key_index.end; i += key_index.step)
|
||||||
lock_key(ArgS(full_args_, i));
|
lock_key(ArgS(full_args_, i));
|
||||||
if (key_index.bonus)
|
if (key_index.bonus)
|
||||||
lock_key(ArgS(full_args_, *key_index.bonus));
|
lock_key(ArgS(full_args_, *key_index.bonus));
|
||||||
|
|
||||||
|
multi_->locks_recorded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
multi_->locks_recorded = true;
|
|
||||||
DCHECK(IsAtomicMulti());
|
DCHECK(IsAtomicMulti());
|
||||||
DCHECK(multi_->mode == GLOBAL || !multi_->lock_counts.empty());
|
DCHECK(multi_->mode == GLOBAL || !multi_->lock_counts.empty());
|
||||||
}
|
}
|
||||||
|
@ -1167,6 +1169,8 @@ bool Transaction::CancelShardCb(EngineShard* shard) {
|
||||||
|
|
||||||
// runs in engine-shard thread.
|
// runs in engine-shard thread.
|
||||||
ArgSlice Transaction::GetShardArgs(ShardId sid) const {
|
ArgSlice Transaction::GetShardArgs(ShardId sid) const {
|
||||||
|
DCHECK(!multi_ || multi_->role != SQUASHER);
|
||||||
|
|
||||||
// We can read unique_shard_cnt_ only because ShardArgsInShard is called after IsArmedInShard
|
// We can read unique_shard_cnt_ only because ShardArgsInShard is called after IsArmedInShard
|
||||||
// barrier.
|
// barrier.
|
||||||
if (unique_shard_cnt_ == 1) {
|
if (unique_shard_cnt_ == 1) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue