1 # SPDX-License-Identifier: EPL-1.0
2 ##############################################################################
3 # Copyright (c) 2018 The Linux Foundation and others.
5 # All rights reserved. This program and the accompanying materials
6 # are made available under the terms of the Eclipse Public License v1.0
7 # which accompanies this distribution, and is available at
8 # http://www.eclipse.org/legal/epl-v10.html
9 ##############################################################################
11 from copy import deepcopy as dc
17 print(json.dumps(x, indent=4, sort_keys=True))
28 'categoryLines': False,
38 'legendPosition': 'right',
40 'addTimeMarker': False
45 def create(self, config):
47 temp['title'] = config['title']
48 temp['type'] = temp['params']['type'] = config['type']
51 temp['params']['categoryAxes'] = [dc(
52 cat.create()) for i in range(config['num_cat_axes'])]
55 temp['params']['valueAxes'] = [dc(val.create(position=i['position'],
58 config['value_axes'].items()]
62 temp['aggs'] = [dc(agg.create(field=i['field'],
63 custom_label=i['custom_label'],
66 config['aggs'].items()]
68 temp['params']['seriesParams'] = [seriesParams(i['data_type'],
75 config['seriesParams'].items()]
101 temp = dc(self.content)
102 temp['id'] = 'CategoryAxis-{}'.format(self.counter)
131 def create(self, position='left', title='Value'):
133 temp = dc(self.content)
134 temp['id'] = 'ValueAxis-{}'.format(self.counter)
135 if position == 'left':
136 temp['name'] = 'LeftAxis-{}'.format(self.counter)
137 elif position == 'right':
138 temp['name'] = 'RightAxis-{}'.format(self.counter)
140 # raise ValueError('Not one of left or right')
142 temp['name'] = 'LeftAxis-{}'.format(self.counter)
144 temp['title']['text'] = title
150 def __init__(self, data_type, mode, label, agg_id, value_axis):
159 'valueAxis': 'ValueAxis-{}'.format(value_axis),
160 'drawLinesBetweenPoints': True,
182 def create(self, field, custom_label, schema):
184 temp = dc(self.content)
185 temp['id'] = str(self.counter)
186 temp['params']['field'] = field
187 temp['params']['customLabel'] = custom_label
188 temp['schema'] = schema
189 if schema == 'metric':
192 elif schema == 'segment':
193 temp['type'] = 'terms'
194 temp['params']['size'] = 20 # default
195 temp['params']['order'] = 'asc'
196 temp['params']['orderBy'] = '_term'
200 # generate takes both the template config and project specific config and
201 # parses and organizes as much info available from that and
202 # generates an intermediate format first which
203 # contains all necessary info to deterministically create the visState to
204 # be sent to Kibana. Hence, any error occuring in the visualizaton side
205 # must first be checked by looking at the intermediate format.
207 def generate(dash_config, viz_config):
213 "index_pattern": None,
221 value_axes_format = {
228 seriesParams_format = {
240 "custom_label": None,
246 # all general description must be present in either of the config files
247 for config in [viz_config, dash_config]:
248 general_fields = ['type', 'index_pattern',
249 'num_cat_axes', 'title', 'desc', 'id']
250 for i in general_fields:
252 format[i] = config[i]
253 except KeyError as e:
256 # setting any default values if available
257 mappings = {'value_axes': value_axes_format,
258 'seriesParams': seriesParams_format, 'aggs': aggs_format}
259 for index, container in mappings.items():
261 default_values = viz_config[index]['default']
262 for i in default_values:
263 container['index'][i] = default_values[i]
267 value_axes_counter = 1
268 for m in viz_config['value_axes']:
270 temp = dc(value_axes_format)
271 temp[str(value_axes_counter)] = temp['index']
272 for i in ['position', 'title']:
274 temp[str(value_axes_counter)
275 ][i] = viz_config['value_axes'][m][i]
278 format['value_axes'].update(temp)
279 value_axes_counter += 1
281 seriesParams_counter = 1
282 seriesParams_fields = ['value_axis',
283 'data_type', 'mode', 'label', 'agg_id']
285 for m in viz_config['seriesParams']:
287 temp = dc(seriesParams_format)
288 temp[str(seriesParams_counter)] = temp['index']
289 for i in seriesParams_fields:
291 temp[str(seriesParams_counter)
292 ][i] = viz_config['seriesParams'][m][i]
295 format['seriesParams'].update(temp)
296 seriesParams_counter += 1
302 for m in viz_config['aggs']:
304 temp = dc(aggs_format)
305 temp[str(agg_counter)] = temp['index']
306 for i in ['field', 'custom_label', 'schema']:
308 temp[str(agg_counter)][i] = viz_config['aggs'][m][i]
311 format['aggs'].update(temp)
319 configs.append(viz_config)
324 dash_config['y-axis']['series']
325 configs.append(dash_config['y-axis'])
329 for config in configs:
331 value_axes_counter = 1
332 for key in config['value_axes']:
334 value_axes_temp = dc(value_axes_format)
335 value_axes_temp[str(value_axes_counter)
336 ] = value_axes_temp['index']
338 for index in ['position', 'title']:
341 value_axes_counter)][index] = \
342 config['value_axes'][key][index]
343 except KeyError as e:
345 format['value_axes'].update(value_axes_temp)
346 value_axes_counter += 1
348 except KeyError as e:
352 for key in config['series']:
354 # check if this key is present or not
355 config['series'][key]['not_in_seriesParams']
357 seriesParams_temp = dc(seriesParams_format)
358 seriesParams_temp[str(
359 seriesParams_counter)] = seriesParams_temp['index']
360 for index in ['value_axis', 'data_type', 'mode', 'label']:
362 seriesParams_temp[str(
363 seriesParams_counter)][index] = \
364 config['series'][key][index]
365 except KeyError as e:
367 seriesParams_temp[str(
368 seriesParams_counter)]['agg_id'] = agg_counter
369 format['seriesParams'].update(seriesParams_temp)
370 seriesParams_counter += 1
372 agg_temp = dc(aggs_format)
373 agg_temp[str(agg_counter)] = agg_temp['index']
374 for index in ['field', 'schema']:
376 agg_temp[str(agg_counter)
377 ][index] = config['series'][key][index]
378 except KeyError as e:
381 agg_counter)]['custom_label'] = \
382 config['series'][key]['label']
383 format['aggs'].update(agg_temp)
385 except KeyError as e:
386 print("required fields are empty!")
388 # to remove the default template index
389 for i in ['value_axes', 'seriesParams', 'aggs']:
391 format[i].pop('index')
393 # print("No default index found")
396 if not config_validator(format):
397 raise ValueError('Missing required field values')
402 generated_visState = vis.create(format)
404 # checking incase there are None values \
405 # in the format indicating missing fields
407 if not config_validator(generated_visState):
408 raise KeyError('required fields are missing values!')
409 return format, generated_visState
412 # Check the generated format if it contains any key with None
413 # as it's value which indicates incomplete information
414 def config_validator(val):
416 for _, i in val.items():
417 if isinstance(i, dict):
418 flag = config_validator(i)
424 if __name__ == '__main__':
425 with open('viz.yaml', 'r') as f:
426 viz_config = yaml.safe_load(f)
428 with open('dashboard.yaml', 'r') as f:
429 dash_config = yaml.safe_load(f)
431 generate(dash_config['dashboard']['viz'][2],
432 viz_config['opendaylight-test-performance'])
433 # generate(dash_config['dashboard']['viz'][3],viz_config['opendaylight-test-performance'])
434 # generate(dash_config['dashboard']['viz'][1],viz_config['opendaylight-test-feature'])