Merge pull request #323 from grafana/167-slack-notification-not-displaying

Fix slack notifications not displaying properly
This commit is contained in:
Ildar Iskhakov 2022-08-23 18:03:12 +03:00 committed by GitHub
commit 762c681ebf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 108 additions and 92 deletions

View file

@ -30,13 +30,34 @@ def call_ack_url(ack_url, alert_group_pk, channel, http_method="GET"):
else None
)
text = "{}".format(debug_message)
footer = "{}".format(info_message)
blocks = [
{
"type": "section",
"block_id": "alert",
"text": {
"type": "mrkdwn",
"text": text,
},
},
{"type": "divider"},
{
"type": "section",
"block_id": "alert",
"text": {
"type": "mrkdwn",
"text": footer,
},
},
]
if channel is not None:
result = sc.api_call(
"chat.postMessage",
channel=channel,
attachments=[
{"callback_id": "alert", "text": "{}".format(debug_message), "footer": "{}".format(info_message)},
],
text=text,
blocks=blocks,
thread_ts=alert_group.slack_message.slack_id,
mrkdwn=True,
)

View file

@ -137,8 +137,15 @@ class SlackMessage(models.Model):
else:
text = "{}\nInviting {} to look at incident.".format(alert_group.long_verbose_name, user_verbal)
attachments = [
{"color": "#c6c000", "callback_id": "alert", "text": text}, # yellow
blocks = [
{
"type": "section",
"block_id": "alert",
"text": {
"type": "mrkdwn",
"text": text,
},
}
]
sc = SlackClientWithErrorHandling(self.slack_team_identity.bot_access_token)
channel_id = slack_message.channel_id
@ -147,7 +154,8 @@ class SlackMessage(models.Model):
result = sc.api_call(
"chat.postMessage",
channel=channel_id,
attachments=attachments,
text=text,
blocks=blocks,
thread_ts=slack_message.slack_id,
unfurl_links=True,
)

View file

@ -192,6 +192,7 @@ class AlertShootingStep(scenario_step.ScenarioStep):
self._slack_client.api_call(
"chat.postMessage",
channel=channel_id,
text=text,
attachments=[],
thread_ts=alert_group.slack_message.slack_id,
mrkdwn=True,
@ -480,10 +481,8 @@ class AttachGroupStep(
alert_group = log_record.alert_group
if log_record.type == AlertGroupLogRecord.TYPE_ATTACHED and log_record.alert_group.is_maintenance_incident:
attachments = [
{"callback_id": "alert", "text": "{}".format(log_record.rendered_log_line_action(for_slack=True))},
]
self._publish_message_to_thread(alert_group, attachments)
text = f"{log_record.rendered_log_line_action(for_slack=True)}"
self.publish_message_to_thread(alert_group, text=text)
if log_record.type == AlertGroupLogRecord.TYPE_FAILED_ATTACHMENT:
ephemeral_text = log_record.rendered_log_line_action(for_slack=True)
@ -629,9 +628,9 @@ class CustomButtonProcessStep(
f"according to escalation policy with the result `{result_message}`"
)
attachments = [
{"callback_id": "alert", "text": debug_message, "footer": text},
{"callback_id": "alert", "text": debug_message},
]
self._publish_message_to_thread(alert_group, attachments)
self.publish_message_to_thread(alert_group, attachments=attachments, text=text)
class ResolveGroupStep(
@ -763,23 +762,27 @@ class UnAcknowledgeGroupStep(
message_attachments = [
{
"callback_id": "alert",
"text": f"{user_verbal} hasn't responded to an acknowledge timeout reminder."
f" Incident is unacknowledged automatically",
"text": "",
"footer": "Escalation started again...",
},
]
text = (
f"{user_verbal} hasn't responded to an acknowledge timeout reminder."
f" Incident is unacknowledged automatically"
)
if alert_group.slack_message.ack_reminder_message_ts:
try:
self._slack_client.api_call(
"chat.update",
channel=channel_id,
ts=alert_group.slack_message.ack_reminder_message_ts,
text=text,
attachments=message_attachments,
)
except SlackAPIException as e:
# post to thread if ack reminder message was deleted in Slack
if e.response["error"] == "message_not_found":
self._publish_message_to_thread(alert_group, message_attachments)
self.publish_message_to_thread(alert_group, attachments=message_attachments, text=text)
elif e.response["error"] == "account_inactive":
logger.info(
f"Skip unacknowledge slack message for alert_group {alert_group.pk} due to account_inactive"
@ -787,7 +790,7 @@ class UnAcknowledgeGroupStep(
else:
raise
else:
self._publish_message_to_thread(alert_group, message_attachments)
self.publish_message_to_thread(alert_group, attachments=message_attachments, text=text)
self._update_slack_message(alert_group)
logger.debug(f"Finished process_signal in UnAcknowledgeGroupStep for alert_group {alert_group.pk}")
@ -806,18 +809,12 @@ class AcknowledgeConfirmationStep(AcknowledgeGroupStep):
if alert_group.acknowledged_by == AlertGroup.USER:
if self.user == alert_group.acknowledged_by_user:
user_verbal = alert_group.acknowledged_by_user.get_user_verbal_for_team_for_slack()
attachments = [
{
"color": "#c6c000",
"callback_id": "alert",
"text": f"{user_verbal} is confirmed to be working on this incident",
},
]
text = f"{user_verbal} confirmed that the incident is still acknowledged"
self._slack_client.api_call(
"chat.update",
channel=channel,
ts=message_ts,
attachments=attachments,
text=text,
)
alert_group.acknowledged_by_confirmed = datetime.utcnow()
alert_group.save(update_fields=["acknowledged_by_confirmed"])
@ -830,18 +827,12 @@ class AcknowledgeConfirmationStep(AcknowledgeGroupStep):
)
elif alert_group.acknowledged_by == AlertGroup.SOURCE:
user_verbal = self.user.get_user_verbal_for_team_for_slack()
attachments = [
{
"color": "#c6c000",
"callback_id": "alert",
"text": f"{user_verbal} is confirmed to be working on this incident",
},
]
text = f"{user_verbal} confirmed that the incident is still acknowledged"
self._slack_client.api_call(
"chat.update",
channel=channel,
ts=message_ts,
attachments=attachments,
text=text,
)
alert_group.acknowledged_by_confirmed = datetime.utcnow()
alert_group.save(update_fields=["acknowledged_by_confirmed"])
@ -865,12 +856,13 @@ class AcknowledgeConfirmationStep(AcknowledgeGroupStep):
alert_group = log_record.alert_group
channel_id = alert_group.slack_message.channel_id
user_verbal = log_record.author.get_user_verbal_for_team_for_slack(mention=True)
text = f"{user_verbal}, please confirm that you're still working on this incident."
if alert_group.channel.organization.unacknowledge_timeout != Organization.UNACKNOWLEDGE_TIMEOUT_NEVER:
attachments = [
{
"fallback": "Are you still working on this incident?",
"text": f"{user_verbal}, please confirm that you're still working on this incident.",
"text": text,
"callback_id": "alert",
"attachment_type": "default",
"footer": "This is a reminder that the incident is still acknowledged"
@ -896,6 +888,7 @@ class AcknowledgeConfirmationStep(AcknowledgeGroupStep):
response = self._slack_client.api_call(
"chat.postMessage",
channel=channel_id,
text=text,
attachments=attachments,
thread_ts=alert_group.slack_message.slack_id,
)
@ -932,14 +925,8 @@ class AcknowledgeConfirmationStep(AcknowledgeGroupStep):
alert_group.slack_message.ack_reminder_message_ts = response["ts"]
alert_group.slack_message.save(update_fields=["ack_reminder_message_ts"])
else:
attachments = [
{
"callback_id": "alert",
"text": f"This is a reminder that the incident is still acknowledged by {user_verbal}"
f" and not resolved.",
},
]
self._publish_message_to_thread(alert_group, attachments)
text = f"This is a reminder that the incident is still acknowledged by {user_verbal}"
self.publish_message_to_thread(alert_group, text=text)
class WipeGroupStep(scenario_step.ScenarioStep):
@ -953,15 +940,8 @@ class WipeGroupStep(scenario_step.ScenarioStep):
def process_signal(self, log_record):
alert_group = log_record.alert_group
user_verbal = log_record.author.get_user_verbal_for_team_for_slack()
attachments = [
{
"color": "warning",
"callback_id": "alert",
"footer": "Incident wiped",
"text": "Wiped by {}.".format(user_verbal),
},
]
self._publish_message_to_thread(alert_group, attachments)
text = f"Wiped by {user_verbal}"
self.publish_message_to_thread(alert_group, text=text)
self._update_slack_message(alert_group)
@ -1069,21 +1049,15 @@ class UpdateLogReportMessageStep(scenario_step.ScenarioStep):
logger.info(f"Cannot post log message for alert_group {alert_group.pk} because SlackMessage doesn't exist")
return None
attachments = [
{
"text": "Building escalation plan... :thinking_face:",
}
]
text = ("Building escalation plan... :thinking_face:",)
slack_log_message = alert_group.slack_log_message
if slack_log_message is None:
logger.debug(f"Start posting new log message for alert_group {alert_group.pk}")
try:
result = self._slack_client.api_call(
"chat.postMessage",
channel=slack_message.channel_id,
thread_ts=slack_message.slack_id,
attachments=attachments,
"chat.postMessage", channel=slack_message.channel_id, thread_ts=slack_message.slack_id, text=text
)
except SlackAPITokenException as e:
print(e)
@ -1148,6 +1122,7 @@ class UpdateLogReportMessageStep(scenario_step.ScenarioStep):
self._slack_client.api_call(
"chat.update",
channel=slack_message.channel_id,
text="Alert Group log",
ts=slack_log_message.slack_id,
attachments=attachments,
)

View file

@ -34,14 +34,3 @@ class EscalationDeliveryStep(scenario_step.ScenarioStep):
user_mention_as = user_verbal
notify_by = " by {}".format(UserNotificationPolicy.NotificationChannel(notification_channel).label)
return "Inviting {}{} to look at incident.".format(user_mention_as, notify_by)
def notify_thread_about_action(self, alert_group, text, footer=None, color=None):
attachments = [
{
"callback_id": "alert",
"footer": footer,
"text": text,
"color": color,
},
]
self._publish_message_to_thread(alert_group, attachments)

View file

@ -62,16 +62,34 @@ class NotificationDeliveryStep(scenario_step.ScenarioStep):
)
def post_message_to_channel(self, text, channel, color=None, footer=None):
color_id = self.get_color_id(color)
attachments = [
{"color": color_id, "callback_id": "alert", "footer": footer, "text": text},
# TODO: No color in blocks, use prefix emoji?
# color_id = self.get_color_id(color)
blocks = [
{
"type": "section",
"block_id": "alert",
"text": {
"type": "mrkdwn",
"text": text,
},
},
{"type": "divider"},
{
"type": "section",
"block_id": "alert",
"text": {
"type": "mrkdwn",
"text": footer,
},
},
]
try:
# TODO: slack-onprem, check exceptions
self._slack_client.api_call(
"chat.postMessage",
channel=channel,
attachments=attachments,
text=text,
blocks=blocks,
unfurl_links=True,
)
except SlackAPITokenException as e:

View file

@ -287,7 +287,7 @@ class ScenarioStep(object):
raise e
logger.info(f"Finished _update_slack_message for alert_group {alert_group.pk}")
def _publish_message_to_thread(self, alert_group, attachments, mrkdwn=True, unfurl_links=True):
def publish_message_to_thread(self, alert_group, attachments=[], mrkdwn=True, unfurl_links=True, text=None):
# TODO: refactor checking the possibility of sending message to slack
# do not try to post message to slack if integration is rate limited
if alert_group.channel.is_rate_limited_in_slack:
@ -300,6 +300,7 @@ class ScenarioStep(object):
result = self._slack_client.api_call(
"chat.postMessage",
channel=channel_id,
text=text,
attachments=attachments,
thread_ts=slack_message.slack_id,
mrkdwn=mrkdwn,

View file

@ -16,7 +16,7 @@ class AlertGroupLogSlackRenderer:
attachments = []
# get rendered logs
result = "Alert Group log:\n\n"
result = ""
for log_record in all_log_records: # list of AlertGroupLogRecord and UserNotificationPolicyLogRecord logs
if type(log_record) == AlertGroupLogRecord:
result += f"{log_record.rendered_incident_log_line(for_slack=True)}\n"

View file

@ -36,16 +36,24 @@ class IncidentActionsAccessControlMixin(AccessControl):
thread_ts = payload["message_ts"]
except KeyError:
thread_ts = payload["message"]["ts"]
text = "Attempted to {} by {}, but failed due to a lack of permissions.".format(
self.ACTION_VERBOSE,
self.user.get_user_verbal_for_team_for_slack(),
)
self._slack_client.api_call(
"chat.postMessage",
channel=payload["channel"]["id"],
attachments=[
text=text,
blocks=[
{
"callback_id": "alert",
"text": "Attempted to {} by {}, but failed due to a lack of permissions.".format(
self.ACTION_VERBOSE,
self.user.get_user_verbal_for_team_for_slack(),
),
"type": "section",
"block_id": "alert",
"text": {
"type": "mrkdwn",
"text": text,
},
},
],
thread_ts=None if self.send_denied_message_to_channel(payload) else thread_ts,

View file

@ -98,9 +98,10 @@ def check_slack_message_exists_before_post_message_to_thread(
slack_message = alert_group.get_slack_message()
if slack_message is not None:
EscalationDeliveryStep(slack_team_identity, alert_group.channel.organization).notify_thread_about_action(
alert_group, text
EscalationDeliveryStep(slack_team_identity, alert_group.channel.organization).publish_message_to_thread(
alert_group, text=text
)
# check how much time has passed since alert group was created
# to prevent eternal loop of restarting check_slack_message_before_post_message_to_thread
elif timezone.now() < alert_group.started_at + timezone.timedelta(hours=retry_timeout_hours):
@ -239,12 +240,7 @@ def send_message_to_thread_if_bot_not_in_channel(alert_group_pk, slack_team_iden
members = slack_team_identity.get_conversation_members(sc, channel_id)
if bot_user_id not in members:
text = f"Please invite <@{bot_user_id}> to this channel to make all features " f"available :wink:"
attachments = [
{
"text": text,
}
]
ScenarioStep(slack_team_identity)._publish_message_to_thread(alert_group, attachments)
ScenarioStep(slack_team_identity).publish_message_to_thread(alert_group, text=text)
@shared_dedicated_queue_retry_task(autoretry_for=(Exception,), retry_backoff=True, max_retries=1)
@ -269,6 +265,7 @@ def send_debug_message_to_thread(alert_group_pk, slack_team_identity_pk):
result = sc.api_call(
"chat.postMessage",
channel=channel_id,
text=text,
attachments=[],
thread_ts=current_alert_group.slack_message.slack_id,
mrkdwn=True,

View file

@ -286,7 +286,6 @@ class SlackEventApiEndpointView(APIView):
or payload["event"]["subtype"] == EVENT_SUBTYPE_MESSAGE_DELETED
)
):
print("Inside channel.messages event")
for route in SCENARIOS_ROUTES:
if (
"message_channel_type" in route

View file

@ -156,7 +156,7 @@ export const PluginConfigPage = (props: Props) => {
setPluginStatusOk(true);
} else {
setPluginStatusMessage(
`OnCall failed to connect to to this grafana via: ${plugin.meta.jsonData.grafanaUrl} check URL, network, and API key.`
`OnCall failed to connect to this grafana via: ${plugin.meta.jsonData.grafanaUrl} check URL, network, and API key.`
);
setRetrySync(true);
}