@@ -44,6 +44,118 @@ def templating(self) -> List:
44
44
return self .dashboard .dashboard .get ("templating" , {}).get ("list" , [])
45
45
46
46
47
+ @dataclasses .dataclass
48
+ class DashboardDataDetails :
49
+ """
50
+ Manage details concerned about "data"-relevant information,
51
+ a subset of the complete bunch of dashboard information.
52
+ """
53
+
54
+ panels : List [Dict ]
55
+ annotations : List [Dict ]
56
+ templating : List [Dict ]
57
+
58
+ def to_munch (self ):
59
+ return Munch (panels = self .panels , annotations = self .annotations , templating = self .templating )
60
+
61
+ @classmethod
62
+ def from_dashboard_details (cls , dbdetails : DashboardDetails ):
63
+ ds_panels = cls .collect_data_nodes (dbdetails .panels )
64
+ ds_annotations = cls .collect_data_nodes (dbdetails .annotations )
65
+ ds_templating = cls .collect_data_nodes (dbdetails .templating )
66
+
67
+ # Inline panel information into data details.
68
+ targets = []
69
+ for panel in ds_panels :
70
+ panel_item = cls ._format_panel_compact (panel )
71
+ if "targets" in panel :
72
+ for target in panel .targets :
73
+ target ["_panel" ] = panel_item
74
+ targets .append (target )
75
+
76
+ return cls (panels = targets , annotations = ds_annotations , templating = ds_templating )
77
+
78
+ @staticmethod
79
+ def collect_data_nodes (element ):
80
+ """
81
+ Select all element nodes which have a "datasource" attribute.
82
+ """
83
+ element = element or []
84
+ items = []
85
+
86
+ def add (item ):
87
+ if item is not None and item not in items :
88
+ items .append (item )
89
+
90
+ for node in element :
91
+ if "datasource" in node and node ["datasource" ]:
92
+ add (node )
93
+
94
+ return items
95
+
96
+ @staticmethod
97
+ def _format_panel_compact (panel ):
98
+ """
99
+ Return a compact representation of panel information.
100
+ """
101
+ attributes = ["id" , "title" , "type" , "datasource" ]
102
+ data = OrderedDict ()
103
+ for attribute in attributes :
104
+ data [attribute ] = panel .get (attribute )
105
+ return data
106
+
107
+ @staticmethod
108
+ def _format_data_node_compact (item : Dict ) -> Dict :
109
+ """
110
+ Return a compact representation of an element concerned about data.
111
+ """
112
+ data = OrderedDict ()
113
+ data ["datasource" ] = item .get ("datasource" )
114
+ data ["type" ] = item .get ("type" )
115
+ for key , value in item .items ():
116
+ if "query" in key .lower ():
117
+ data [key ] = value
118
+ return data
119
+
120
+ def queries_only (self ):
121
+ """
122
+ Return a representation of data details information, only where query expressions are present.
123
+ """
124
+ # All attributes containing query-likes.
125
+ attributes_query_likes = ["expr" , "jql" , "query" , "rawSql" , "target" ]
126
+
127
+ attributes = [
128
+ # Carry over datasource and panel references for informational purposes.
129
+ "datasource" ,
130
+ "_panel" ,
131
+ ] + attributes_query_likes
132
+
133
+ def transform (section ):
134
+ new_items = []
135
+ for item in section :
136
+ new_item = OrderedDict ()
137
+ for key , value in item .items ():
138
+ if key in attributes :
139
+ new_item [key ] = value
140
+ if any (attr in attributes_query_likes for attr in new_item .keys ()):
141
+ # Filter annotations without any value.
142
+ if "target" in new_item and isinstance (new_item ["target" ], dict ):
143
+ if new_item ["target" ].get ("type" ) == "dashboard" :
144
+ continue
145
+ # Unnest items with nested "query" slot.
146
+ for slot in ["query" , "target" ]:
147
+ if slot in new_item and isinstance (new_item [slot ], dict ) and "query" in new_item [slot ]:
148
+ new_item ["query" ] = new_item [slot ]["query" ]
149
+ new_items .append (new_item )
150
+ return new_items
151
+
152
+ return DashboardDataDetails (
153
+ panels = transform (self .panels ),
154
+ annotations = transform (self .annotations ),
155
+ templating = transform (self .templating ),
156
+ )
157
+
158
+
47
159
@dataclasses .dataclass
48
160
class DatasourceItem :
49
161
uid : Optional [str ] = None
@@ -94,7 +206,7 @@ class DashboardExplorationItem:
94
206
datasources : List [Munch ]
95
207
grafana_url : str
96
208
97
- def format (self , with_data_details : bool = False ):
209
+ def format (self , with_data_details : bool = False , queries_only : bool = False ):
98
210
"""
99
211
Generate a representation from selected information.
100
212
@@ -124,70 +236,19 @@ def format(self, with_data_details: bool = False):
124
236
125
237
data = Munch (dashboard = dbshort , datasources = dsshort )
126
238
if with_data_details :
127
- data .details = self .collect_data_details ()
239
+ details = self .collect_data_details (queries_only = queries_only )
240
+ if not details .panels and not details .annotations and not details .templating :
241
+ return None
242
+ data .details = details .to_munch ()
128
243
return data
129
244
130
- def collect_data_details (self ):
245
+ def collect_data_details (self , queries_only : bool = False ):
131
246
"""
132
247
Collect details concerned about data from dashboard information.
133
248
"""
134
249
135
250
dbdetails = DashboardDetails (dashboard = self .dashboard )
136
-
137
- ds_panels = self .collect_data_nodes (dbdetails .panels )
138
- ds_annotations = self .collect_data_nodes (dbdetails .annotations )
139
- ds_templating = self .collect_data_nodes (dbdetails .templating )
140
-
141
- targets = []
142
- for panel in ds_panels :
143
- panel_item = self ._format_panel_compact (panel )
144
- if "targets" in panel :
145
- for target in panel .targets :
146
- target ["_panel" ] = panel_item
147
- targets .append (target )
148
-
149
- response = OrderedDict (targets = targets , annotations = ds_annotations , templating = ds_templating )
150
-
151
- return response
152
-
153
- @staticmethod
154
- def collect_data_nodes (element ):
155
- """
156
- Select all element nodes which have a "datasource" attribute.
157
- """
158
- element = element or []
159
- items = []
160
-
161
- def add (item ):
162
- if item is not None and item not in items :
163
- items .append (item )
164
-
165
- for node in element :
166
- if "datasource" in node and node ["datasource" ]:
167
- add (node )
168
-
169
- return items
170
-
171
- @staticmethod
172
- def _format_panel_compact (panel ):
173
- """
174
- Return a compact representation of panel information.
175
- """
176
- attributes = ["id" , "title" , "type" , "datasource" ]
177
- data = OrderedDict ()
178
- for attribute in attributes :
179
- data [attribute ] = panel .get (attribute )
180
- return data
181
-
182
- @staticmethod
183
- def _format_data_node_compact (item : Dict ) -> Dict :
184
- """
185
- Return a compact representation of an element concerned about data.
186
- """
187
- data = OrderedDict ()
188
- data ["datasource" ] = item .get ("datasource" )
189
- data ["type" ] = item .get ("type" )
190
- for key , value in item .items ():
191
- if "query" in key .lower ():
192
- data [key ] = value
193
- return data
251
+ dbdatadetails = DashboardDataDetails .from_dashboard_details (dbdetails )
252
+ if queries_only :
253
+ dbdatadetails = dbdatadetails .queries_only ()
254
+ return dbdatadetails
0 commit comments