Skip to content

Commit ad789e6

Browse files
authored
Merge pull request #848 from anikitinDSR/validator_additionals
[INDY-1542] Validator additionals
2 parents f4d8a6e + 324c2a7 commit ad789e6

File tree

4 files changed

+66
-27
lines changed

4 files changed

+66
-27
lines changed

build-scripts/ubuntu-1604/build-3rd-parties.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,4 +82,5 @@ build_from_pypi pyzmq 17.0.0
8282
build_from_pypi intervaltree 2.1.0
8383
build_from_pypi jsonpickle 0.9.6
8484
# TODO: add libsnappy dependency for python-rocksdb package
85-
build_from_pypi python-rocksdb 0.6.9
85+
build_from_pypi python-rocksdb 0.6.9
86+
build_from_pypi pympler 0.5

plenum/server/validator_info_tool.py

Lines changed: 55 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from ledger.genesis_txn.genesis_txn_file_util import genesis_txn_path
1515
from stp_core.common.constants import ZMQ_NETWORK_PROTOCOL
1616
from stp_core.common.log import getlogger
17+
from pympler import muppy, summary
1718

1819

1920
def decode_err_handler(error):
@@ -31,6 +32,7 @@ def decode_err_handler(error):
3132
INDY_NODE_SERVICE_FILE_PATH = "/etc/systemd/system/indy-node.service"
3233
NODE_CONTROL_SERVICE_FILE_PATH = "/etc/systemd/system/indy-node-control.service"
3334
NUMBER_TXNS_FOR_DISPLAY = 10
35+
LIMIT_OBJECTS_FOR_PROFILER = 10
3436

3537

3638
def none_on_fail(func):
@@ -65,6 +67,9 @@ def info(self):
6567
pool_info = self.__pool_info
6668
protocol_info = self.__protocol_info
6769
node_info = self.__node_info
70+
memory_profiler = self.__memory_profiler
71+
extractions_info = self.__extractions
72+
6873
if hardware_info:
6974
general_info.update(hardware_info)
7075
if software_info:
@@ -75,17 +80,26 @@ def info(self):
7580
general_info.update(protocol_info)
7681
if node_info:
7782
general_info.update(node_info)
83+
if memory_profiler:
84+
general_info.update(memory_profiler)
85+
if extractions_info:
86+
general_info.update(extractions_info)
87+
7888
return general_info
7989

90+
@property
91+
@none_on_fail
92+
def __memory_profiler(self):
93+
all_objects = muppy.get_objects()
94+
stats = summary.summarize(all_objects)
95+
return {'Memory_profiler': [l for l in summary.format_(stats, LIMIT_OBJECTS_FOR_PROFILER)]}
96+
8097
@property
8198
def additional_info(self):
8299
additional_info = {}
83100
config_info = self.__config_info
84-
extractions_info = self.__extractions
85101
if config_info:
86102
additional_info.update(config_info)
87-
if extractions_info:
88-
additional_info.update(extractions_info)
89103
return additional_info
90104

91105
def _prepare_for_json(self, item):
@@ -181,21 +195,32 @@ def __unreachable_list(self):
181195
def __total_count(self):
182196
return len(self._node.nodestack.remotes) + 1
183197

198+
def _get_folder_size(self, start_path):
199+
total_size = 0
200+
for dirpath, dirnames, filenames in os.walk(start_path):
201+
for f in filenames:
202+
fp = os.path.join(dirpath, f)
203+
try:
204+
total_size += os.path.getsize(fp)
205+
except OSError:
206+
pass
207+
return total_size
208+
184209
@property
185210
@none_on_fail
186211
def __hardware_info(self):
187212
hdd = psutil.disk_usage('/')
188213
ram_all = psutil.virtual_memory()
189214
current_process = psutil.Process()
190215
ram_by_process = current_process.memory_info()
191-
nodes_data = psutil.disk_usage(self._node.ledger_dir)
216+
nodes_data = self._get_folder_size(self._node.ledger_dir)
192217

193218
return {
194219
"Hardware": {
195220
"HDD_all": "{} Mbs".format(int(hdd.used / MBs)),
196221
"RAM_all_free": "{} Mbs".format(int(ram_all.free / MBs)),
197222
"RAM_used_by_node": "{} Mbs".format(int(ram_by_process.vms / MBs)),
198-
"HDD_used_by_node": "{} MBs".format(int(nodes_data.used / MBs)),
223+
"HDD_used_by_node": "{} MBs".format(int(nodes_data / MBs)),
199224
}
200225
}
201226

@@ -404,19 +429,28 @@ def __node_info(self):
404429
waiting_cp = {}
405430
num_txns_in_catchup = {}
406431
last_txn_3PC_keys = {}
407-
root_hashes = {}
408-
uncommited_root_hashes = {}
409-
uncommited_txns = {}
432+
committed_ledger_root_hashes = {}
433+
uncommited_ledger_root_hashes = {}
434+
uncommitted_ledger_txns = {}
435+
committed_state_root_hashes = {}
436+
uncommitted_state_root_hashes = {}
410437
for idx, linfo in self._node.ledgerManager.ledgerRegistry.items():
411438
ledger_statuses[idx] = self._prepare_for_json(linfo.state.name)
412439
waiting_cp[idx] = self._prepare_for_json(linfo.catchUpTill)
413440
num_txns_in_catchup[idx] = self._prepare_for_json(linfo.num_txns_caught_up)
414441
last_txn_3PC_keys[idx] = self._prepare_for_json(linfo.last_txn_3PC_key)
415442
if linfo.ledger.uncommittedRootHash:
416-
uncommited_root_hashes[idx] = self._prepare_for_json(base58.b58encode(linfo.ledger.uncommittedRootHash))
417-
uncommited_txns[idx] = [self._prepare_for_json(txn) for txn in linfo.ledger.uncommittedTxns]
443+
uncommited_ledger_root_hashes[idx] = self._prepare_for_json(base58.b58encode(linfo.ledger.uncommittedRootHash))
444+
txns = {"Count": len(linfo.ledger.uncommittedTxns)}
445+
if len(linfo.ledger.uncommittedTxns) > 0:
446+
txns["First_txn"] = self._prepare_for_json(linfo.ledger.uncommittedTxns[0])
447+
txns["Last_txn"] = self._prepare_for_json(linfo.ledger.uncommittedTxns[-1])
448+
uncommitted_ledger_txns[idx] = txns
418449
if linfo.ledger.tree.root_hash:
419-
root_hashes[idx] = self._prepare_for_json(base58.b58encode(linfo.ledger.tree.root_hash))
450+
committed_ledger_root_hashes[idx] = self._prepare_for_json(base58.b58encode(linfo.ledger.tree.root_hash))
451+
for l_id, req_handler in self._node.ledger_to_req_handler.items():
452+
committed_state_root_hashes[l_id] = self._prepare_for_json(base58.b58encode(req_handler.state.committedHeadHash))
453+
uncommitted_state_root_hashes[l_id] = self._prepare_for_json(base58.b58encode(req_handler.state.headHash))
420454

421455
return {
422456
"Node_info": {
@@ -438,12 +472,16 @@ def __node_info(self):
438472
self.__verkey),
439473
"Metrics": self._prepare_for_json(
440474
self._get_node_metrics()),
441-
"Root_hashes": self._prepare_for_json(
442-
root_hashes),
443-
"Uncommitted_root_hashes": self._prepare_for_json(
444-
uncommited_root_hashes),
445-
"Uncommitted_txns": self._prepare_for_json(
446-
uncommited_txns),
475+
"Committed_ledger_root_hashes": self._prepare_for_json(
476+
committed_ledger_root_hashes),
477+
"Committed_state_root_hashes": self._prepare_for_json(
478+
committed_state_root_hashes),
479+
"Uncommitted_ledger_root_hashes": self._prepare_for_json(
480+
uncommited_ledger_root_hashes),
481+
"Uncommitted_ledger_txns": self._prepare_for_json(
482+
uncommitted_ledger_txns),
483+
"Uncommitted_state_root_hashes": self._prepare_for_json(
484+
uncommitted_state_root_hashes),
447485
"View_change_status": {
448486
"View_No": self._prepare_for_json(
449487
self._node.viewNo),

plenum/test/validator_info/test_validator_info.py

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
INFO_FILENAME = '{}_info.json'.format(TEST_NODE_NAME.lower())
2828
PERIOD_SEC = 1
2929
nodeCount = 5
30-
MAX_TIME_FOR_INFO_BUILDING = 2
30+
MAX_TIME_FOR_INFO_BUILDING = 3
3131

3232

3333
def test_validator_info_file_alias_field_valid(info):
@@ -154,12 +154,11 @@ def test_node_info_section(info, node):
154154
assert info['Node_info']['Mode']
155155
assert info['Node_info']['Name']
156156
assert info['Node_info']['Replicas_status']
157-
assert info['Node_info']['Root_hashes']
158-
assert info['Node_info']['Root_hashes'][0]
159-
assert info['Node_info']['Root_hashes'][1]
160-
assert info['Node_info']['Root_hashes'][2]
161-
assert 'Uncommitted_root_hashes' in info['Node_info']
162-
assert 'Uncommitted_txns' in info['Node_info']
157+
assert "Committed_ledger_root_hashes" in info['Node_info']
158+
assert "Committed_state_root_hashes" in info['Node_info']
159+
assert "Uncommitted_ledger_root_hashes" in info['Node_info']
160+
assert "Uncommitted_ledger_txns" in info['Node_info']
161+
assert "Uncommitted_state_root_hashes" in info['Node_info']
163162
assert info['Node_info']['View_change_status']
164163
assert 'IC_queue' in info['Node_info']['View_change_status']
165164
assert 'VCDone_queue' in info['Node_info']['View_change_status']
@@ -206,7 +205,7 @@ def test_config_info_section(node):
206205

207206

208207
def test_extractions_section(node):
209-
info = node._info_tool.additional_info
208+
info = node._info_tool.info
210209
assert "journalctl_exceptions" in info["Extractions"]
211210
assert "indy-node_status" in info["Extractions"]
212211
assert "node-control status" in info["Extractions"]

setup.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@
4949
'portalocker==0.5.7', 'pyzmq==17.0.0', 'libnacl==1.6.1',
5050
'six==1.11.0', 'psutil==5.4.3', 'intervaltree==2.1.0',
5151
'msgpack-python==0.4.6', 'indy-crypto==0.4.1',
52-
'python-rocksdb==0.6.9', 'python-dateutil==2.6.1'],
52+
'python-rocksdb==0.6.9', 'python-dateutil==2.6.1',
53+
'pympler==0.5'],
5354
setup_requires=['pytest-runner'],
5455
extras_require={
5556
'tests': tests_require,

0 commit comments

Comments
 (0)