Skip to content

Commit 448620c

Browse files
author
Keshav Chandak
committed
Fixed: Cron expression resetting on update monitor
1 parent 56fd6b2 commit 448620c

File tree

4 files changed

+67
-6
lines changed

4 files changed

+67
-6
lines changed

src/sagemaker/model_monitor/dataset_format.py

-2
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,6 @@ def csv(header=True):
7171
Args:
7272
header (bool): Whether the csv dataset to baseline and monitor has a header.
7373
Default: True.
74-
output_columns_position (str): The position of the output columns.
75-
Must be one of ("START", "END"). Default: "START".
7674
7775
Returns:
7876
dict: JSON string containing DatasetFormat to be used by DefaultModelMonitor.

src/sagemaker/model_monitor/model_monitoring.py

+15
Original file line numberDiff line numberDiff line change
@@ -2054,6 +2054,21 @@ def _update_data_quality_monitoring_schedule(
20542054
self._update_monitoring_schedule(self.job_definition_name, schedule_cron_expression)
20552055
return
20562056

2057+
existing_desc = self.sagemaker_session.describe_monitoring_schedule(
2058+
monitoring_schedule_name=self.monitoring_schedule_name
2059+
)
2060+
2061+
if (
2062+
existing_desc.get("MonitoringScheduleConfig") is not None
2063+
and existing_desc["MonitoringScheduleConfig"].get("ScheduleConfig") is not None
2064+
and existing_desc["MonitoringScheduleConfig"]["ScheduleConfig"]["ScheduleExpression"]
2065+
is not None
2066+
and schedule_cron_expression is None
2067+
):
2068+
schedule_cron_expression = existing_desc["MonitoringScheduleConfig"]["ScheduleConfig"][
2069+
"ScheduleExpression"
2070+
]
2071+
20572072
# Need to update schedule with a new job definition
20582073
job_desc = self.sagemaker_session.sagemaker_client.describe_data_quality_job_definition(
20592074
JobDefinitionName=self.job_definition_name

tests/integ/test_model_monitor.py

+47-1
Original file line numberDiff line numberDiff line change
@@ -802,6 +802,49 @@ def test_default_monitor_create_and_update_schedule_config_without_customization
802802
_wait_for_schedule_changes_to_apply(monitor=my_default_monitor)
803803

804804

805+
@pytest.mark.skipif(
806+
tests.integ.test_region() in tests.integ.NO_MODEL_MONITORING_REGIONS,
807+
reason="ModelMonitoring is not yet supported in this region.",
808+
)
809+
def test_default_monitor_create_and_simple_update_schedule_config(sagemaker_session, predictor):
810+
my_default_monitor = DefaultModelMonitor(role=ROLE, sagemaker_session=sagemaker_session)
811+
812+
my_default_monitor.create_monitoring_schedule(
813+
endpoint_input=predictor.endpoint_name,
814+
schedule_cron_expression=CronExpressionGenerator.hourly(),
815+
)
816+
817+
schedule_description = my_default_monitor.describe_schedule()
818+
_verify_default_monitoring_schedule(
819+
sagemaker_session=sagemaker_session,
820+
schedule_description=schedule_description,
821+
cron_expression=CronExpressionGenerator.hourly(),
822+
)
823+
824+
_wait_for_schedule_changes_to_apply(my_default_monitor)
825+
826+
my_default_monitor.update_monitoring_schedule(
827+
max_runtime_in_seconds=UPDATED_MAX_RUNTIME_IN_SECONDS
828+
)
829+
830+
_wait_for_schedule_changes_to_apply(my_default_monitor)
831+
832+
schedule_description = my_default_monitor.describe_schedule()
833+
834+
_verify_default_monitoring_schedule(
835+
sagemaker_session=sagemaker_session,
836+
schedule_description=schedule_description,
837+
cron_expression=CronExpressionGenerator.hourly(),
838+
max_runtime_in_seconds=UPDATED_MAX_RUNTIME_IN_SECONDS,
839+
)
840+
841+
_wait_for_schedule_changes_to_apply(monitor=my_default_monitor)
842+
843+
my_default_monitor.stop_monitoring_schedule()
844+
845+
_wait_for_schedule_changes_to_apply(monitor=my_default_monitor)
846+
847+
805848
@pytest.mark.skipif(
806849
tests.integ.test_region() in tests.integ.NO_MODEL_MONITORING_REGIONS,
807850
reason="ModelMonitoring is not yet supported in this region.",
@@ -1644,7 +1687,10 @@ def _verify_default_monitoring_schedule(
16441687
schedule_description["MonitoringScheduleConfig"]["ScheduleConfig"]["ScheduleExpression"]
16451688
== cron_expression
16461689
)
1647-
assert schedule_description["MonitoringType"] == "DataQuality"
1690+
if schedule_description.get("MonitoringType") is not None:
1691+
assert schedule_description["MonitoringType"] == "DataQuality"
1692+
else:
1693+
assert schedule_description["MonitoringScheduleConfig"]["MonitoringType"] == "DataQuality"
16481694
job_definition_name = schedule_description["MonitoringScheduleConfig"].get(
16491695
"MonitoringJobDefinitionName"
16501696
)

tests/unit/sagemaker/monitor/test_model_monitoring.py

+5-3
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@
6565
PROBLEM_TYPE = "Regression"
6666
GROUND_TRUTH_ATTRIBUTE = "TestAttribute"
6767

68-
68+
CRON_DAILY = CronExpressionGenerator.daily()
6969
BASELINING_JOB_NAME = "baselining-job"
7070
BASELINE_DATASET_PATH = "/my/local/path/baseline.csv"
7171
PREPROCESSOR_PATH = "/my/local/path/preprocessor.py"
@@ -84,7 +84,9 @@
8484
MONITORING_SCHEDULE_DESC = {
8585
"MonitoringScheduleArn": "arn:aws:monitoring-schedule",
8686
"MonitoringScheduleName": "my-monitoring-schedule",
87+
"MonitoringScheduleStatus": "Completed",
8788
"MonitoringScheduleConfig": {
89+
"ScheduleExpression": CRON_DAILY,
8890
"MonitoringJobDefinition": {
8991
"MonitoringOutputConfig": {},
9092
"MonitoringResources": {
@@ -101,7 +103,7 @@
101103
],
102104
},
103105
"RoleArn": ROLE,
104-
}
106+
},
105107
},
106108
"EndpointName": "my-endpoint",
107109
}
@@ -282,7 +284,6 @@
282284
security_group_ids=NEW_SECURITY_GROUP_IDS,
283285
subnets=NEW_SUBNETS,
284286
)
285-
CRON_DAILY = CronExpressionGenerator.daily()
286287
NEW_ENDPOINT_NAME = "new-endpoint"
287288
NEW_GROUND_TRUTH_S3_URI = "s3://bucket/monitoring_captured/groundtruth"
288289
NEW_START_TIME_OFFSET = "-PT2H"
@@ -858,6 +859,7 @@ def _test_data_quality_monitor_update_schedule(data_quality_monitor, sagemaker_s
858859
)
859860
sagemaker_session.sagemaker_client.create_data_quality_job_definition = Mock()
860861
sagemaker_session.expand_role = Mock(return_value=NEW_ROLE_ARN)
862+
sagemaker_session.describe_monitoring_schedule = Mock(return_value=MONITORING_SCHEDULE_DESC)
861863
old_job_definition_name = data_quality_monitor.job_definition_name
862864
data_quality_monitor.update_monitoring_schedule(role=NEW_ROLE_ARN)
863865
expected_arguments = {

0 commit comments

Comments
 (0)