Files
scylladb/test/nodetool/test_info.py
Nadav Har'El 4faceeaa33 Merge 'treewide: drop thrift support' from Kefu Chai
thrift support was deprecated since ScyllaDB 5.2

> Thrift API - legacy ScyllaDB (and Apache Cassandra) API is
> deprecated and will be removed in followup release. Thrift has
> been disabled by default.

so let's drop it. in this change,

* thrift protocol support is dropped
* all references to thrift support in document are dropped
* the "thrift_version" column in system.local table is preserved for backward compatibility, as we could load from an existing system.local table which still contains this clolumn, so we need to write this column as well.
* "/storage_service/rpc_server" is only preserved for backward compatibility with java-based nodetool.

Fixes #3811
Fixes #18416
Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

- [x] not a fix, no need to backport

Closes scylladb/scylladb#18453

* github.com:scylladb/scylladb:
  config: expand on rpc_keepalive's description
  api: s/rpc/thrift/
  db/system_keyspace: drop thrift_version from system.local table
  transport: do not return client_type from cql_server::connection::make_client_key()
  treewide: drop thrift support
2024-06-17 22:36:49 +03:00

217 lines
8.2 KiB
Python

#
# Copyright 2023-present ScyllaDB
#
# SPDX-License-Identifier: AGPL-3.0-or-later
#
import random
from typing import NamedTuple
import pytest
from test.nodetool.rest_api_mock import expected_request
from test.nodetool.utils import format_size
class moving_average(NamedTuple):
rates: list[float]
mean_rate: float
count: int
def to_json(self):
return {
'rates': self.rates,
'mean_rate': self.mean_rate,
'count': self.count
}
@staticmethod
def make(count=0):
# 1, 5, 15 minutes rates
rates = [random.random() for _ in (1, 5, 15)]
# the mean rate from startup
mean_rate = random.random()
return moving_average(rates, mean_rate, count)
class cache_metrics(NamedTuple):
entries: int
size: int
capacity: int
hits: moving_average
requests: moving_average
hit_rate: float
save_period: int
def normalize_output(output):
# Scylla does not run a JVM, so it the memory usage exposed by MemoryMXBean
# is meaningless to it.
normalized = ''
for line in output.split('\n'):
if line.startswith('Heap Memory'):
continue
if line.startswith('Uptime'):
continue
# cassandra nodetool use KiB and KB interchangeably, let's
# normalize these two prefixes
for iec, si in [('KiB', 'KB'), ('MiB', 'MB'), ('GiB', 'GB')]:
line = line.replace(iec, si)
normalized += f'{line}\n'
return normalized
@pytest.mark.parametrize("display_all_tokens",
[
True,
False,
]
)
def test_info(request, nodetool, display_all_tokens):
host_id = 'hostid0'
endpoint = '127.0.0.1'
endpoint_to_host_id = {endpoint: host_id}
generation_number = 42
load = 42424242
uptime = 12345
datacenter = 'dc0'
rack = 'rack0'
nr_exceptions = 0
join_ring = True
caches = {
'key': cache_metrics(98, 123, 1220, moving_average.make(), moving_average.make(), 0.42, 20),
'row': cache_metrics(42, 223, 1200, moving_average.make(), moving_average.make(), 0.43, 20),
'counter': cache_metrics(13, 523, 3200, moving_average.make(), moving_average.make(), 0.44, 20),
}
off_heap_mem_usages = {
'memtable_off_heap_size': 1234,
'bloom_filter_off_heap_memory_used': 1235,
'index_summary_off_heap_memory_used': 1236,
'compression_metadata_off_heap_memory_used': 1237,
}
tables = [('ks0', 'cf0', 'ColumnFamilies'),
('ks0', 'cf1', 'ColumnFamilies')]
tokens = ['-9217327499541836964',
'9066719992055809912',
'50927788561116407']
expected_requests = [
expected_request('GET', '/storage_service/gossiping', response=True),
expected_request('GET', '/storage_service/hostid/local', response=host_id),
expected_request('GET', '/storage_service/rpc_server', response=False),
expected_request('GET', '/storage_service/native_transport', response=True),
expected_request('GET', '/storage_service/load', response=load),
expected_request('GET', '/storage_service/generation_number', response=generation_number),
]
is_scylla = request.config.getoption('nodetool') == 'scylla'
if is_scylla:
expected_requests.append(
expected_request('GET', '/system/uptime_ms', response=uptime))
else:
# cassandra nodetool uses RuntimeMXBean
pass
expected_requests.append(
expected_request('GET', '/column_family/',
multiple=expected_request.MULTIPLE,
response=[{'ks': ks, 'cf': cf, 'type': type_} for ks, cf, type_ in tables]))
off_heap_mem_used = 0
for ks, cf, _ in tables:
for name, mem_used in off_heap_mem_usages.items():
off_heap_mem_used += mem_used
expected_requests.append(
expected_request('GET', f'/column_family/metrics/{name}/{ks}:{cf}',
response=mem_used))
expected_requests += [
expected_request('GET', '/snitch/datacenter', multiple=expected_request.ANY, response=datacenter),
expected_request('GET', '/snitch/rack', multiple=expected_request.ANY, response=rack),
expected_request('GET', '/storage_service/metrics/exceptions', response=nr_exceptions),
]
for name, cache in caches.items():
expected_requests += [
expected_request('GET', f'/cache_service/metrics/{name}/entries',
response=cache.entries),
expected_request('GET', f'/cache_service/metrics/{name}/size',
response=cache.size),
expected_request('GET', f'/cache_service/metrics/{name}/capacity',
response=cache.capacity),
expected_request('GET', f'/cache_service/metrics/{name}/hits_moving_avrage',
multiple=expected_request.ANY,
response=cache.hits.to_json()),
expected_request('GET', f'/cache_service/metrics/{name}/requests_moving_avrage',
multiple=expected_request.ANY,
response=cache.requests.to_json()),
expected_request('GET', f'/cache_service/metrics/{name}/hit_rate',
response=cache.hit_rate),
expected_request('GET', f'/cache_service/{name}_cache_save_period',
response=cache.save_period)
]
expected_requests.append(
expected_request('GET', '/storage_service/join_ring',
response=join_ring))
if join_ring:
if is_scylla:
expected_requests.append(
expected_request('GET', '/storage_service/tokens',
response=tokens))
else:
expected_requests += [
expected_request('GET', '/storage_service/host_id',
response=[{'key': endpoint, 'value': hostid}
for endpoint, hostid in endpoint_to_host_id.items()]),
expected_request('GET', '/storage_service/hostid/local', response=host_id),
expected_request('GET', f'/storage_service/tokens/{endpoint}',
response=tokens)
]
mem_used = 0.0
mem_max = 0.0
off_heap_mem_used_in_mb = off_heap_mem_used / 1024 / 1024
expected_output = f'''\
{'ID':<23}: {host_id}
{'Gossip active':<23}: true
{'Thrift active':<23}: false
{'Native Transport active':<23}: true
{'Load':<23}: {format_size(load)}
{'Generation No':<23}: {generation_number}
{'Uptime (seconds)':<23}: {uptime}
{'Heap Memory (MB)':<23}: {mem_used:.2f} / {mem_max:.2f}
{'Off Heap Memory (MB)':<23}: {off_heap_mem_used_in_mb:.2f}
{'Data Center':<23}: {datacenter}
{'Rack':<23}: {rack}
{'Exceptions':<23}: {nr_exceptions}
'''
for n, c in caches.items():
name = f'{n.capitalize()} Cache'
expected_output += (f'{name:<23}: '
f'entries {c.entries}, size {format_size(c.size)}, '
f'capacity {format_size(c.capacity)}, '
f'{c.hits.count} hits, {c.requests.count} requests, '
f'{c.hit_rate:.3f} recent hit rate, '
f'{c.save_period} save period in seconds\n')
percent_repaired = 0.0
expected_output += f"{'Percent Repaired':<23}: {percent_repaired:.1f}%\n"
if join_ring:
name = 'Token'
if display_all_tokens:
for token in tokens:
expected_output += f'{name:<23}: {token}\n'
else:
nr_tokens = len(tokens)
expected_output += f'{name:<23}: (invoke with -T/--tokens to see all {nr_tokens} tokens)\n'
else:
expected_output += f'{name:<23}: (invoke with -T/--tokens to see all {nr_tokens} tokens)\n'
args = []
if display_all_tokens:
args.append('--tokens')
res = nodetool("info", *args, expected_requests=expected_requests)
assert normalize_output(res.stdout) == normalize_output(expected_output)