I’ve been using the MicrosoftTeamsNotificationAction to notify my team about critical issues, and almost everything works perfectly. However, the images included in the webhook messages are not showing up in Teams.
I checked the webhook logs and noticed the following image URL was being sent:
"type": "ColumnSet",
"columns": [
{
"type": "Column",
"items": [
{
"type": "Image",
"url": "https://www.greatexpectations.io/image/gx-logo-mark-400",
"altText": "my_checkpoint",
"size": "small"
}
],
"width": "auto"
},
https://greatexpectations.io/image/gx-logo-mark-400
When trying to access the image directly, I encountered an error:
In the git repo you will find this setting in great_expectations/great_expectations/render/renderer/microsoft_teams_renderer.py at develop · great-expectations/great_expectations · GitHub
To troubleshoot this, I ran the following notebook code in Databricks.
%pip install great-expectations
# Import great_expectations and request a Data Context.
import great_expectations as gx
context = gx.get_context(mode="file")
# Optional. Request a File Data Context from a specific folder.
context = gx.get_context(mode="file", project_root_dir="./new_context_folder")
# Optional. Review the configuration of the returned File Data Context.
print(context)
context = gx.get_context(mode="file", project_root_dir="./new_context_folder")
# Define the Data Source name
data_source_name = "my_data_source"
# Add the Data Source to the Data Context
data_source = context.data_sources.add_pandas(name=data_source_name)
# Retrieve the Data Source
data_source_name = "my_data_source"
data_source = context.data_sources.get(data_source_name)
# Define the Data Asset name
data_asset_name = "my_dataframe_data_asset"
# Add a Data Asset to the Data Source
data_asset = data_source.add_dataframe_asset(name=data_asset_name)
# Retrieve the Data Asset
data_source_name = "my_data_source"
data_asset_name = "my_dataframe_data_asset"
data_asset = context.data_sources.get(data_source_name).get_asset(data_asset_name)
# Define the Batch Definition name
batch_definition_name = "my_batch_definition"
# Add a Batch Definition to the Data Asset
batch_definition = data_asset.add_batch_definition_whole_dataframe(
batch_definition_name
)
# Create an Expectation Suite
suite_name = "my_expectation_suite"
suite = gx.ExpectationSuite(name=suite_name)
# Add the Expectation Suite to the Data Context
suite = context.suites.add(suite)
# Create an Expectation to put into an Expectation Suite
expectation = gx.expectations.ExpectColumnValuesToNotBeNull(column="passenger_count")
# Add the previously created Expectation to the Expectation Suite
suite.add_expectation(expectation)
# Add another Expectation to the Expectation Suite.
suite.add_expectation(
gx.expectations.ExpectColumnValuesToNotBeNull(column="pickup_datetime")
)
# Update the configuration of an Expectation, then push the changes to the Expectation Suite
expectation.column = "pickup_location_id"
expectation.save()
# Retrieve an Expectation Suite from the Data Context
existing_suite_name = (
"my_expectation_suite" # replace this with the name of your Expectation Suite
)
suite = context.suites.get(name=existing_suite_name)
context = gx.get_context(mode="file", project_root_dir="./new_context_folder")
# Retrieve an Expectation Suite
expectation_suite_name = "my_expectation_suite"
expectation_suite = context.suites.get(name=expectation_suite_name)
# Retrieve a Batch Definition
data_source_name = "my_data_source"
data_asset_name = "my_dataframe_data_asset"
batch_definition_name = "my_batch_definition"
batch_definition = (
context.data_sources.get(data_source_name)
.get_asset(data_asset_name)
.get_batch_definition(batch_definition_name)
)
# Create a Validation Definition
definition_name = "my_validation_definition"
validation_definition = gx.ValidationDefinition(
data=batch_definition, suite=expectation_suite, name=definition_name
)
# Add the Validation Definition to the Data Context
validation_definition = context.validation_definitions.add(validation_definition)
import pandas as pd
# Retrieve the Validation Definition
validation_definition_name = "my_validation_definition"
validation_definition = context.validation_definitions.get(validation_definition_name)
# Define Batch parameters
df = pd.read_csv(
"https://raw.githubusercontent.com/great-expectations/gx_tutorials/main/data/yellow_tripdata_sample_2019-01.csv"
)
# Accepted keys are determined by the BatchDefinition used to instantiate this ValidationDefinition.
batch_parameters_dataframe = {"dataframe": df}
#batch_parameters_daily = {"year": "2020", "month": "1", "day": "17"}
#batch_parameters_yearly = {"year": "2019"}
# Run the Validation Definition
validation_results = validation_definition.run(batch_parameters=batch_parameters_dataframe)
# Review the Validation Results
print(validation_results)
import great_expectations as gx
from great_expectations.checkpoint import (
MicrosoftTeamsNotificationAction,
)
# Create a list of one or more Validation Definitions for the Checkpoint to run
validation_definitions = [
context.validation_definitions.get("my_validation_definition")
]
# Create a list of Actions for the Checkpoint to perform
action_list = [
# This Action sends a Slack Notification if an Expectation fails.
MicrosoftTeamsNotificationAction(
name="send_teams_notification_on_all_expectations",
teams_webhook="${webhook_url}",
notify_on="all",
# show_failed_expectations=True,
),
# This Action updates the Data Docs static website with the Validation
# Results after the Checkpoint is run.
# UpdateDataDocsAction(
# name="update_all_data_docs",
# ),
]
# Create the Checkpoint
checkpoint_name = "my_checkpoint"
checkpoint = gx.Checkpoint(
name=checkpoint_name,
validation_definitions=validation_definitions,
actions=action_list,
result_format={"result_format": "COMPLETE"},
)
# Save the Checkpoint to the Data Context
context.checkpoints.add(checkpoint)
# Retrieve the Checkpoint later
checkpoint_name = "my_checkpoint"
checkpoint = context.checkpoints.get(checkpoint_name)
import os
os.environ["webhook_url"] = "https://your-webhook-url"
checkpoint = context.checkpoints.get("my_checkpoint")
batch_parameters_dataframe = {"dataframe": df}
expectation_parameters = {
"expect_fare_max_to_be_above": 5.00,
"expect_fare_max_to_be_below": 1000.00,
}
validation_results = checkpoint.run(
batch_parameters=batch_parameters_dataframe, expectation_parameters=expectation_parameters
)
