-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[MAINTENANCE] Migrate OpsgenieNotificationAction
#9716
Changes from all commits
3cfa163
ff1a51d
e6046bf
be19100
49f101a
9d92d07
2e4d4db
d5f3b4f
be9d6d1
a833779
f78ddcb
7ceb94d
0321d54
69dd70c
4e78e41
0f9b525
df7c87c
bf93776
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -96,6 +96,7 @@ | |
json_encoders = {Renderer: lambda r: r.serialize()} | ||
|
||
type: str | ||
notify_on: Literal["all", "failure", "success"] = "all" | ||
|
||
@property | ||
def _using_cloud_context(self) -> bool: | ||
|
@@ -164,6 +165,15 @@ | |
def v1_run(self, checkpoint_result: CheckpointResult) -> str | dict: | ||
raise NotImplementedError | ||
|
||
def _is_enabled(self, success: bool) -> bool: | ||
return ( | ||
self.notify_on == "all" | ||
or self.notify_on == "success" | ||
and success | ||
or self.notify_on == "failure" | ||
and not success | ||
) | ||
|
||
|
||
class DataDocsAction(ValidationAction): | ||
def _build_data_docs( | ||
|
@@ -326,13 +336,7 @@ | |
payload["store_validation_result"]["validation_result_url"] | ||
) | ||
result = {"slack_notification_result": "none required"} | ||
if ( | ||
self.notify_on == "all" | ||
or self.notify_on == "success" | ||
and validation_success | ||
or self.notify_on == "failure" | ||
and not validation_success | ||
): | ||
if self._is_enabled(success=validation_success): | ||
query: Dict = self.renderer.render( | ||
validation_result_suite, | ||
data_docs_pages, | ||
|
@@ -451,13 +455,7 @@ | |
) | ||
|
||
def _run_pypd_alert(self, dedup_key: str, message: str, success: bool): | ||
if ( | ||
self.notify_on == "all" | ||
or self.notify_on == "success" | ||
and success | ||
or self.notify_on == "failure" | ||
and not success | ||
): | ||
if self._is_enabled(success=success): | ||
pypd.api_key = self.api_key | ||
pypd.EventV2.create( | ||
data={ | ||
|
@@ -560,13 +558,7 @@ | |
if payload[action_names]["class"] == "UpdateDataDocsAction": | ||
data_docs_pages = payload[action_names] | ||
|
||
if ( | ||
self.notify_on == "all" | ||
or self.notify_on == "success" | ||
and validation_success | ||
or self.notify_on == "failure" | ||
and not validation_success | ||
): | ||
if self._is_enabled(success=validation_success): | ||
query = self.renderer.render( | ||
validation_result_suite, | ||
validation_result_suite_identifier, | ||
|
@@ -625,6 +617,35 @@ | |
renderer = _renderer | ||
return renderer | ||
|
||
@override | ||
def v1_run(self, checkpoint_result: CheckpointResult) -> dict: | ||
validation_success = checkpoint_result.success or False | ||
checkpoint_name = checkpoint_result.checkpoint_config.name | ||
|
||
if self._is_enabled(success=validation_success): | ||
settings = { | ||
"api_key": self.api_key, | ||
"region": self.region, | ||
"priority": self.priority, | ||
"tags": self.tags, | ||
} | ||
|
||
description = self.renderer.v1_render(checkpoint_result=checkpoint_result) | ||
|
||
message = f"Great Expectations Checkpoint {checkpoint_name} " | ||
if checkpoint_result.success: | ||
message += "succeeded!" | ||
else: | ||
message += "failed!" | ||
|
||
alert_result = send_opsgenie_alert( | ||
query=description, message=message, settings=settings | ||
) | ||
|
||
return {"opsgenie_alert_result": alert_result} | ||
else: | ||
return {"opsgenie_alert_result": "No alert sent"} | ||
|
||
@override | ||
def _run( # type: ignore[override] # signature does not match parent # noqa: PLR0913 | ||
self, | ||
|
@@ -653,13 +674,7 @@ | |
|
||
validation_success = validation_result_suite.success | ||
|
||
if ( | ||
self.notify_on == "all" | ||
or self.notify_on == "success" | ||
and validation_success | ||
or self.notify_on == "failure" | ||
and not validation_success | ||
): | ||
if self._is_enabled(success=validation_success): | ||
expectation_suite_name = validation_result_suite.meta.get( | ||
"expectation_suite_name", "__no_expectation_suite_name__" | ||
) | ||
|
@@ -673,7 +688,8 @@ | |
|
||
description = self.renderer.render(validation_result_suite, None, None) | ||
|
||
alert_result = send_opsgenie_alert(description, expectation_suite_name, settings) | ||
message = f"Great Expectations suite {expectation_suite_name} failed" | ||
alert_result = send_opsgenie_alert(description, message, settings) | ||
|
||
return {"opsgenie_alert_result": alert_result} | ||
else: | ||
|
@@ -806,11 +822,7 @@ | |
if payload[action_names]["class"] == "UpdateDataDocsAction": | ||
data_docs_pages = payload[action_names] | ||
|
||
if ( | ||
(self.notify_on == "all") | ||
or (self.notify_on == "success" and validation_success) | ||
or (self.notify_on == "failure" and not validation_success) | ||
): | ||
if self._is_enabled(success=validation_success): | ||
title, html = self.renderer.render( | ||
validation_result_suite, data_docs_pages, self.notify_with | ||
) | ||
|
@@ -1116,19 +1128,8 @@ | |
checkpoint_identifier=None, | ||
**kwargs, | ||
): | ||
suite_name: str = validation_result_suite.meta["expectation_suite_name"] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm confused on this change. This is a separate action, right? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yup but There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Probably because of the change to |
||
if "batch_kwargs" in validation_result_suite.meta: | ||
data_asset_name = validation_result_suite.meta["batch_kwargs"].get( | ||
"data_asset_name", "__no_data_asset_name__" | ||
) | ||
elif "active_batch_definition" in validation_result_suite.meta: | ||
data_asset_name = ( | ||
validation_result_suite.meta["active_batch_definition"].data_asset_name | ||
if validation_result_suite.meta["active_batch_definition"].data_asset_name | ||
else "__no_data_asset_name__" | ||
) | ||
else: | ||
data_asset_name = "__no_data_asset_name__" | ||
suite_name: str = validation_result_suite.suite_name | ||
data_asset_name: str = validation_result_suite.asset_name or "__no_data_asset_name__" | ||
|
||
validation_results: list = validation_result_suite.results | ||
validation_results_serializable: list = convert_to_json_serializable(validation_results) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -288,10 +288,10 @@ | |
"expectation_suite_names": [expectation_suite_name], | ||
} | ||
else: | ||
assets_validated_by_batch_id[batch_id]["validation_results"].append( | ||
assets_validated_by_batch_id[batch_id]["validation_results"].append( # type: ignore[union-attr] | ||
validation_result | ||
) | ||
assets_validated_by_batch_id[batch_id]["expectation_suite_names"].append( | ||
assets_validated_by_batch_id[batch_id]["expectation_suite_names"].append( # type: ignore[union-attr] | ||
Comment on lines
+291
to
+294
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the old checkpoint result (not sure why mypy is mad about it now). We're using a new Pydantic type so I think we can ignore these? |
||
expectation_suite_name | ||
) | ||
self._data_assets_validated_by_batch_id = assets_validated_by_batch_id | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -514,7 +514,7 @@ | |
suite_name: str, | ||
evaluation_parameters: Optional[dict] = None, | ||
statistics: Optional[dict] = None, | ||
meta: Optional[ExpectationSuiteValidationResult | dict] = None, | ||
meta: Optional[ExpectationSuiteValidationResultMeta | dict] = None, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This has been wrong for a while (thank you @tyler-hoffman for pointing it out). Some minor changes in this PR to adhere to the proper type |
||
batch_id: Optional[str] = None, | ||
result_url: Optional[str] = None, | ||
id: Optional[str] = None, | ||
|
@@ -532,6 +532,12 @@ | |
self.id = id | ||
self._metrics: dict = {} | ||
|
||
@property | ||
def asset_name(self) -> str | None: | ||
if "active_batch_definition" in self.meta: | ||
return self.meta["active_batch_definition"].data_asset_name | ||
return None | ||
Comment on lines
+535
to
+539
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would like to make this a top-level property (might write a ticket around it) but not pressing |
||
|
||
def __eq__(self, other): | ||
"""ExpectationSuiteValidationResult equality ignores instance identity, relying only on properties.""" # noqa: E501 | ||
if not isinstance(other, self.__class__): | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lots of overlap with
_run
. I might DRY this up, but if we can remove_run
in the near term, I'm less stressed about it.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Legacy
_run
will be removed shortly!