monitor-p2p.py 4.8 KB

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