def update_impact(incident: Incident, user_id: str, message: str): # Easy case. No impact currently and one has been provided if message and not incident.impact: incident.impact = message incident.save() return True, f"{IMPACT_UPDATED_TITLE}{message}" # Either no new impact has been provided, or one already exists msg = block_kit.Message() msg.add_block( block_kit.Section( block_id="update", text=block_kit.Text( f"{CURRENT_TITLE}{incident.impact or NO_IMPACT_TEXT}"), accessory=block_kit.Button(CHANGE_BUTTON_TEXT, UPDATE_CURRENT_IMPACT_ACTION, value=incident.pk), )) # if the user has supplied a message, provide the option for them to set it without # retyping in the dialog if message: msg.add_block( block_kit.Section( block_id=PROPOSED_MESSAGE_BLOCK_ID, text=block_kit.Text(f"{PROPOSED_TITLE}{message}"), accessory=block_kit.Button(ACCEPT_PROPOSED_TEXT, SET_NEW_IMPACT_ACTION, value=incident.pk), )) comms_channel = CommsChannel.objects.get(incident=incident) msg.send(comms_channel.channel_id) return True, None
def set_incident_lead(incident: Incident, user_id: str, message: str): assignee = reference_to_id(message) or user_id name = settings.SLACK_CLIENT.get_user_profile(assignee)['name'] user = GetOrCreateSlackExternalUser(external_id=assignee, display_name=name) incident.lead = user incident.save() return True, None
def set_incident_lead(incident: Incident, user_id: str, message: str): assignee = reference_to_id(message) or user_id name = get_user_profile(assignee)["name"] user, _ = ExternalUser.objects.get_or_create_slack(external_id=assignee, display_name=name) incident.lead = user incident.save() return True, None
def set_severity(incident: Incident, user_id: str, message: str): for sev_id, sev_name in Incident.SEVERITIES: # look for sev name (e.g. critical) or sev id (1) if (sev_name in message) or (sev_id in message): incident.severity = sev_id incident.save() return True, None return False, None
def set_severity(incident: Incident, user_id: str, message: str): for sev_id, sev_name in Incident.SEVERITIES: # look for sev name (e.g. critical) or sev id (1) if (sev_name in message.lower()) or (sev_id in message.lower()): incident.severity = sev_id incident.save() return add_status_update( incident, user_id, 'Severity updated to ' + incident.severity_text()) return False, None
def set_incident_lead(incident: Incident, user_id: str, message: str): assignee = get_user_profile_by_name(message) name = assignee['name'] print(name) user, _ = ExternalUser.objects.get_or_create_slack( external_id=assignee['id'], display_name=name) incident.lead = user incident.save() return add_status_update(incident, user_id, 'New lead is ' + incident.lead.full_name)
def close_incident(incident: Incident, user_id: str, message: str): comms_channel = CommsChannel.objects.get(incident=incident) if incident.is_closed(): comms_channel.post_in_channel( f"This incident was already closed at {incident.end_time.strftime('%Y-%m-%d %H:%M:%S')}" ) return True, None incident.end_time = datetime.now() incident.save() comms_channel.post_in_channel(f"This incident has been closed! 📖 -> 📕") return True, None
def set_duration(incident: Incident, user_id: str, message: str): duration = incident.duration() comms_channel = CommsChannel.objects.get(incident=incident) comms_channel.post_in_channel(f"The incident has been running for {duration}") return True, None
def remind_close_incident(incident: Incident): try: comms_channel = CommsChannel.objects.get(incident=incident) if not incident.is_closed(): comms_channel.post_in_channel( ":timer_clock: This incident has been running a long time. Can it be closed now? Remember to pin important messages in order to create the timeline." ) except CommsChannel.DoesNotExist: pass
def remind_update_status(incident: Incident): try: comms_channel = CommsChannel.objects.get(incident=incident) if not incident.is_closed(): user_to_notify = incident.lead or incident.reporter comms_channel.post_in_channel( f":timer_clock: <@{user_to_notify.external_id}>, this incident has been running a long time." " Have you updated the proper notification channels? Remember to notify status updates in twitter and status page" ) except CommsChannel.DoesNotExist: pass
def remind_close_incident(incident: Incident): # Only remind on weekdays (weekday returns an ordinal indexed from 0 on Monday) if datetime.now().weekday() in (5, 6): return try: comms_channel = CommsChannel.objects.get(incident=incident) if not incident.is_closed(): user_to_notify = incident.lead or incident.reporter comms_channel.post_in_channel( f":timer_clock: <@{user_to_notify.external_id}>, this incident has been running a long time." " Can it be closed now? Remember to pin important messages in order to create the timeline." ) except CommsChannel.DoesNotExist: pass
def create_zoom(incident: Incident, user_id: str, message: str): try: m = incident.zoom_meeting() except ObjectDoesNotExist: m = Meeting.objects.create_meeting(incident) # Update the headline post here too h = HeadlinePost.objects.get(incident=incident) h.zoom_meeting = m h.save() h.update_in_slack() comms_channel = CommsChannel.objects.get(incident=incident) comms_channel.post_in_channel( f"You can join the zoom meeting here {m.weblink} with password `{m.challenge}`" ) return True, None
def prompt_incident_report(sender, instance: Incident, **kwargs): """ Prompt incident lead to complete a report when an incident is closed. """ try: prev_state = Incident.objects.get(pk=instance.pk) except Incident.DoesNotExist: # Incident hasn't been saved yet, nothing to do here. return if instance.is_closed() and not prev_state.is_closed(): user_to_notify = instance.lead or instance.reporter doc_url = urljoin( settings.SITE_URL, reverse('incident_doc', kwargs={'incident_id': instance.pk}) ) settings.SLACK_CLIENT.send_message( user_to_notify.external_id, f"👋 Don't forget to fill out an incident report here: {doc_url}")
def prompt_incident_report(sender, instance: Incident, **kwargs): """ Prompt incident lead to complete a report when an incident is closed. """ try: prev_state = Incident.objects.get(pk=instance.pk) except Incident.DoesNotExist: # Incident hasn't been saved yet, nothing to do here. return if instance.is_closed() and not prev_state.is_closed(): user_to_notify = instance.lead or instance.reporter doc_url = urljoin( settings.SITE_URL, reverse("incident_doc", kwargs={"incident_id": instance.pk}), ) settings.SLACK_CLIENT.send_message( user_to_notify.external_id, f"👋 Don't forget to fill out an incident report <https://signal-ai.getoutline.com/doc/incident-logbook-wL5JK4hyTr|on the wiki>. The <{doc_url}|incident doc> may help with that.", )
def remind_update(incident: Incident): update = StatusUpdate.objects.filter( incident=incident).order_by("timestamp").first() if update is not None: if update.timestamp < datetime.datetime.now() - datetime.timedelta( minutes=60): logger.info("The last update was over 1h ago") try: comms_channel = CommsChannel.objects.get(incident=incident) if not incident.is_closed(): user_to_notify = incident.lead settings.SLACK_CLIENT.send_ephemeral_message( comms_channel.channel_id, user_to_notify.external_id, "The last update was over 1h ago. To provide a new update use the command:\n `/%s update [text]`" % settings.SLACK_SLASH_COMMAND, ) except CommsChannel.DoesNotExist: pass else: logger.info("The last update is not older than 60 minutes")
def update_impact(incident: Incident, user_id: str, message: str): incident.impact = message incident.save() return True, None
def update_summary(incident: Incident, user_id: str, message: str): incident.summary = message incident.save() return True, None
def mitigate_incident(incident: Incident, user_id: str, message: str): incident.mitigated = True incident.save() return add_status_update(incident, user_id, 'Status changed to Mitigated - ' + message)