1
+ import json
2
+
3
+ class Variable :
4
+ def __init__ (self , variable_type , variable_property , inputType , id , label , search , populateFrom ):
5
+ self .variable_type = variable_type
6
+ self .variable_property = variable_property
7
+ self .inputType = inputType
8
+ self .id = id
9
+ self .label = label
10
+ self .search = search
11
+ self .populateFrom = populateFrom
12
+
13
+ def to_dict (self ):
14
+ variable_properties_dict = {}
15
+ if self .variable_type != None :
16
+ variable_properties_dict ["type" ] = self .variable_type
17
+ if self .variable_property != None :
18
+ variable_properties_dict ["property" ] = self .variable_property
19
+ if self .inputType != None :
20
+ variable_properties_dict ["inputType" ] = self .inputType
21
+ if self .id != None :
22
+ variable_properties_dict ["id" ] = self .id
23
+ if self .label != None :
24
+ variable_properties_dict ["label" ] = self .label
25
+ if self .search != None :
26
+ variable_properties_dict ["search" ] = self .search
27
+ if self .populateFrom != None :
28
+ variable_properties_dict ["populateFrom" ] = self .populateFrom
29
+ return variable_properties_dict
30
+
31
+ def to_json (self ):
32
+ json .dumps (self .to_dict (), indent = 4 )
33
+
34
+ class WidgetProperties :
35
+ def __init__ (self , view = None , stacked = None , metrics = None , region = None , period = None , title = None , markdown = None ):
36
+ self .view = view
37
+ self .stacked = stacked
38
+ self .metrics = metrics
39
+ self .region = region
40
+ self .period = period
41
+ self .title = title
42
+ self .markdown = markdown
43
+
44
+ def to_dict (self ):
45
+ widget_properties_dict = {}
46
+ if self .view != None :
47
+ widget_properties_dict ["view" ] = self .view
48
+ if self .period != None :
49
+ widget_properties_dict ["period" ] = self .period
50
+ if self .markdown != None :
51
+ widget_properties_dict ["markdown" ] = self .markdown
52
+ if self .stacked != None :
53
+ widget_properties_dict ["stacked" ] = self .stacked
54
+ if self .region != None :
55
+ widget_properties_dict ["region" ] = self .region
56
+ if self .metrics != None :
57
+ widget_properties_dict ["metrics" ] = self .metrics
58
+ if self .title != None :
59
+ widget_properties_dict ["title" ] = self .title
60
+ return widget_properties_dict
61
+
62
+ def to_json (self ):
63
+ json .dumps (self .to_dict (), indent = 4 )
64
+
65
+ class Widget :
66
+ def __init__ (self , height , width , widget_type , properties = None ):
67
+ self .height = height
68
+ self .width = width
69
+ self .type = widget_type
70
+ self .properties = properties if properties else WidgetProperties (None , False , [], None , None , None )
71
+
72
+ def to_dict (self ):
73
+ return {
74
+ "height" : self .height ,
75
+ "width" : self .width ,
76
+ "type" : self .type ,
77
+ "properties" : self .properties .to_dict ()
78
+ }
79
+
80
+ def to_json (self ):
81
+ return json .dumps (self .to_dict (), indent = 4 )
82
+
83
+ class AutomaticDataQualityDashboard :
84
+ DATA_QUALITY_METRICS_ENDPOINT_NAMESPACE = "{aws/sagemaker/Endpoints/data-metrics,Endpoint,Feature,MonitoringSchedule}"
85
+ DATA_QUALITY_METRICS_BATCH_NAMESPACE = "{aws/sagemaker/ModelMonitoring/data-metrics,Feature,MonitoringSchedule}"
86
+
87
+ def __init__ (self , endpoint_name , monitoring_schedule_name , batch_transform_input , region_name ):
88
+ self .endpoint = endpoint_name
89
+ self .monitoring_schedule = monitoring_schedule_name
90
+ self .batch_transform = batch_transform_input
91
+ self .region = region_name
92
+
93
+ variables = self ._generate_variables ()
94
+ type_counts_widget = self ._generate_type_counts_widget ()
95
+ null_counts_widget = self ._generate_null_counts_widget ()
96
+ estimated_unique_values_widget = self ._generate_estimated_unique_values_widget ()
97
+ completeness_widget = self ._generate_completeness_widget ()
98
+ baseline_drift_widget = self ._generate_baseline_drift_widget ()
99
+
100
+ self .dashboard = {"variables" : variables , "widgets" : [type_counts_widget , null_counts_widget , estimated_unique_values_widget , completeness_widget , baseline_drift_widget ]}
101
+
102
+ def _generate_variables (self ):
103
+ if self .batch_transform :
104
+ return [Variable (variable_type = "property" ,
105
+ variable_property = "Feature" ,
106
+ inputType = "select" ,
107
+ id = "Feature" ,
108
+ label = "Feature" ,
109
+ search = AutomaticDataQualityDashboard .DATA_QUALITY_METRICS_BATCH_NAMESPACE ,
110
+ populateFrom = "Feature" )]
111
+ else :
112
+ return [Variable (variable_type = "property" ,
113
+ variable_property = "Feature" ,
114
+ inputType = "select" ,
115
+ id = "Feature" ,
116
+ label = "Feature" ,
117
+ search = AutomaticDataQualityDashboard .DATA_QUALITY_METRICS_ENDPOINT_NAMESPACE ,
118
+ populateFrom = "Feature" )]
119
+
120
+ def _generate_type_counts_widget (self ):
121
+ if self .batch_transform :
122
+ type_counts_widget_properties = WidgetProperties (view = "timeSeries" ,
123
+ stacked = False ,
124
+ metrics = [[{ "expression" : f"SEARCH( '{ AutomaticDataQualityDashboard .DATA_QUALITY_METRICS_BATCH_NAMESPACE } feature_(fractional OR boolean OR integral OR string OR unknown)_counts_ Feature=\" _\" MonitoringSchedule=\" { self .monitoring_schedule } \" ', 'Average')" }]],
125
+ region = self .region ,
126
+ title = "Type Counts" )
127
+ else :
128
+ type_counts_widget_properties = WidgetProperties (view = "timeSeries" ,
129
+ stacked = False ,
130
+ metrics = [[{ "expression" : f"SEARCH( '{ AutomaticDataQualityDashboard .DATA_QUALITY_METRICS_ENDPOINT_NAMESPACE } feature_(fractional OR boolean OR integral OR string OR unknown)_counts_ Endpoint=\" { self .endpoint } \" Feature=\" _\" MonitoringSchedule=\" { self .monitoring_schedule } \" ', 'Average')" }]],
131
+ region = self .region ,
132
+ title = "Type Counts" )
133
+ return Widget (height = 8 , width = 12 , widget_type = "metric" , properties = type_counts_widget_properties )
134
+
135
+ def _generate_null_counts_widget (self ):
136
+ if self .batch_transform :
137
+ null_counts_widget_properties = WidgetProperties (view = "timeSeries" ,
138
+ stacked = False ,
139
+ metrics = [[{ "expression" : f"SEARCH( '{ AutomaticDataQualityDashboard .DATA_QUALITY_METRICS_BATCH_NAMESPACE } feature_null_ OR feature_non_null_ Feature=\" _\" MonitoringSchedule=\" { self .monitoring_schedule } \" ', 'Average')" }]],
140
+ region = self .region ,
141
+ title = "Missing Data Counts" )
142
+ else :
143
+ null_counts_widget_properties = WidgetProperties (view = "timeSeries" ,
144
+ stacked = False ,
145
+ metrics = [[{ "expression" : f"SEARCH( '{ AutomaticDataQualityDashboard .DATA_QUALITY_METRICS_ENDPOINT_NAMESPACE } feature_null_ OR feature_non_null_ Endpoint=\" { self .endpoint } \" Feature=\" _\" MonitoringSchedule=\" { self .monitoring_schedule } \" ', 'Average')" }]],
146
+ region = self .region ,
147
+ title = "Missing Data Counts" )
148
+ return Widget (height = 8 , width = 12 , widget_type = "metric" , properties = null_counts_widget_properties )
149
+
150
+ def _generate_estimated_unique_values_widget (self ):
151
+ if self .batch_transform :
152
+ estimated_unique_vals_widget_properties = WidgetProperties (view = "timeSeries" ,
153
+ stacked = False ,
154
+ metrics = [[{ "expression" : f"SEARCH( '{ AutomaticDataQualityDashboard .DATA_QUALITY_METRICS_BATCH_NAMESPACE } feature_estimated_unique_values_ Feature=\" _\" MonitoringSchedule=\" { self .monitoring_schedule } \" ', 'Average')" }]],
155
+ region = self .region ,
156
+ title = "Estimated Unique Values" )
157
+ else :
158
+ estimated_unique_vals_widget_properties = WidgetProperties (view = "timeSeries" ,
159
+ stacked = False ,
160
+ metrics = [[{ "expression" : f"SEARCH( '{ AutomaticDataQualityDashboard .DATA_QUALITY_METRICS_ENDPOINT_NAMESPACE } feature_estimated_unique_values_ Endpoint=\" { self .endpoint } \" Feature=\" _\" MonitoringSchedule=\" { self .monitoring_schedule } \" ', 'Average')" }]],
161
+ region = self .region ,
162
+ title = "Estimated Unique Values" )
163
+
164
+ return Widget (height = 8 , width = 12 , widget_type = "metric" , properties = estimated_unique_vals_widget_properties )
165
+
166
+ def _generate_completeness_widget (self ):
167
+ if self .batch_transform :
168
+ completeness_widget_properties = WidgetProperties (view = "timeSeries" ,
169
+ stacked = False ,
170
+ metrics = [[{ "expression" : f"SEARCH( '{ AutomaticDataQualityDashboard .DATA_QUALITY_METRICS_BATCH_NAMESPACE } feature_completeness_ Feature=\" _\" MonitoringSchedule=\" { self .monitoring_schedule } \" ', 'Average')" }]],
171
+ region = self .region ,
172
+ title = "Completeness" )
173
+ else :
174
+ completeness_widget_properties = WidgetProperties (view = "timeSeries" ,
175
+ stacked = False ,
176
+ metrics = [[{ "expression" : f"SEARCH( '{ AutomaticDataQualityDashboard .DATA_QUALITY_METRICS_ENDPOINT_NAMESPACE } feature_completeness_ Endpoint=\" { self .endpoint } \" Feature=\" _\" MonitoringSchedule=\" { self .monitoring_schedule } \" ', 'Average')" }]],
177
+ region = self .region ,
178
+ title = "Completeness" )
179
+ return Widget (height = 8 , width = 12 , widget_type = "metric" , properties = completeness_widget_properties )
180
+
181
+ def _generate_baseline_drift_widget (self ):
182
+ if self .batch_transform :
183
+ baseline_drift_widget_properties = WidgetProperties (view = "timeSeries" ,
184
+ stacked = False ,
185
+ metrics = [[{ "expression" : f"SEARCH( '{ AutomaticDataQualityDashboard .DATA_QUALITY_METRICS_BATCH_NAMESPACE } feature_baseline_drift_ Feature=\" _\" MonitoringSchedule=\" { self .monitoring_schedule } \" ', 'Average')" }]],
186
+ region = self .region ,
187
+ title = "Baseline Drift" )
188
+ else :
189
+ baseline_drift_widget_properties = WidgetProperties (view = "timeSeries" ,
190
+ stacked = False ,
191
+ metrics = [[{ "expression" : f"SEARCH( '{ AutomaticDataQualityDashboard .DATA_QUALITY_METRICS_ENDPOINT_NAMESPACE } feature_baseline_drift_ Endpoint=\" { self .endpoint } \" Feature=\" _\" MonitoringSchedule=\" { self .monitoring_schedule } \" ', 'Average')" }]],
192
+ region = self .region ,
193
+ title = "Baseline Drift" )
194
+ return Widget (height = 8 , width = 12 , widget_type = "metric" , properties = baseline_drift_widget_properties )
195
+
196
+ def to_dict (self ):
197
+ return {"variables" : [var .to_dict () for var in self .dashboard ["variables" ]], "widgets" : [widget .to_dict () for widget in self .dashboard ["widgets" ]]}
198
+
199
+ def to_json (self ):
200
+ return json .dumps (self .to_dict (), indent = 4 )
201
+
202
+ # # The above code is a Python script that uses the boto3 library to interact with AWS CloudWatch
203
+ # service. It seems to be related to creating and managing CloudWatch dashboards.
204
+ import boto3
205
+ # dashboard_body = AutomaticDataQualityDashboard("DEMO-xgb-churn-pred-model-monitor-2024-07-09-17-54-38", "DEMO-xgb-churn-pred-model-monitor-schedule-2024-07-09-18-30-14", None, "us-west-2").to_json()
206
+ # print(dashboard_body)
207
+ # response = boto3.client('cloudwatch').put_dashboard(
208
+ # DashboardName="New",
209
+ # DashboardBody=dashboard_body
210
+ # )
211
+ # print(response)
212
+
213
+
214
+ # resp = boto3.client('cloudwatch').get_dashboard(DashboardName="Old")
215
+ # print(resp)
0 commit comments