2020@author: HWASSMAN
2121'''
2222
23-
24- from collections import defaultdict
23+ import copy
24+ from collections import defaultdict , OrderedDict
2525from typing import Set , List , Dict , DefaultDict
2626
2727# dict.iteritems() deprecated in python 3
@@ -34,14 +34,14 @@ class Topo(object):
3434 '''
3535
3636 def __init__ (self , jsonStr = None ):
37- self .topo = jsonStr
3837 self .__metricsDef = defaultdict (dict ) # metrics dictionary, per sensor for all elements in the metadata
38+ self .__metricsType = defaultdict (dict ) # metrics types dictionary
3939 self .__levels = defaultdict (dict ) # component level priority dictionary, per sensor
4040 self .__ids = {} # fieldIds dictionary
4141 self .__groupKeys = {}
4242 self .__compTree = {}
43- if self . topo :
44- self ._processMetadata (self . topo )
43+ if jsonStr :
44+ self ._processMetadata (jsonStr )
4545
4646 def _processMetadata (self , metadata ):
4747 '''
@@ -55,22 +55,24 @@ def _processMetadata(self, metadata):
5555 _components = defaultdict (set )
5656 # filters dictionary, per sensor, per (cluster or cluster_node) component
5757 _filters = defaultdict (list )
58+ # ordered dictionary to store filedLabel:fieldName pairs in order as they occur in metaStr
59+ _tags = OrderedDict ()
5860 # name of the (cluster or cluster_node) component
5961 label = metaStr .get ('fieldLabel' )
6062
6163 if label in self .__compTree .keys ():
6264 _components = self .__compTree [label ]['componentsMap' ]
6365 _filters = self .__compTree [label ]['filtersMap' ]
6466
65- self ._parse_topoJSONStr (self .__metricsDef , self .__levels , self .__ids , self .__groupKeys , _components , _filters , metaStr )
67+ self ._parse_topoJSONStr (self .__metricsDef , self .__metricsType , self . __levels , self .__ids , self .__groupKeys , _components , _filters , _tags , metaStr )
6668 tree_entry = {}
6769 tree_entry ['componentsMap' ] = _components
6870 tree_entry ['filtersMap' ] = _filters
6971
7072 # comp_tree[label] = tree_entry
7173 self .__compTree [label ] = tree_entry
7274
73- def _parse_topoJSONStr (self , metrics , levels , ids , groupKeys , components , filters , metaStr ):
75+ def _parse_topoJSONStr (self , metrics , metricsType , levels , ids , groupKeys , components , filters , _tags , metaStr ):
7476 '''
7577 This function parses the 'node' or 'attribute' object found in the given JSON string (metaStr) in
7678 the componets or metrics dictionary. Also the used metric filters (per sensor) will be stored
@@ -80,15 +82,24 @@ def _parse_topoJSONStr(self, metrics, levels, ids, groupKeys, components, filter
8082
8183 field_value = metaStr ['fieldLabel' ]
8284 field_name = metaStr ['fieldName' ]
85+ field_type = metaStr ['fieldSemantics' ]
8386
8487 # check if entity is a component
8588 if metaStr ['type' ] == 'node' :
89+ if field_name == "sensor" :
90+ # remove all partialKey tags from _tags dict except parent since we step in the new sensor level metaKey
91+ parent = _tags .popitem (last = False )
92+ _tags .clear ()
93+ _tags .update ([parent ])
94+ else :
95+ _tags [field_name ] = field_value
96+
8697 if field_value not in components [field_name ]:
8798 components [field_name ].add (field_value )
8899 # check if metaStr includes next level metaStr
89100 if 'keys' in metaStr and len (metaStr ['keys' ]) > 0 :
90101 for metaKey in metaStr ['keys' ]:
91- self ._parse_topoJSONStr (metrics , levels , ids , groupKeys , components , filters , metaKey )
102+ self ._parse_topoJSONStr (metrics , metricsType , levels , ids , groupKeys , components , filters , _tags , metaKey )
92103
93104 # check if entity is a metric
94105 elif metaStr ['type' ] == 'attribute' :
@@ -100,21 +111,22 @@ def _parse_topoJSONStr(self, metrics, levels, ids, groupKeys, components, filter
100111
101112 if field_name not in iterval (metrics [sensor ]):
102113 metrics [sensor ][field_id ] = field_name
114+ metricsType [field_name ] = field_type
103115
104116 if groupKey not in groupKeys :
105117 # parse sensor relevant data f.e. groupKey, filters, levels
106118 groupKeys [groupKey ] = len (groupKeys ) + 1
107- tags = {}
108- levTree = {}
109- for i , compValue in enumerate (partKey ):
110- for compLabel in components :
111- if compValue in components [compLabel ]:
112- levTree [i + 1 ] = compLabel
113- tags [compLabel ] = compValue
114- # if tags not in filters[sensor]:
115- # not needed as groupkeys check will allow this to be reached only once
116- filters [sensor ].append (tags )
119+ group_tags = copy .deepcopy (_tags )
120+
121+ # if not all((value in tags.values()) for value in partKey):
122+ # rint("different key values")
123+
124+ filters [sensor ].append (group_tags )
117125 if sensor not in levels :
126+ levTree = {}
127+ for i , tag_key in enumerate (group_tags .keys ()):
128+ levTree [i + 1 ] = tag_key
129+
118130 levels [sensor ] = levTree
119131
120132 # parse key id
@@ -177,6 +189,11 @@ def metricsSpec(self):
177189 ''' Returns all defined metrics as dictionary of (metric_name : metric_id) items '''
178190 return self .__metricsDef
179191
192+ @property
193+ def metricsType (self ):
194+ ''' Returns a dictionary of (metric_name : metric_type) items '''
195+ return self .__metricsType
196+
180197 @property
181198 def getAllEnabledMetricsNames (self ):
182199 ''' Returns list of all found metrics names'''
@@ -201,7 +218,7 @@ def getSensorForMetric(self, searchMetric):
201218 if (searchMetric .find ("(" ) >= 0 ):
202219 searchMetric = searchMetric [searchMetric .find ("(" ) + 1 :- 1 ]
203220 for sensor , metrics in self .__metricsDef .items ():
204- if searchMetric in metrics .values ():
221+ if searchMetric in set ( metrics .values () ):
205222 return sensor
206223 return None
207224
@@ -237,8 +254,11 @@ def getAllFilterMapsForSensor(self, searchSensor):
237254 based on metadata topology returned from zimon "topo".
238255 '''
239256 filtersMaps = []
240- if searchSensor in self .allFiltersMaps .keys ():
241- filtersMaps .extend (self .allFiltersMaps [searchSensor ])
257+ if searchSensor in set (self .sensorsSpec .keys ()):
258+ for entryName in self .__compTree .keys ():
259+ values = self .__compTree [entryName ]['filtersMap' ].get (searchSensor , [])
260+ if len (values ) > 0 :
261+ filtersMaps .extend (values )
242262 return filtersMaps
243263
244264 def getAllFilterMapsForMetric (self , searchMetric ):
@@ -274,13 +294,11 @@ def getAllFilterKeysForMetric(self, searchMetric):
274294 return keys
275295
276296 def getAllFilterKeysForSensor (self , searchSensor ):
277- keys = []
297+ filter_keys = set ()
278298 filtersMap = self .getAllFilterMapsForSensor (searchSensor )
279- for a in filtersMap :
280- keys .extend (list (a .keys ()))
281- if len (keys ) > 1 :
282- return list (set (keys ))
283- return keys
299+ for filter in filtersMap :
300+ filter_keys .update (filter .keys ())
301+ return list (filter_keys )
284302
285303 def getAllFilterKeysForMeasurementsMetrics (self , searchMetrics ):
286304 filterKeys = []
0 commit comments