monitor-p2p.py 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. import asyncio
  2. from tabulate import tabulate
  3. from copy import deepcopy
  4. import re
  5. import os
  6. import sys
  7. import time
  8. lock = asyncio.Lock()
  9. logs_path = "/tmp/darkfi/"
  10. node_info = {
  11. }
  12. ping_times = {
  13. }
  14. def debug(line):
  15. #print(line)
  16. pass
  17. def process(info, line):
  18. regex_inbound_connect = re.compile(
  19. ".* Connected inbound \[(\d+[.]\d+[.]\d+[.]\d+:\d+)\]")
  20. regex_outbound_slots = re.compile(
  21. ".* Starting (\d+) outbound connection slots.")
  22. regex_outbound_connect = re.compile(
  23. ".* #(\d+) connected to outbound \[(\d+[.]\d+[.]\d+[.]\d+:\d+)\]")
  24. regex_channel_disconnected = re.compile(
  25. ".* Channel (\d+[.]\d+[.]\d+[.]\d+:\d+) disconnected")
  26. regex_pong_recv = re.compile(
  27. ".* Received Pong message (\d+)ms from \[(\d+[.]\d+[.]\d+[.]\d+:\d+)\]")
  28. if "net: P2p::start() [BEGIN]" in line:
  29. info["status"] = "p2p-start"
  30. elif "net: SeedSession::start() [START]" in line:
  31. info["status"] = "seed-start"
  32. elif "net: SeedSession::start() [END]" in line:
  33. info["status"] = "seed-done"
  34. elif "net: P2p::start() [END]" in line:
  35. info["status"] = "p2p-done"
  36. elif "net: P2p::run() [BEGIN]" in line:
  37. info["status"] = "p2p-run"
  38. elif "Not configured for accepting incoming connections." in line:
  39. info["inbounds"] = ["Disabled"]
  40. elif (match := regex_inbound_connect.match(line)) is not None:
  41. address = match.group(1)
  42. info["inbounds"].append(address)
  43. elif (match := regex_outbound_slots.match(line)) is not None:
  44. slots = match.group(1)
  45. info["outbounds"] = ["None" for _ in range(int(slots))]
  46. elif (match := regex_outbound_connect.match(line)) is not None:
  47. slot = match.group(1)
  48. address = match.group(2)
  49. info["outbounds"][int(slot)] = address
  50. elif (match := regex_channel_disconnected.match(line)) is not None:
  51. address = match.group(1)
  52. try:
  53. info["inbounds"].remove(address)
  54. except ValueError:
  55. pass
  56. try:
  57. idx = info["outbounds"].index(address)
  58. info["outbounds"][idx] = "None"
  59. except ValueError:
  60. pass
  61. elif (match := regex_pong_recv.match(line)) is not None:
  62. ping_time = match.group(1)
  63. address = match.group(2)
  64. ping_times[address] = ping_time
  65. async def scanner(filename):
  66. global table_data
  67. async with lock:
  68. node_info[filename] = {
  69. "status": "none",
  70. "inbounds": [],
  71. "outbounds": [],
  72. }
  73. info = node_info[filename]
  74. with open(logs_path + filename) as fileh:
  75. while True:
  76. line = fileh.readline()
  77. if line:
  78. debug("R: " + filename + ": " + line[:-1])
  79. async with lock:
  80. process(info, line)
  81. else:
  82. await asyncio.sleep(0.5)
  83. def clear_lines(n):
  84. for i in range(n):
  85. sys.stdout.write('\033[F')
  86. def get_ping(addr):
  87. ping_time = "none"
  88. if addr in ping_times:
  89. ping_time = str(ping_times[addr]) + " ms"
  90. return ping_time
  91. def table_format(ninfo):
  92. table_data = []
  93. for filename, info in ninfo.items():
  94. table_data.append([filename, "", ""])
  95. table_data.append(["", "status", info["status"]])
  96. inbounds = info["inbounds"]
  97. if inbounds:
  98. table_data.append(["", "inbounds", inbounds[0],
  99. get_ping(inbounds[0])])
  100. for inbound in inbounds[1:]:
  101. table_data.append(["", "", inbound, get_ping(inbound)])
  102. outbounds = info["outbounds"]
  103. if outbounds:
  104. table_data.append(["", "outbounds", outbounds[0],
  105. get_ping(outbounds[0])])
  106. for outbound in outbounds[1:]:
  107. table_data.append(["", "", outbound, get_ping(outbound)])
  108. headers = ["Name", "Attribute", "Value", "Ping Times"]
  109. return headers, table_data
  110. async def refresh_table(tick=1):
  111. for filename in os.listdir(logs_path):
  112. asyncio.create_task(scanner(filename))
  113. previous_lines = 0
  114. while True:
  115. clear_lines(previous_lines)
  116. async with lock:
  117. ninfo = deepcopy(node_info)
  118. headers, table_data = table_format(ninfo)
  119. lines = tabulate(table_data, headers=headers).split("\n")
  120. debug("-------------------")
  121. for line in lines:
  122. print('\x1b[2K\r', end="")
  123. print(line)
  124. previous_lines = len(lines)
  125. await asyncio.sleep(1)
  126. asyncio.run(refresh_table())