2
2
3
3
#####################################################################
4
4
#
5
- # queuestat is a tool for summarizing queue statistics of all ports.
5
+ # queuestat is a tool for summarizing queue statistics of all ports.
6
6
#
7
7
#####################################################################
8
8
9
9
import _pickle as pickle
10
10
import argparse
11
11
import datetime
12
12
import os .path
13
- from swsscommon .swsscommon import SonicV2Connector
14
13
import sys
15
14
16
15
from collections import namedtuple , OrderedDict
17
16
from natsort import natsorted
18
17
from tabulate import tabulate
19
18
19
+ # mock the redis for unit test purposes #
20
+ try :
21
+ if os .environ ["UTILITIES_UNIT_TESTING" ] == "2" :
22
+ modules_path = os .path .join (os .path .dirname (__file__ ), ".." )
23
+ tests_path = os .path .join (modules_path , "tests" )
24
+ sys .path .insert (0 , modules_path )
25
+ sys .path .insert (0 , tests_path )
26
+ import mock_tables .dbconnector # lgtm [py/unused-import]
27
+
28
+ except KeyError :
29
+ pass
30
+
31
+ from swsscommon .swsscommon import SonicV2Connector
20
32
21
33
QueueStats = namedtuple ("QueueStats" , "queueindex, queuetype, totalpacket, totalbytes, droppacket, dropbytes" )
22
34
header = ['Port' , 'TxQ' , 'Counter/pkts' , 'Counter/bytes' , 'Drop/pkts' , 'Drop/bytes' ]
@@ -28,6 +40,7 @@ counter_bucket_dict = {
28
40
'SAI_QUEUE_STAT_DROPPED_BYTES' : 5 ,
29
41
}
30
42
43
+ from utilities_common .cli import json_dump
31
44
from utilities_common .netstat import ns_diff , STATUS_NA
32
45
33
46
QUEUE_TYPE_MC = 'MC'
@@ -47,6 +60,24 @@ COUNTERS_QUEUE_PORT_MAP = "COUNTERS_QUEUE_PORT_MAP"
47
60
cnstat_dir = 'N/A'
48
61
cnstat_fqn_file = 'N/A'
49
62
63
+
64
+ def build_json (port , cnstat ):
65
+ def ports_stats (k ):
66
+ p = {}
67
+ p [k [1 ]] = {
68
+ "totalpacket" : k [2 ],
69
+ "totalbytes" : k [3 ],
70
+ "droppacket" : k [4 ],
71
+ "dropbytes" : k [5 ]
72
+ }
73
+ return p
74
+
75
+ out = {}
76
+ for k in cnstat :
77
+ out .update (ports_stats (k ))
78
+ return out
79
+
80
+
50
81
class Queuestat (object ):
51
82
def __init__ (self ):
52
83
self .db = SonicV2Connector (use_unix_socket_path = False )
@@ -134,33 +165,45 @@ class Queuestat(object):
134
165
if queue_map is None :
135
166
return cnstat_dict
136
167
for queue in natsorted (queue_map ):
137
- cnstat_dict [queue ] = get_counters (queue_map [queue ])
168
+ cnstat_dict [queue ] = get_counters (queue_map [queue ])
138
169
return cnstat_dict
139
170
140
- def cnstat_print (self , port , cnstat_dict ):
171
+ def cnstat_print (self , port , cnstat_dict , json_opt ):
141
172
"""
142
- Print the cnstat.
173
+ Print the cnstat. If JSON option is True, return data in
174
+ JSON format.
143
175
"""
144
176
table = []
177
+ json_output = {port : {}}
145
178
146
179
for key , data in cnstat_dict .items ():
147
180
if key == 'time' :
181
+ if json_opt :
182
+ json_output [port ][key ] = data
148
183
continue
149
184
table .append ((port , data .queuetype + str (data .queueindex ),
150
185
data .totalpacket , data .totalbytes ,
151
186
data .droppacket , data .dropbytes ))
152
187
153
- print (tabulate (table , header , tablefmt = 'simple' , stralign = 'right' ))
154
- print ()
188
+ if json_opt :
189
+ json_output [port ].update (build_json (port , table ))
190
+ return json_output
191
+ else :
192
+ print (tabulate (table , header , tablefmt = 'simple' , stralign = 'right' ))
193
+ print ()
155
194
156
- def cnstat_diff_print (self , port , cnstat_new_dict , cnstat_old_dict ):
195
+ def cnstat_diff_print (self , port , cnstat_new_dict , cnstat_old_dict , json_opt ):
157
196
"""
158
- Print the difference between two cnstat results.
197
+ Print the difference between two cnstat results. If JSON
198
+ option is True, return data in JSON format.
159
199
"""
160
200
table = []
201
+ json_output = {port : {}}
161
202
162
203
for key , cntr in cnstat_new_dict .items ():
163
204
if key == 'time' :
205
+ if json_opt :
206
+ json_output [port ][key ] = cntr
164
207
continue
165
208
old_cntr = None
166
209
if key in cnstat_old_dict :
@@ -177,42 +220,78 @@ class Queuestat(object):
177
220
cntr .totalpacket , cntr .totalbytes ,
178
221
cntr .droppacket , cntr .dropbytes ))
179
222
180
- print (tabulate (table , header , tablefmt = 'simple' , stralign = 'right' ))
181
- print ()
223
+ if json_opt :
224
+ json_output [port ].update (build_json (port , table ))
225
+ return json_output
226
+ else :
227
+ print (tabulate (table , header , tablefmt = 'simple' , stralign = 'right' ))
228
+ print ()
182
229
183
- def get_print_all_stat (self ):
184
- # Get stat for each port
230
+ def get_print_all_stat (self , json_opt ):
231
+ """
232
+ Get stat for each port
233
+ If JSON option is True, collect data for each port and
234
+ print data in JSON format for all ports
235
+ """
236
+ json_output = {}
185
237
for port in natsorted (self .counter_port_name_map ):
238
+ json_output [port ] = {}
186
239
cnstat_dict = self .get_cnstat (self .port_queues_map [port ])
187
240
188
241
cnstat_fqn_file_name = cnstat_fqn_file + port
189
242
if os .path .isfile (cnstat_fqn_file_name ):
190
243
try :
191
244
cnstat_cached_dict = pickle .load (open (cnstat_fqn_file_name , 'rb' ))
192
- print (port + " Last cached time was " + str (cnstat_cached_dict .get ('time' )))
193
- self .cnstat_diff_print (port , cnstat_dict , cnstat_cached_dict )
245
+ if json_opt :
246
+ json_output [port ].update ({"cached_time" :cnstat_cached_dict .get ('time' )})
247
+ json_output .update (self .cnstat_diff_print (port , cnstat_dict , cnstat_cached_dict , json_opt ))
248
+ else :
249
+ print (port + " Last cached time was " + str (cnstat_cached_dict .get ('time' )))
250
+ self .cnstat_diff_print (port , cnstat_dict , cnstat_cached_dict , json_opt )
194
251
except IOError as e :
195
252
print (e .errno , e )
196
253
else :
197
- self .cnstat_print (port , cnstat_dict )
254
+ if json_opt :
255
+ json_output .update (self .cnstat_print (port , cnstat_dict , json_opt ))
256
+ else :
257
+ self .cnstat_print (port , cnstat_dict , json_opt )
198
258
199
- def get_print_port_stat (self , port ):
259
+ if json_opt :
260
+ print (json_dump (json_output ))
261
+
262
+ def get_print_port_stat (self , port , json_opt ):
263
+ """
264
+ Get stat for the port
265
+ If JSON option is True print data in JSON format
266
+ """
200
267
if not port in self .port_queues_map :
201
268
print ("Port doesn't exist!" , port )
202
269
sys .exit (1 )
203
270
204
271
# Get stat for the port queried
205
272
cnstat_dict = self .get_cnstat (self .port_queues_map [port ])
206
273
cnstat_fqn_file_name = cnstat_fqn_file + port
274
+ json_output = {}
275
+ json_output [port ] = {}
207
276
if os .path .isfile (cnstat_fqn_file_name ):
208
277
try :
209
278
cnstat_cached_dict = pickle .load (open (cnstat_fqn_file_name , 'rb' ))
210
- print ("Last cached time was " + str (cnstat_cached_dict .get ('time' )))
211
- self .cnstat_diff_print (port , cnstat_dict , cnstat_cached_dict )
279
+ if json_opt :
280
+ json_output [port ].update ({"cached_time" :cnstat_cached_dict .get ('time' )})
281
+ json_output .update (self .cnstat_diff_print (port , cnstat_dict , cnstat_cached_dict , json_opt ))
282
+ else :
283
+ print ("Last cached time was " + str (cnstat_cached_dict .get ('time' )))
284
+ self .cnstat_diff_print (port , cnstat_dict , cnstat_cached_dict , json_opt )
212
285
except IOError as e :
213
286
print (e .errno , e )
214
287
else :
215
- self .cnstat_print (port , cnstat_dict )
288
+ if json_opt :
289
+ json_output .update (self .cnstat_print (port , cnstat_dict , json_opt ))
290
+ else :
291
+ self .cnstat_print (port , cnstat_dict , json_opt )
292
+
293
+ if json_opt :
294
+ print (json_dump (json_output ))
216
295
217
296
def save_fresh_stats (self ):
218
297
if not os .path .exists (cnstat_dir ):
@@ -251,10 +330,12 @@ Examples:
251
330
parser .add_argument ('-c' , '--clear' , action = 'store_true' , help = 'Clear previous stats and save new ones' )
252
331
parser .add_argument ('-d' , '--delete' , action = 'store_true' , help = 'Delete saved stats' )
253
332
parser .add_argument ('-v' , '--version' , action = 'version' , version = '%(prog)s 1.0' )
333
+ parser .add_argument ('-j' , '--json_opt' , action = 'store_true' , help = 'Print in JSON format' )
254
334
args = parser .parse_args ()
255
335
256
336
save_fresh_stats = args .clear
257
337
delete_all_stats = args .delete
338
+ json_opt = args .json_opt
258
339
259
340
port_to_show_stats = args .port
260
341
@@ -282,9 +363,9 @@ Examples:
282
363
sys .exit (0 )
283
364
284
365
if port_to_show_stats != None :
285
- queuestat .get_print_port_stat (port_to_show_stats )
366
+ queuestat .get_print_port_stat (port_to_show_stats , json_opt )
286
367
else :
287
- queuestat .get_print_all_stat ()
368
+ queuestat .get_print_all_stat (json_opt )
288
369
289
370
sys .exit (0 )
290
371
0 commit comments