3 from __future__ import print_function
8 typedef uint64_t counter_t;
15 STAT_DIR_TYPE_ILLEGAL = 0,
16 STAT_DIR_TYPE_SCALAR_INDEX,
17 STAT_DIR_TYPE_COUNTER_VECTOR_SIMPLE,
18 STAT_DIR_TYPE_COUNTER_VECTOR_COMBINED,
19 STAT_DIR_TYPE_ERROR_INDEX,
20 } stat_directory_type_t;
24 stat_directory_type_t type;
30 uint64_t offset_vector;
31 char name[128]; // TODO change this to pointer to "somewhere"
32 } stat_segment_directory_entry_t;
37 stat_directory_type_t type;
42 counter_t **simple_counter_vec;
43 vlib_counter_t **combined_counter_vec;
45 } stat_segment_data_t;
47 int stat_segment_connect (char *socket_name);
48 void stat_segment_disconnect (void);
50 uint32_t *stat_segment_ls (uint8_t ** pattern);
51 stat_segment_data_t *stat_segment_dump (uint32_t * counter_vec);
52 void stat_segment_data_free (stat_segment_data_t * res);
53 double stat_segment_heartbeat (void);
54 int stat_segment_vec_len(void *vec);
55 uint8_t **stat_segment_string_vector(uint8_t **string_vector, char *string);
60 def make_string_vector(api, strings):
62 if type(strings) is not list:
65 vec = api.stat_segment_string_vector(vec, ffi.new("char []",
70 def make_string_list(api, vec):
71 vec_len = api.stat_segment_vec_len(vec)
72 return [ffi.string(vec[i]) for i in range(vec_len)]
75 # 2-dimensonal array of thread, index
76 def simple_counter_vec_list(api, e):
78 for thread in range(api.stat_segment_vec_len(e)):
79 len_interfaces = api.stat_segment_vec_len(e[thread])
80 if_per_thread = [e[thread][interfaces]
81 for interfaces in range(len_interfaces)]
82 vec.append(if_per_thread)
86 def vlib_counter_dict(c):
87 return {'packets': c.packets,
91 def combined_counter_vec_list(api, e):
93 for thread in range(api.stat_segment_vec_len(e)):
94 len_interfaces = api.stat_segment_vec_len(e[thread])
95 if_per_thread = [vlib_counter_dict(e[thread][interfaces])
96 for interfaces in range(len_interfaces)]
97 vec.append(if_per_thread)
101 def stat_entry_to_python(api, e):
104 return e.scalar_value
107 return simple_counter_vec_list(api, e.simple_counter_vec)
109 return combined_counter_vec_list(api, e.combined_counter_vec)
116 def __init__(self, socketname='/var/run/stats.sock'):
117 self.api = ffi.dlopen('libvppapiclient.so')
118 rv = self.api.stat_segment_connect(socketname.encode())
123 return self.api.stat_segment_heartbeat()
125 def ls(self, patterns):
126 return self.api.stat_segment_ls(make_string_vector(self.api, patterns))
128 def dump(self, counters):
130 rv = self.api.stat_segment_dump(counters)
131 # Raise exception and retry
134 rv_len = self.api.stat_segment_vec_len(rv)
135 for i in range(rv_len):
136 n = ffi.string(rv[i].name).decode()
137 e = stat_entry_to_python(self.api, rv[i])
142 def get_counter(self, name):
147 return self.dump(dir).values()[0]
148 except Exception as e:
154 def disconnect(self):
155 self.api.stat_segment_disconnect()
157 def set_errors(self):
158 '''Return all errors counters > 0'''
162 error_names = self.ls(['/err/'])
163 error_counters = self.dump(error_names)
165 except Exception as e:
170 return {k: error_counters[k]
171 for k in error_counters.keys() if error_counters[k]}
173 def set_errors_str(self):
174 '''Return all errors counters > 0 pretty printed'''
176 error_counters = self.set_errors()
177 for k in sorted(error_counters):
178 s += '{:<60}{:>10}\n'.format(k, error_counters[k])