chore: Add stats print for slot migrations (#4456)

* chore: Add stats print for slot migrations

Fixes #4415
This commit is contained in:
Shahar Mike 2025-01-15 13:06:09 +02:00 committed by GitHub
parent 0eff6c93f2
commit 5ba608b58d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 116 additions and 34 deletions

View file

@ -214,6 +214,21 @@ async def get_node_id(connection):
return id
def stop_and_get_restore_log(instance):
instance.stop()
lines = instance.find_in_logs("RestoreStreamer LSN")
assert len(lines) == 1
line = lines[0]
logging.debug(f"Streamer log line: {line}")
return line
def extract_int_after_prefix(prefix, line):
match = re.search(prefix + "(\\d+)", line)
assert match
return int(match.group(1))
@dfly_args({})
class TestNotEmulated:
async def test_cluster_commands_fails_when_not_emulate(self, async_client: aioredis.Redis):
@ -2035,6 +2050,18 @@ async def test_cluster_migration_huge_container(df_factory: DflyInstanceFactory)
logging.debug(f"Memory before {mem_before} after {mem_after}")
assert mem_after < mem_before * 1.1
line = stop_and_get_restore_log(nodes[0].instance)
# 'with X commands' - how many breakdowns we used for the keys
assert extract_int_after_prefix("with ", line) > 500_000
assert extract_int_after_prefix("Keys skipped ", line) == 0
assert extract_int_after_prefix("buckets skipped ", line) == 0
assert extract_int_after_prefix("keys written ", line) > 90
# We don't send updates during the migration
assert extract_int_after_prefix("buckets on_db_update ", line) == 0
@dfly_args({"proactor_threads": 2, "cluster_mode": "yes"})
@pytest.mark.parametrize("chunk_size", [1_000_000, 30])
@ -2056,7 +2083,6 @@ async def test_cluster_migration_while_seeding(
nodes[0].slots = [(0, 16383)]
nodes[1].slots = []
client0 = nodes[0].client
client1 = nodes[1].client
await push_config(json.dumps(generate_config(nodes)), [node.admin_client for node in nodes])
@ -2098,6 +2124,12 @@ async def test_cluster_migration_while_seeding(
capture = await seeder.capture_fake_redis()
assert await seeder.compare(capture, instances[1].port)
line = stop_and_get_restore_log(nodes[0].instance)
assert extract_int_after_prefix("Keys skipped ", line) == 0
assert extract_int_after_prefix("buckets skipped ", line) > 0
assert extract_int_after_prefix("keys written ", line) >= 9_000
assert extract_int_after_prefix("buckets on_db_update ", line) > 0
def parse_lag(replication_info: str):
lags = re.findall("lag=([0-9]+)\r\n", replication_info)

View file

@ -380,16 +380,17 @@ class DflyInstance:
for metric_family in text_string_to_metric_families(data)
}
def is_in_logs(self, pattern):
def find_in_logs(self, pattern):
if self.proc is not None:
raise RuntimeError("Must close server first")
results = []
matcher = re.compile(pattern)
for path in self.log_files:
for line in open(path):
if matcher.search(line):
return True
return False
results.append(line)
return results
@property
def rss(self):
@ -416,7 +417,7 @@ class DflyInstanceFactory:
args.setdefault("noversion_check", None)
# MacOs does not set it automatically, so we need to set it manually
args.setdefault("maxmemory", "8G")
vmod = "dragonfly_connection=1,accept_server=1,listener_interface=1,main_service=1,rdb_save=1,replica=1,cluster_family=1,proactor_pool=1,dflycmd=1,snapshot=1"
vmod = "dragonfly_connection=1,accept_server=1,listener_interface=1,main_service=1,rdb_save=1,replica=1,cluster_family=1,proactor_pool=1,dflycmd=1,snapshot=1,streamer=1"
args.setdefault("vmodule", vmod)
args.setdefault("jsonpathv2")