88from time import sleep
99
1010import click
11+ import requests
1112import yaml
13+ from prometheus_client .parser import text_string_to_metric_families
1214from pyparsing import alphanums
1315from pyparsing import Group
1416from pyparsing import OneOrMore
1921
2022DEBUG = False
2123
24+ RECEPTOR_METRICS = (
25+ "active_work" ,
26+ "connected_peers" ,
27+ "incoming_messages" ,
28+ "route_events" ,
29+ "work_events" ,
30+ )
31+
2232
2333class Conn :
2434 def __init__ (self , a , b ):
@@ -65,7 +75,10 @@ def random_port(tcp=True):
6575procs = []
6676
6777
68- Node = namedtuple ("Node" , ["name" , "controller" , "listen_port" , "connections" ])
78+ Node = namedtuple ('Node' , [
79+ "name" , "controller" , "listen_port" , "connections" , "stats_enable" ,
80+ "stats_port"
81+ ])
6982
7083
7184def generate_random_mesh (controller_port , node_count , conn_method ):
@@ -91,6 +104,8 @@ def do_it(topology, profile=False):
91104 "listen_port" : node_data .listen_port if node_data .controller else None ,
92105 "controller" : node_data .controller ,
93106 "connections" : node_data .connections ,
107+ "stats_enable" : node_data .stats_enable ,
108+ "stats_port" : node_data .stats_port ,
94109 }
95110 yaml .dump (data , f )
96111 with open ("last-topology_graph.dot" , "w" ) as f :
@@ -131,6 +146,11 @@ def do_it(topology, profile=False):
131146 f"--listen-port={ node .listen_port } " ,
132147 ]
133148 )
149+ if node .stats_enable :
150+ starter .extend ([
151+ "--stats-enable" ,
152+ f"--stats-port={ node .stats_port } " ,
153+ ])
134154 op = subprocess .Popen (" " .join (starter ), shell = True )
135155 procs .append (op )
136156 f .write (f"{ ' ' .join (starter )} \n " )
@@ -155,6 +175,11 @@ def do_it(topology, profile=False):
155175 peer_string ,
156176 ]
157177 )
178+ if node .stats_enable :
179+ starter .extend ([
180+ "--stats-enable" ,
181+ f"--stats-port={ node .stats_port } " ,
182+ ])
158183 op = subprocess .Popen (" " .join (starter ), shell = True )
159184 procs .append (op )
160185 f .write (f"{ ' ' .join (starter )} \n " )
@@ -177,6 +202,8 @@ def load_topology(filename):
177202 definition ["controller" ],
178203 definition .get ("listen_port" , None ) or random_port (),
179204 definition ["connections" ],
205+ definition .get ("stats_enable" , False ),
206+ definition .get ("stats_port" , None ) or random_port (),
180207 )
181208 return topology
182209
@@ -331,5 +358,37 @@ def dot_compare(filename_one, filename_two, wait):
331358 sys .exit (127 )
332359
333360
361+ @main .command ("check-stats" )
362+ @click .option ("--debug" , is_flag = True , default = False )
363+ @click .option ("--profile" , is_flag = True , default = False )
364+ @click .argument ("filename" , type = click .File ("r" ))
365+ def check_stats (filename , debug , profile ):
366+ topology = load_topology (filename )
367+ failures = []
368+
369+ for node in topology .values ():
370+ if not node .stats_enable :
371+ continue
372+ stats = requests .get (f'http://localhost:{ node .stats_port } /metrics' )
373+ metrics = {
374+ metric .name : metric
375+ for metric in text_string_to_metric_families (stats .text )
376+ if metric .name in RECEPTOR_METRICS
377+ }
378+ expected_connected_peers = len ([
379+ n for n in topology .values () if node .name in n .connections
380+ ]) + len (node .connections )
381+ connected_peers = metrics ['connected_peers' ].samples [0 ].value
382+ if expected_connected_peers != connected_peers :
383+ failures .append (
384+ f"Node '{ node .name } ' was expected to have "
385+ f"{ expected_connected_peers } connections, but it reported to "
386+ f" have { connected_peers } "
387+ )
388+ if failures :
389+ print ('\n ' .join (failures ))
390+ sys .exit (127 )
391+
392+
334393if __name__ == "__main__" :
335394 main ()
0 commit comments