Пример #1
0
def send_welcome_email_to_participant(
    participant_email: str, incident_id: int, db_session: SessionLocal
):
    """Sends a welcome email to the participant."""
    # we load the incident instance
    plugin = plugin_service.get_active(db_session=db_session, plugin_type="email")
    if not plugin:
        log.warning("Participant welcome email not sent, not email plugin configured.")
        return

    incident = incident_service.get(db_session=db_session, incident_id=incident_id)

    message_kwargs = {
        "name": incident.name,
        "title": incident.title,
        "description": incident.description,
        "status": incident.status,
        "type": incident.incident_type.name,
        "type_description": incident.incident_type.description,
        "priority": incident.incident_priority.name,
        "priority_description": incident.incident_priority.description,
        "commander_fullname": incident.commander.individual.name,
        "commander_team": incident.commander.team,
        "commander_weblink": incident.commander.individual.weblink,
        "reporter_fullname": incident.reporter.individual.name,
        "reporter_team": incident.reporter.team,
        "reporter_weblink": incident.reporter.individual.weblink,
        "document_weblink": resolve_attr(incident, "incident_document.weblink"),
        "storage_weblink": resolve_attr(incident, "storage.weblink"),
        "ticket_weblink": resolve_attr(incident, "ticket.weblink"),
        "conference_weblink": resolve_attr(incident, "conference.weblink"),
        "conference_challenge": resolve_attr(incident, "conference.conference_challenge"),
        "contact_fullname": incident.commander.individual.name,
        "contact_weblink": incident.commander.individual.weblink,
    }

    faq_doc = document_service.get_incident_faq_document(db_session=db_session)
    if faq_doc:
        message_kwargs.update({"faq_weblink": faq_doc.weblink})

    conversation_reference = document_service.get_conversation_reference_document(
        db_session=db_session
    )
    if conversation_reference:
        message_kwargs.update(
            {"conversation_commands_reference_document_weblink": conversation_reference.weblink}
        )

    notification_text = "Incident Notification"
    plugin.instance.send(
        participant_email,
        notification_text,
        INCIDENT_PARTICIPANT_WELCOME_MESSAGE,
        MessageType.incident_participant_welcome,
        **message_kwargs,
    )

    log.debug(f"Welcome email sent to {participant_email}.")
Пример #2
0
def send_incident_resources_ephemeral_message_to_participant(
    user_id: str, incident_id: int, db_session: SessionLocal
):
    """Sends the list of incident resources to the participant via an ephemeral message."""
    # we load the incident instance
    plugin = plugin_service.get_active(db_session=db_session, plugin_type="conversation")
    if not plugin:
        log.warning("Incident resource message not sent, no conversation plugin enabled.")
        return

    incident = incident_service.get(db_session=db_session, incident_id=incident_id)

    message_kwargs = {
        "title": incident.title,
        "description": incident.description,
        "commander_fullname": incident.commander.individual.name,
        "commander_team": incident.commander.team,
        "commander_weblink": incident.commander.individual.weblink,
        "reporter_fullname": incident.reporter.individual.name,
        "reporter_team": incident.reporter.team,
        "reporter_weblink": incident.reporter.individual.weblink,
        "document_weblink": resolve_attr(incident, "incident_document.weblink"),
        "storage_weblink": resolve_attr(incident, "storage.weblink"),
        "ticket_weblink": resolve_attr(incident, "ticket.weblink"),
        "conference_weblink": resolve_attr(incident, "conference.weblink"),
        "conference_challenge": resolve_attr(incident, "conference.conference_challenge"),
    }

    if incident.incident_review_document:
        message_kwargs.update(
            {"review_document_weblink": incident.incident_review_document.weblink}
        )

    faq_doc = document_service.get_incident_faq_document(db_session=db_session)
    if faq_doc:
        message_kwargs.update({"faq_weblink": faq_doc.weblink})

    conversation_reference = document_service.get_conversation_reference_document(
        db_session=db_session
    )
    if conversation_reference:
        message_kwargs.update(
            {"conversation_commands_reference_document_weblink": conversation_reference.weblink}
        )

    # we send the ephemeral message
    plugin.instance.send_ephemeral(
        incident.conversation.channel_id,
        user_id,
        "Incident Resources Message",
        INCIDENT_RESOURCES_MESSAGE,
        MessageType.incident_resources_message,
        **message_kwargs,
    )

    log.debug(f"List of incident resources sent to {user_id} via ephemeral message.")
Пример #3
0
def send_welcome_ephemeral_message_to_participant(
    participant_email: str, incident_id: int, db_session: SessionLocal
):
    """Sends an ephemeral message to the participant."""
    # we load the incident instance
    plugin = plugin_service.get_active(db_session=db_session, plugin_type="conversation")
    if not plugin:
        log.warning("Incident welcome message not sent, not conversation plugin enabled.")
        return

    incident = incident_service.get(db_session=db_session, incident_id=incident_id)

    # we send the ephemeral message
    message_kwargs = {
        "name": incident.name,
        "title": incident.title,
        "status": incident.status,
        "type": incident.incident_type.name,
        "type_description": incident.incident_type.description,
        "priority": incident.incident_priority.name,
        "priority_description": incident.incident_priority.description,
        "commander_fullname": incident.commander.individual.name,
        "commander_weblink": incident.commander.individual.weblink,
        "document_weblink": resolve_attr(incident, "incident_document.weblink"),
        "storage_weblink": resolve_attr(incident, "storage.weblink"),
        "ticket_weblink": resolve_attr(incident, "ticket.weblink"),
        "conference_weblink": resolve_attr(incident, "conference.weblink"),
        "conference_challenge": resolve_attr(incident, "conference.conference_challenge"),
    }

    faq_doc = document_service.get_incident_faq_document(db_session=db_session)
    if faq_doc:
        message_kwargs.update({"faq_weblink": faq_doc.weblink})

    conversation_reference = document_service.get_conversation_reference_document(
        db_session=db_session
    )
    if conversation_reference:
        message_kwargs.update(
            {"conversation_commands_reference_document_weblink": conversation_reference.weblink}
        )

    plugin.instance.send_ephemeral(
        incident.conversation.channel_id,
        participant_email,
        "Incident Welcome Message",
        INCIDENT_PARTICIPANT_WELCOME_MESSAGE,
        MessageType.incident_participant_welcome,
        **message_kwargs,
    )

    log.debug(f"Welcome ephemeral message sent to {participant_email}.")
Пример #4
0
def send_incident_created_notifications(incident: Incident, db_session: SessionLocal):
    """Sends incident created notifications."""
    notification_template = INCIDENT_NOTIFICATION.copy()

    if incident.status != IncidentStatus.closed:
        notification_template.insert(0, INCIDENT_NAME_WITH_ENGAGEMENT)
    else:
        notification_template.insert(0, INCIDENT_NAME)

    notification_kwargs = {
        "name": incident.name,
        "title": incident.title,
        "description": incident.description,
        "status": incident.status,
        "type": incident.incident_type.name,
        "type_description": incident.incident_type.description,
        "priority": incident.incident_priority.name,
        "priority_description": incident.incident_priority.description,
        "reporter_fullname": incident.reporter.individual.name,
        "reporter_team": incident.reporter.team,
        "reporter_weblink": incident.reporter.individual.weblink,
        "commander_fullname": incident.commander.individual.name,
        "commander_team": incident.commander.team,
        "commander_weblink": incident.commander.individual.weblink,
        "document_weblink": resolve_attr(incident, "incident_document.weblink"),
        "storage_weblink": resolve_attr(incident, "storage.weblink"),
        "ticket_weblink": resolve_attr(incident, "ticket.weblink"),
        "conference_weblink": resolve_attr(incident, "conference.weblink"),
        "conference_challenge": resolve_attr(incident, "conference.conference_challenge"),
        "contact_fullname": incident.commander.individual.name,
        "contact_weblink": incident.commander.individual.weblink,
        "incident_id": incident.id,
    }

    faq_doc = document_service.get_incident_faq_document(db_session=db_session)
    if faq_doc:
        notification_kwargs.update({"faq_weblink": faq_doc.weblink})

    notification_params = {
        "text": "Incident Notification",
        "type": MessageType.incident_notification,
        "template": notification_template,
        "kwargs": notification_kwargs,
    }

    notification_service.filter_and_send(
        db_session=db_session, class_instance=incident, notification_params=notification_params
    )

    log.debug("Incident created notifications sent.")
Пример #5
0
def send_incident_report_reminder(incident: Incident, report_type: ReportTypes,
                                  db_session: SessionLocal):
    """Sends a direct message to the incident commander indicating that they should complete a report."""
    message_text = f"Incident {report_type.value} Reminder"
    message_template = INCIDENT_REPORT_REMINDER
    command_name, message_type = get_report_reminder_settings(report_type)

    plugin = plugin_service.get_active(db_session=db_session,
                                       plugin_type="conversation")
    if not plugin:
        log.warning(
            "Incident report reminder not sent, no conversation plugin enabled."
        )
        return

    report_command = plugin.instance.get_command_name(command_name)
    ticket_weblink = resolve_attr(incident, "ticket.weblink")

    items = [{
        "command": report_command,
        "name": incident.name,
        "report_type": report_type.value,
        "ticket_weblink": ticket_weblink,
        "title": incident.title,
    }]

    plugin.instance.send_direct(
        incident.commander.email,
        message_text,
        message_template,
        message_type,
        items=items,
    )

    log.debug(f"Incident report reminder sent to {incident.commander.email}.")
Пример #6
0
def list_incidents(incident_id: int, command: dict = None, db_session=None):
    """Returns the list of current active and stable incidents,
    and closed incidents in the last 24 hours."""
    incidents = []

    # We fetch active incidents
    incidents = incident_service.get_all_by_status(
        db_session=db_session, status=IncidentStatus.active.value)
    # We fetch stable incidents
    incidents.extend(
        incident_service.get_all_by_status(db_session=db_session,
                                           status=IncidentStatus.stable.value))
    # We fetch closed incidents in the last 24 hours
    incidents.extend(
        incident_service.get_all_last_x_hours_by_status(
            db_session=db_session,
            status=IncidentStatus.closed.value,
            hours=24))

    blocks = []
    blocks.append({
        "type": "header",
        "text": {
            "type": "plain_text",
            "text": "List of Incidents"
        }
    })

    if incidents:
        for incident in incidents:
            if incident.visibility == Visibility.open:
                ticket_weblink = resolve_attr(incident, "ticket.weblink")
                try:
                    blocks.append({
                        "type": "section",
                        "text": {
                            "type":
                            "mrkdwn",
                            "text":
                            (f"*<{ticket_weblink}|{incident.name}>*\n"
                             f"*Title*: {incident.title}\n"
                             f"*Type*: {incident.incident_type.name}\n"
                             f"*Priority*: {incident.incident_priority.name}\n"
                             f"*Status*: {incident.status}\n"
                             f"*Incident Commander*: <{incident.commander.individual.weblink}|{incident.commander.individual.name}>"
                             ),
                        },
                    })
                except Exception as e:
                    log.exception(e)

    dispatch_slack_service.send_ephemeral_message(
        slack_client,
        command["channel_id"],
        command["user_id"],
        "Incident List",
        blocks=blocks,
    )
Пример #7
0
def update_external_incident_ticket(
    incident: Incident,
    db_session: SessionLocal,
):
    """Update external incident ticket."""
    plugin = plugin_service.get_active(db_session=db_session,
                                       plugin_type="ticket")
    if not plugin:
        log.warning("External ticket not updated, no ticket plugin enabled.")
        return

    title = incident.title
    description = incident.description
    if incident.visibility == Visibility.restricted:
        title = description = incident.incident_type.name

    incident_type_plugin_metadata = incident_type_service.get_by_name(
        db_session=db_session,
        name=incident.incident_type.name).get_meta(plugin.slug)

    plugin.instance.update(
        incident.ticket.resource_id,
        title,
        description,
        incident.incident_type.name,
        incident.incident_priority.name,
        incident.status.lower(),
        incident.commander.email,
        incident.reporter.email,
        resolve_attr(incident, "conversation.weblink"),
        resolve_attr(incident, "incident_document.weblink"),
        resolve_attr(incident, "storage.weblink"),
        resolve_attr(incident, "conference.weblink"),
        incident.cost,
        incident_type_plugin_metadata=incident_type_plugin_metadata,
    )

    log.debug("The external ticket has been updated.")
Пример #8
0
def send_incident_update_notifications(incident: Incident,
                                       previous_incident: IncidentRead,
                                       db_session: SessionLocal):
    """Sends notifications about incident changes."""
    notification_text = "Incident Notification"
    notification_type = MessageType.incident_notification
    notification_template = INCIDENT_NOTIFICATION_COMMON.copy()

    change = False
    if previous_incident.status != incident.status:
        change = True
        notification_template.append(INCIDENT_STATUS_CHANGE)

    if previous_incident.incident_type.name != incident.incident_type.name:
        change = True
        notification_template.append(INCIDENT_TYPE_CHANGE)

    if previous_incident.incident_priority.name != incident.incident_priority.name:
        change = True
        notification_template.append(INCIDENT_PRIORITY_CHANGE)

    if not change:
        # we don't need to notify
        log.debug("Incident change notifications not sent.")
        return

    notification_template.append(INCIDENT_COMMANDER)
    convo_plugin = plugin_service.get_active(db_session=db_session,
                                             plugin_type="conversation")

    # we send an update to the incident conversation
    incident_conversation_notification_template = notification_template.copy()
    incident_conversation_notification_template.insert(0, INCIDENT_NAME)

    # we can't send messages to closed channels
    if incident.status != IncidentStatus.closed:
        convo_plugin.instance.send(
            incident.conversation.channel_id,
            notification_text,
            incident_conversation_notification_template,
            notification_type,
            name=incident.name,
            ticket_weblink=incident.ticket.weblink,
            title=incident.title,
            incident_type_old=previous_incident.incident_type.name,
            incident_type_new=incident.incident_type.name,
            incident_priority_old=previous_incident.incident_priority.name,
            incident_priority_new=incident.incident_priority.name,
            incident_status_old=previous_incident.status.value,
            incident_status_new=incident.status,
            commander_fullname=incident.commander.name,
            commander_weblink=incident.commander.weblink,
        )

    if incident.visibility == Visibility.open:
        notification_conversation_notification_template = notification_template.copy(
        )
        if incident.status != IncidentStatus.closed:
            notification_conversation_notification_template.insert(
                0, INCIDENT_NAME_WITH_ENGAGEMENT)
        else:
            notification_conversation_notification_template.insert(
                0, INCIDENT_NAME)

        # we send an update to the incident notification conversations
        for conversation in INCIDENT_NOTIFICATION_CONVERSATIONS:
            convo_plugin.instance.send(
                conversation,
                notification_text,
                notification_conversation_notification_template,
                notification_type,
                name=incident.name,
                ticket_weblink=incident.ticket.weblink,
                title=incident.title,
                incident_id=incident.id,
                incident_type_old=previous_incident.incident_type.name,
                incident_type_new=incident.incident_type.name,
                incident_priority_old=previous_incident.incident_priority.name,
                incident_priority_new=incident.incident_priority.name,
                incident_status_old=previous_incident.status.value,
                incident_status_new=incident.status,
                commander_fullname=incident.commander.name,
                commander_weblink=incident.commander.weblink,
            )

        # we send an update to the incident notification distribution lists
        email_plugin = plugin_service.get_active(db_session=db_session,
                                                 plugin_type="email")
        for distro in INCIDENT_NOTIFICATION_DISTRIBUTION_LISTS:
            email_plugin.instance.send(
                distro,
                notification_template,
                notification_type,
                name=incident.name,
                title=incident.title,
                status=incident.status,
                priority=incident.incident_priority.name,
                priority_description=incident.incident_priority.description,
                commander_fullname=incident.commander.name,
                commander_weblink=incident.commander.weblink,
                document_weblink=resolve_attr(incident,
                                              "incident_document.weblink"),
                storage_weblink=resolve_attr(incident, "storage.weblink"),
                ticket_weblink=resolve_attr(incident, "ticket.weblink"),
                incident_id=incident.id,
                incident_priority_old=previous_incident.incident_priority.name,
                incident_priority_new=incident.incident_priority.name,
                incident_type_old=previous_incident.incident_type.name,
                incident_type_new=incident.incident_type.name,
                incident_status_old=previous_incident.status.value,
                incident_status_new=incident.status,
                contact_fullname=incident.commander.name,
                contact_weblink=incident.commander.weblink,
            )

    log.debug("Incident update notifications sent.")
Пример #9
0
def send_incident_status_notifications(incident: Incident,
                                       db_session: SessionLocal):
    """Sends incident status notifications to conversations and distribution lists."""
    notification_text = "Incident Notification"
    notification_type = MessageType.incident_notification
    message_template = INCIDENT_NOTIFICATION.copy()

    # we send status notifications to conversations
    if incident.status != IncidentStatus.closed:
        message_template.insert(0, INCIDENT_NAME_WITH_ENGAGEMENT)
    else:
        message_template.insert(0, INCIDENT_NAME)

    message_kwargs = {
        "name":
        incident.name,
        "title":
        incident.title,
        "status":
        incident.status,
        "type":
        incident.incident_type.name,
        "type_description":
        incident.incident_type.description,
        "priority":
        incident.incident_priority.name,
        "priority_description":
        incident.incident_priority.description,
        "commander_fullname":
        incident.commander.name,
        "commander_weblink":
        incident.commander.weblink,
        "document_weblink":
        resolve_attr(incident, "incident_document.weblink"),
        "storage_weblink":
        resolve_attr(incident, "storage.weblink"),
        "ticket_weblink":
        resolve_attr(incident, "ticket.weblink"),
        "conference_weblink":
        resolve_attr(incident, "conference.weblink"),
        "conference_challenge":
        resolve_attr(incident, "conference.conference_challenge"),
        "contact_fullname":
        incident.commander.name,
        "contact_weblink":
        incident.commander.weblink,
        "incident_id":
        incident.id,
    }
    faq_doc = document_service.get_incident_faq_document(db_session=db_session)
    if faq_doc:
        message_kwargs.update({"faq_weblink": faq_doc.weblink})

    convo_plugin = plugin_service.get_active(db_session=db_session,
                                             plugin_type="conversation")
    if convo_plugin:
        for conversation in INCIDENT_NOTIFICATION_CONVERSATIONS:
            convo_plugin.instance.send(
                conversation,
                notification_text,
                message_template,
                notification_type,
                **message_kwargs,
            )
    else:
        log.warning(
            "No incident conversation notifications sent. No conversation plugin is active."
        )

    # we send status notifications to distribution lists
    email_plugin = plugin_service.get_active(db_session=db_session,
                                             plugin_type="email")
    if email_plugin:
        for distro in INCIDENT_NOTIFICATION_DISTRIBUTION_LISTS:
            email_plugin.instance.send(distro, message_template,
                                       notification_type, **message_kwargs)
    else:
        log.warning(
            "No incident email notifications sent. No email plugin is active.")

    log.debug("Incident status notifications sent.")
Пример #10
0
def send_incident_update_notifications(
    incident: Incident, previous_incident: IncidentRead, db_session: SessionLocal
):
    """Sends notifications about incident changes."""
    notification_text = "Incident Notification"
    notification_type = MessageType.incident_notification
    notification_template = INCIDENT_NOTIFICATION_COMMON.copy()

    change = False
    if previous_incident.status != incident.status:
        change = True
        notification_template.append(INCIDENT_STATUS_CHANGE)

    if previous_incident.incident_type.name != incident.incident_type.name:
        change = True
        notification_template.append(INCIDENT_TYPE_CHANGE)

    if previous_incident.incident_priority.name != incident.incident_priority.name:
        change = True
        notification_template.append(INCIDENT_PRIORITY_CHANGE)

    if not change:
        # we don't need to notify
        log.debug("Incident updated notifications not sent.")
        return

    notification_template.append(INCIDENT_COMMANDER)

    # we send an update to the incident conversation if the incident is active or stable
    if incident.status != IncidentStatus.closed:
        incident_conversation_notification_template = notification_template.copy()
        incident_conversation_notification_template.insert(0, INCIDENT_NAME)

        convo_plugin = plugin_service.get_active(db_session=db_session, plugin_type="conversation")
        if convo_plugin:
            convo_plugin.instance.send(
                incident.conversation.channel_id,
                notification_text,
                incident_conversation_notification_template,
                notification_type,
                commander_fullname=incident.commander.individual.name,
                commander_team=incident.commander.team,
                commander_weblink=incident.commander.individual.weblink,
                incident_priority_new=incident.incident_priority.name,
                incident_priority_old=previous_incident.incident_priority.name,
                incident_status_new=incident.status,
                incident_status_old=previous_incident.status.value,
                incident_type_new=incident.incident_type.name,
                incident_type_old=previous_incident.incident_type.name,
                name=incident.name,
                ticket_weblink=incident.ticket.weblink,
                title=incident.title,
            )
        else:
            log.debug(
                "Incident updated notification not sent to incident conversation. No conversation plugin enabled."
            )

    # we send a notification to the notification conversations and emails
    fyi_notification_template = notification_template.copy()
    if incident.status != IncidentStatus.closed:
        fyi_notification_template.insert(0, INCIDENT_NAME_WITH_ENGAGEMENT)
    else:
        fyi_notification_template.insert(0, INCIDENT_NAME)

    notification_kwargs = {
        "commander_fullname": incident.commander.individual.name,
        "commander_team": incident.commander.team,
        "commander_weblink": incident.commander.individual.weblink,
        "contact_fullname": incident.commander.individual.name,
        "contact_weblink": incident.commander.individual.weblink,
        "incident_id": incident.id,
        "incident_priority_new": incident.incident_priority.name,
        "incident_priority_old": previous_incident.incident_priority.name,
        "incident_status_new": incident.status,
        "incident_status_old": previous_incident.status.value,
        "incident_type_new": incident.incident_type.name,
        "incident_type_old": previous_incident.incident_type.name,
        "name": incident.name,
        "ticket_weblink": resolve_attr(incident, "ticket.weblink"),
        "title": incident.title,
    }

    notification_params = {
        "text": notification_text,
        "type": notification_type,
        "template": fyi_notification_template,
        "kwargs": notification_kwargs,
    }

    notification_service.filter_and_send(
        db_session=db_session, class_instance=incident, notification_params=notification_params
    )

    log.debug("Incident updated notifications sent.")
Пример #11
0
def daily_summary(db_session=None):
    """
    Fetches all active, and stable and closed incidents in the last 24 hours
    and sends a daily summary to all incident notification conversations.
    """
    blocks = []
    blocks.append(
        {
            "type": "header",
            "text": {
                "type": "plain_text",
                "text": f"{INCIDENT_DAILY_SUMMARY_DESCRIPTION}",
            },
        }
    )

    active_incidents = get_all_by_status(db_session=db_session, status=IncidentStatus.active)
    if active_incidents:
        blocks.append(
            {
                "type": "section",
                "text": {
                    "type": "mrkdwn",
                    "text": f"*{INCIDENT_DAILY_SUMMARY_ACTIVE_INCIDENTS_DESCRIPTION}*",
                },
            }
        )
        for idx, incident in enumerate(active_incidents):
            ticket_weblink = resolve_attr(incident, "ticket.weblink")
            if incident.visibility == Visibility.open:
                try:
                    blocks.append(
                        {
                            "type": "section",
                            "text": {
                                "type": "mrkdwn",
                                "text": (
                                    f"*<{ticket_weblink}|{incident.name}>*\n"
                                    f"*Title*: {incident.title}\n"
                                    f"*Type*: {incident.incident_type.name}\n"
                                    f"*Priority*: {incident.incident_priority.name}\n"
                                    f"*Incident Commander*: <{incident.commander.weblink}|{incident.commander.name}>"
                                ),
                            },
                            "block_id": f"{ConversationButtonActions.invite_user}-active-{idx}",
                            "accessory": {
                                "type": "button",
                                "text": {"type": "plain_text", "text": "Join Incident"},
                                "value": f"{incident.id}",
                            },
                        }
                    )
                except Exception as e:
                    log.exception(e)

        blocks.append(
            {
                "type": "context",
                "elements": [
                    {
                        "type": "mrkdwn",
                        "text": f"For more information about active incidents, please visit the active incidents status <{DISPATCH_UI_URL}/incidents/status|page>.",
                    }
                ],
            }
        )
    else:
        blocks.append(
            {
                "type": "section",
                "text": {
                    "type": "mrkdwn",
                    "text": INCIDENT_DAILY_SUMMARY_NO_ACTIVE_INCIDENTS_DESCRIPTION,
                },
            }
        )

    blocks.append({"type": "divider"})
    blocks.append(
        {
            "type": "section",
            "text": {
                "type": "mrkdwn",
                "text": f"*{INCIDENT_DAILY_SUMMARY_STABLE_CLOSED_INCIDENTS_DESCRIPTION}*",
            },
        }
    )

    hours = 24
    stable_incidents = get_all_last_x_hours_by_status(
        db_session=db_session, status=IncidentStatus.stable, hours=hours
    )
    closed_incidents = get_all_last_x_hours_by_status(
        db_session=db_session, status=IncidentStatus.closed, hours=hours
    )
    if stable_incidents or closed_incidents:
        for idx, incident in enumerate(stable_incidents):
            ticket_weblink = resolve_attr(incident, "ticket.weblink")

            if incident.visibility == Visibility.open:
                try:
                    blocks.append(
                        {
                            "type": "section",
                            "text": {
                                "type": "mrkdwn",
                                "text": (
                                    f"*<{ticket_weblink}|{incident.name}>*\n"
                                    f"*Title*: {incident.title}\n"
                                    f"*Type*: {incident.incident_type.name}\n"
                                    f"*Priority*: {incident.incident_priority.name}\n"
                                    f"*Incident Commander*: <{incident.commander.weblink}|{incident.commander.name}>\n"
                                    f"*Status*: {incident.status}"
                                ),
                            },
                            "block_id": f"{ConversationButtonActions.invite_user}-stable-{idx}",
                            "accessory": {
                                "type": "button",
                                "text": {"type": "plain_text", "text": "Join Incident"},
                                "value": f"{incident.id}",
                            },
                        }
                    )
                except Exception as e:
                    log.exception(e)

        for incident in closed_incidents:
            ticket_weblink = resolve_attr(incident, "ticket.weblink")

            if incident.visibility == Visibility.open:
                try:
                    blocks.append(
                        {
                            "type": "section",
                            "text": {
                                "type": "mrkdwn",
                                "text": (
                                    f"*<{ticket_weblink}|{incident.name}>*\n"
                                    f"*Title*: {incident.title}\n"
                                    f"*Type*: {incident.incident_type.name}\n"
                                    f"*Priority*: {incident.incident_priority.name}\n"
                                    f"*Incident Commander*: <{incident.commander.weblink}|{incident.commander.name}>\n"
                                    f"*Status*: {incident.status}"
                                ),
                            },
                        }
                    )
                except Exception as e:
                    log.exception(e)
    else:
        blocks.append(
            {
                "type": "section",
                "text": {
                    "type": "mrkdwn",
                    "text": INCIDENT_DAILY_SUMMARY_NO_STABLE_CLOSED_INCIDENTS_DESCRIPTION,
                },
            }
        )

    # NOTE INCIDENT_ONCALL_SERVICE_ID is optional
    if INCIDENT_ONCALL_SERVICE_ID:
        oncall_service = service_service.get_by_external_id(
            db_session=db_session, external_id=INCIDENT_ONCALL_SERVICE_ID
        )

        if not oncall_service:
            log.warning(
                "INCIDENT_ONCALL_SERVICE_ID configured in the .env file, but not found in the database. Did you create the oncall service in the UI?"
            )
            return

        oncall_plugin = plugin_service.get_active(db_session=db_session, plugin_type="oncall")
        if not oncall_plugin:
            log.warning(
                f"Unable to resolve the oncall, INCIDENT_ONCALL_SERVICE_ID configured, but associated plugin ({oncall_plugin.slug}) is not enabled."
            )
            return

        if oncall_plugin.slug != oncall_service.type:
            log.warning(
                f"Unable to resolve the oncall. Oncall plugin enabled not of type {oncall_plugin.slug}."
            )
            return

        oncall_email = oncall_plugin.instance.get(service_id=INCIDENT_ONCALL_SERVICE_ID)
        oncall_individual = individual_service.resolve_user_by_email(oncall_email, db_session)

        blocks.append(
            {
                "type": "context",
                "elements": [
                    {
                        "type": "mrkdwn",
                        "text": f"For any questions about this notification, please reach out to <{oncall_individual['weblink']}|{oncall_individual['fullname']}> (current on-call)",
                    }
                ],
            }
        )

    plugin = plugin_service.get_active(db_session=db_session, plugin_type="conversation")

    for c in INCIDENT_NOTIFICATION_CONVERSATIONS:
        plugin.instance.send(c, "Incident Daily Summary", {}, "", blocks=blocks)
Пример #12
0
def daily_report(db_session=None):
    """
    Creates and sends incident daily reports based on notifications.
    """
    # we fetch all active, stable and closed incidents
    active_incidents = get_all_by_status(db_session=db_session, status=IncidentStatus.active.value)
    stable_incidents = get_all_last_x_hours_by_status(
        db_session=db_session, status=IncidentStatus.stable.value, hours=24
    )
    closed_incidents = get_all_last_x_hours_by_status(
        db_session=db_session, status=IncidentStatus.closed.value, hours=24
    )
    incidents = active_incidents + stable_incidents + closed_incidents

    # we map incidents to notification filters
    incidents_notification_filters_mapping = defaultdict(lambda: defaultdict(lambda: []))
    notifications = notification_service.get_all_enabled(db_session=db_session)
    for incident in incidents:
        for notification in notifications:
            for search_filter in notification.filters:
                match = search_service.match(
                    db_session=db_session,
                    filter_spec=search_filter.expression,
                    class_instance=incident,
                )
                if match:
                    incidents_notification_filters_mapping[notification.id][
                        search_filter.id
                    ].append(incident)

            if not notification.filters:
                incidents_notification_filters_mapping[notification.id][0].append(incident)

    # we create and send an incidents daily report for each notification filter
    for notification_id, search_filter_dict in incidents_notification_filters_mapping.items():
        for search_filter_id, incidents in search_filter_dict.items():
            items_grouped = []
            items_grouped_template = INCIDENT

            for idx, incident in enumerate(incidents):
                try:
                    item = {
                        "commander_fullname": incident.commander.individual.name,
                        "commander_team": incident.commander.team,
                        "commander_weblink": incident.commander.individual.weblink,
                        "incident_id": incident.id,
                        "name": incident.name,
                        "priority": incident.incident_priority.name,
                        "priority_description": incident.incident_priority.description,
                        "status": incident.status,
                        "ticket_weblink": resolve_attr(incident, "ticket.weblink"),
                        "title": incident.title,
                        "type": incident.incident_type.name,
                        "type_description": incident.incident_type.description,
                    }

                    if incident.status != IncidentStatus.closed.value:
                        item.update(
                            {
                                "button_text": "Join Incident",
                                "button_value": str(incident.id),
                                "button_action": f"{ConversationButtonActions.invite_user.value}-{incident.status}-{idx}",
                            }
                        )

                    items_grouped.append(item)
                except Exception as e:
                    log.exception(e)

            notification_kwargs = {
                "contact_fullname": DISPATCH_HELP_EMAIL,
                "contact_weblink": DISPATCH_HELP_EMAIL,
                "items_grouped": items_grouped,
                "items_grouped_template": items_grouped_template,
            }

            notification_params = {
                "text": INCIDENT_DAILY_REPORT_TITLE,
                "type": MessageType.incident_daily_report,
                "template": INCIDENT_DAILY_REPORT,
                "kwargs": notification_kwargs,
            }

            notification = notification_service.get(
                db_session=db_session, notification_id=notification_id
            )

            notification_service.send(
                db_session=db_session,
                notification=notification,
                notification_params=notification_params,
            )
Пример #13
0
def incident_stable_status_flow(incident: Incident, db_session=None):
    """Runs the incident stable flow."""
    # we set the stable time
    incident.stable_at = datetime.utcnow()

    # set time immediately
    db_session.add(incident)
    db_session.commit()

    if incident.incident_review_document:
        log.debug("Incident review document already created... skipping creation.")
        return

    storage_plugin = plugin_service.get_active(db_session=db_session, plugin_type="storage")
    if not storage_plugin:
        log.warning("Incident review document not created, no storage plugin enabled.")
        return

    # we create a copy of the incident review document template and we move it to the incident storage
    incident_review_document_name = f"{incident.name} - Post Incident Review Document"
    template = document_service.get_incident_review_template(db_session=db_session)

    # incident review document is optional
    if not template:
        log.warning("No incident review template specificed.")
        return

    incident_review_document = storage_plugin.instance.copy_file(
        folder_id=incident.storage.resource_id,
        file_id=template.resource_id,
        name=incident_review_document_name,
    )

    incident_review_document.update(
        {
            "name": incident_review_document_name,
            "resource_type": INCIDENT_RESOURCE_INCIDENT_REVIEW_DOCUMENT,
        }
    )

    storage_plugin.instance.move_file(
        new_folder_id=incident.storage.resource_id,
        file_id=incident_review_document["id"],
    )

    event_service.log(
        db_session=db_session,
        source=storage_plugin.title,
        description="Incident review document added to storage",
        incident_id=incident.id,
    )

    document_in = DocumentCreate(
        name=incident_review_document["name"],
        resource_id=incident_review_document["id"],
        resource_type=incident_review_document["resource_type"],
        weblink=incident_review_document["weblink"],
    )
    incident.documents.append(
        document_service.create(db_session=db_session, document_in=document_in)
    )

    event_service.log(
        db_session=db_session,
        source="Dispatch Core App",
        description="Incident review document added to incident",
        incident_id=incident.id,
    )

    # we update the incident review document
    document_plugin = plugin_service.get_active(db_session=db_session, plugin_type="document")
    if document_plugin:
        document_plugin.instance.update(
            incident.incident_review_document.resource_id,
            name=incident.name,
            priority=incident.incident_priority.name,
            status=incident.status,
            type=incident.incident_type.name,
            title=incident.title,
            description=incident.description,
            commander_fullname=incident.commander.name,
            conversation_weblink=resolve_attr(incident, "conversation.weblink"),
            document_weblink=resolve_attr(incident, "incident_document.weblink"),
            storage_weblink=resolve_attr(incident, "storage.weblink"),
            ticket_weblink=resolve_attr(incident, "ticket.weblink"),
            conference_weblink=resolve_attr(incident, "conference.weblink"),
            conference_challenge=resolve_attr(incident, "conference.challendge"),
        )
    else:
        log.warning("No document plugin enabled, could not update template.")

    # we send a notification about the incident review document to the conversation
    send_incident_review_document_notification(
        incident.conversation.channel_id,
        incident.incident_review_document.weblink,
        db_session,
    )

    db_session.add(incident)
    db_session.commit()
Пример #14
0
def incident_create_flow(*, incident_id: int, checkpoint: str = None, db_session=None):
    """Creates all resources required for new incidents."""
    incident = incident_service.get(db_session=db_session, incident_id=incident_id)

    # create the incident ticket
    ticket = create_incident_ticket(incident, db_session)
    if ticket:
        incident.ticket = ticket_service.create(
            db_session=db_session, ticket_in=TicketCreate(**ticket)
        )

        # we set the incident name
        incident.name = ticket["resource_id"]

    # get the incident participants based on incident type and priority
    individual_participants, team_participants = get_incident_participants(incident, db_session)

    # add individuals to incident
    for individual in individual_participants:
        participant_flows.add_participant(
            user_email=individual.email, incident_id=incident.id, db_session=db_session
        )

    event_service.log(
        db_session=db_session,
        source="Dispatch Core App",
        description="Incident participants added to incident",
        incident_id=incident.id,
    )

    # we create the participant groups (tactical and notification)
    individual_participants = [x.individual for x in incident.participants]
    participant_emails = [x.individual.email for x in incident.participants]

    group_plugin = plugin_service.get_active(db_session=db_session, plugin_type="participant-group")
    tactical_group = None
    notification_group = None
    if group_plugin:
        try:
            tactical_group, notification_group = create_participant_groups(
                incident, individual_participants, team_participants, db_session
            )

            for g in [tactical_group, notification_group]:
                group_in = GroupCreate(
                    name=g["name"],
                    email=g["email"],
                    resource_type=g["resource_type"],
                    resource_id=g["resource_id"],
                    weblink=g["weblink"],
                )
                incident.groups.append(
                    group_service.create(db_session=db_session, group_in=group_in)
                )

            event_service.log(
                db_session=db_session,
                source="Dispatch Core App",
                description="Tactical and notification groups added to incident",
                incident_id=incident.id,
            )
        except Exception as e:
            event_service.log(
                db_session=db_session,
                source="Dispatch Core App",
                description=f"Creation of tactical and notification groups failed. Reason: {e}",
                incident_id=incident.id,
            )
            log.exception(e)

    storage_plugin = plugin_service.get_active(db_session=db_session, plugin_type="storage")
    if storage_plugin:
        # we create storage resource
        if group_plugin:
            storage = create_incident_storage(
                incident, [tactical_group["email"], notification_group["email"]], db_session
            )
        else:
            # we don't have a group so add participants directly
            storage = create_incident_storage(incident, participant_emails, db_session)

        incident.storage = storage_service.create(
            db_session=db_session,
            resource_id=storage["resource_id"],
            resource_type=storage["resource_type"],
            weblink=storage["weblink"],
        )

        event_service.log(
            db_session=db_session,
            source="Dispatch Core App",
            description="Storage added to incident",
            incident_id=incident.id,
        )

        # we create collaboration documents, don't fail the whole flow if this fails
        try:
            collab_documents = create_collaboration_documents(incident, db_session)

            for d in collab_documents:
                document_in = DocumentCreate(
                    name=d["name"],
                    resource_id=d["resource_id"],
                    resource_type=d["resource_type"],
                    weblink=d["weblink"],
                )
                incident.documents.append(
                    document_service.create(db_session=db_session, document_in=document_in)
                )

            event_service.log(
                db_session=db_session,
                source="Dispatch Core App",
                description="Documents added to incident",
                incident_id=incident.id,
            )
        except Exception as e:
            event_service.log(
                db_session=db_session,
                source="Dispatch Core App",
                description=f"Creation of incident documents failed. Reason: {e}",
                incident_id=incident.id,
            )
            log.exception(e)

    conference_plugin = plugin_service.get_active(db_session=db_session, plugin_type="conference")
    if conference_plugin:
        try:
            participants = participant_emails
            
            if group_plugin:
                # we use the tactical group email if the group plugin is enabled
                participants = [tactical_group["email"]]
                
            conference = create_conference(incident, participants, db_session)

            conference_in = ConferenceCreate(
                resource_id=conference["resource_id"],
                resource_type=conference["resource_type"],
                weblink=conference["weblink"],
                conference_id=conference["id"],
                conference_challenge=conference["challenge"],
            )
            incident.conference = conference_service.create(
                db_session=db_session, conference_in=conference_in
            )

            event_service.log(
                db_session=db_session,
                source="Dispatch Core App",
                description="Conference added to incident",
                incident_id=incident.id,
            )
        except Exception as e:
            event_service.log(
                db_session=db_session,
                source="Dispatch Core App",
                description=f"Creation of incident conference failed. Reason: {e}",
                incident_id=incident.id,
            )
            log.exception(e)

    # we create the conversation for real-time communications

    conversation_plugin = plugin_service.get_active(
        db_session=db_session, plugin_type="conversation"
    )
    if conversation_plugin:
        try:
            conversation = create_conversation(incident, participant_emails, db_session)

            conversation_in = ConversationCreate(
                resource_id=conversation["resource_id"],
                resource_type=conversation["resource_type"],
                weblink=conversation["weblink"],
                channel_id=conversation["id"],
            )
            incident.conversation = conversation_service.create(
                db_session=db_session, conversation_in=conversation_in
            )

            event_service.log(
                db_session=db_session,
                source="Dispatch Core App",
                description="Conversation added to incident",
                incident_id=incident.id,
            )

            # we set the conversation topic
            set_conversation_topic(incident, db_session)
        except Exception as e:
            event_service.log(
                db_session=db_session,
                source="Dispatch Core App",
                description=f"Creation of incident conversation failed. Reason: {e}",
                incident_id=incident.id,
            )
            log.exception(e)

    db_session.add(incident)
    db_session.commit()

    # we update the incident ticket
    update_external_incident_ticket(incident, db_session)

    # we update the investigation document
    document_plugin = plugin_service.get_active(db_session=db_session, plugin_type="document")
    if document_plugin:
        if incident.incident_document:
            try:
                document_plugin.instance.update(
                    incident.incident_document.resource_id,
                    name=incident.name,
                    priority=incident.incident_priority.name,
                    status=incident.status,
                    type=incident.incident_type.name,
                    title=incident.title,
                    description=incident.description,
                    commander_fullname=incident.commander.name,
                    conversation_weblink=resolve_attr(incident, "conversation.weblink"),
                    document_weblink=resolve_attr(incident, "incident_document.weblink"),
                    storage_weblink=resolve_attr(incident, "storage.weblink"),
                    ticket_weblink=resolve_attr(incident, "ticket.weblink"),
                    conference_weblink=resolve_attr(incident, "conference.weblink"),
                    conference_challenge=resolve_attr(incident, "conference.challendge"),
                )
            except Exception as e:
                event_service.log(
                    db_session=db_session,
                    source="Dispatch Core App",
                    description=f"Incident documents rendering failed. Reason: {e}",
                    incident_id=incident.id,
                )
                log.exception(e)

    if incident.visibility == Visibility.open:
        send_incident_notifications(incident, db_session)
        event_service.log(
            db_session=db_session,
            source="Dispatch Core App",
            description="Incident notifications sent",
            incident_id=incident.id,
        )

    suggested_document_items = get_suggested_document_items(incident.id, db_session)

    for participant in incident.participants:
        # we announce the participant in the conversation
        # should protect ourselves from failures of any one participant
        try:
            send_incident_participant_announcement_message(
                participant.individual.email, incident.id, db_session
            )

            # we send the welcome messages to the participant
            send_incident_welcome_participant_messages(
                participant.individual.email, incident.id, db_session
            )

            send_incident_suggested_reading_messages(
                incident.id, suggested_document_items, participant.individual.email, db_session
            )

        except Exception as e:
            log.exception(e)

    event_service.log(
        db_session=db_session,
        source="Dispatch Core App",
        description="Participants announced and welcome messages sent",
        incident_id=incident.id,
    )
Пример #15
0
def daily_summary(db_session=None):
    """Fetches all open incidents and provides a daily summary."""

    blocks = []
    blocks.append({
        "type": "section",
        "text": {
            "type": "mrkdwn",
            "text": f"*{INCIDENT_DAILY_SUMMARY_DESCRIPTION}*"
        },
    })

    active_incidents = get_all_by_status(db_session=db_session,
                                         status=IncidentStatus.active)
    if active_incidents:
        blocks.append({
            "type": "section",
            "text": {
                "type": "mrkdwn",
                "text":
                f"*{INCIDENT_DAILY_SUMMARY_ACTIVE_INCIDENTS_DESCRIPTION}*",
            },
        })
        for idx, incident in enumerate(active_incidents):
            ticket_weblink = resolve_attr(incident, "ticket.weblink")
            if incident.visibility == Visibility.open:
                try:
                    blocks.append({
                        "type": "section",
                        "text": {
                            "type":
                            "mrkdwn",
                            "text":
                            (f"*<{ticket_weblink}|{incident.name}>*\n"
                             f"*Title*: {incident.title}\n"
                             f"*Type*: {incident.incident_type.name}\n"
                             f"*Priority*: {incident.incident_priority.name}\n"
                             f"*Incident Commander*: <{incident.commander.weblink}|{incident.commander.name}>"
                             ),
                        },
                        "block_id":
                        f"{ConversationButtonActions.invite_user}-active-{idx}",
                        "accessory": {
                            "type": "button",
                            "text": {
                                "type": "plain_text",
                                "text": "Join Incident"
                            },
                            "value": f"{incident.id}",
                        },
                    })
                except Exception as e:
                    log.exception(e)
    else:
        blocks.append({
            "type": "section",
            "text": {
                "type": "mrkdwn",
                "text": INCIDENT_DAILY_SUMMARY_NO_ACTIVE_INCIDENTS_DESCRIPTION,
            },
        })

    blocks.append({"type": "divider"})
    blocks.append({
        "type": "section",
        "text": {
            "type":
            "mrkdwn",
            "text":
            f"*{INCIDENT_DAILY_SUMMARY_STABLE_CLOSED_INCIDENTS_DESCRIPTION}*",
        },
    })

    hours = 24
    stable_incidents = get_all_last_x_hours_by_status(
        db_session=db_session, status=IncidentStatus.stable, hours=hours)
    closed_incidents = get_all_last_x_hours_by_status(
        db_session=db_session, status=IncidentStatus.closed, hours=hours)
    if stable_incidents or closed_incidents:
        for idx, incident in enumerate(stable_incidents):
            ticket_weblink = resolve_attr(incident, "ticket.weblink")

            if incident.visibility == Visibility.open:
                try:
                    blocks.append({
                        "type": "section",
                        "text": {
                            "type":
                            "mrkdwn",
                            "text":
                            (f"*<{ticket_weblink}|{incident.name}>*\n"
                             f"*Title*: {incident.title}\n"
                             f"*Type*: {incident.incident_type.name}\n"
                             f"*Priority*: {incident.incident_priority.name}\n"
                             f"*Incident Commander*: <{incident.commander.weblink}|{incident.commander.name}>\n"
                             f"*Status*: {incident.status}"),
                        },
                        "block_id":
                        f"{ConversationButtonActions.invite_user}-stable-{idx}",
                        "accessory": {
                            "type": "button",
                            "text": {
                                "type": "plain_text",
                                "text": "Join Incident"
                            },
                            "value": f"{incident.id}",
                        },
                    })
                except Exception as e:
                    log.exception(e)

        for incident in closed_incidents:
            ticket_weblink = resolve_attr(incident, "ticket.weblink")

            if incident.visibility == Visibility.open:
                try:
                    blocks.append({
                        "type": "section",
                        "text": {
                            "type":
                            "mrkdwn",
                            "text":
                            (f"*<{ticket_weblink}|{incident.name}>*\n"
                             f"*Title*: {incident.title}\n"
                             f"*Type*: {incident.incident_type.name}\n"
                             f"*Priority*: {incident.incident_priority.name}\n"
                             f"*Incident Commander*: <{incident.commander.weblink}|{incident.commander.name}>\n"
                             f"*Status*: {incident.status}"),
                        },
                    })
                except Exception as e:
                    log.exception(e)
    else:
        blocks.append({
            "type": "section",
            "text": {
                "type":
                "mrkdwn",
                "text":
                INCIDENT_DAILY_SUMMARY_NO_STABLE_CLOSED_INCIDENTS_DESCRIPTION,
            },
        })

    # NOTE INCIDENT_ONCALL_SERVICE_ID is optional
    if INCIDENT_ONCALL_SERVICE_ID:
        oncall_service = service_service.get_by_external_id(
            db_session=db_session, external_id=INCIDENT_ONCALL_SERVICE_ID)

        oncall_plugin = plugins.get(oncall_service.type)
        oncall_email = oncall_plugin.get(service_id=INCIDENT_ONCALL_SERVICE_ID)

        oncall_individual = individual_service.resolve_user_by_email(
            oncall_email, db_session)

        blocks.append({
            "type":
            "context",
            "elements": [{
                "type":
                "mrkdwn",
                "text":
                f"For any questions about this notification, please reach out to <{oncall_individual['weblink']}|{oncall_individual['fullname']}> (current on-call)",
            }],
        })

    plugin = plugin_service.get_active(db_session=db_session,
                                       plugin_type="conversation")

    for c in INCIDENT_NOTIFICATION_CONVERSATIONS:
        plugin.instance.send(c,
                             "Incident Daily Summary", {},
                             "",
                             blocks=blocks)
Пример #16
0
def daily_report(db_session=None):
    """
    Creates and sends an incident daily report.
    """
    active_incidents = get_all_by_status(db_session=db_session,
                                         status=IncidentStatus.active)
    stable_incidents = get_all_last_x_hours_by_status(
        db_session=db_session, status=IncidentStatus.stable, hours=24)
    closed_incidents = get_all_last_x_hours_by_status(
        db_session=db_session, status=IncidentStatus.closed, hours=24)
    incidents = active_incidents + stable_incidents + closed_incidents

    items_grouped_template = INCIDENT
    items_grouped = []
    for idx, incident in enumerate(incidents):
        if incident.visibility == Visibility.open:
            try:
                item = {
                    "commander_fullname": incident.commander.individual.name,
                    "commander_weblink": incident.commander.individual.weblink,
                    "incident_id": incident.id,
                    "name": incident.name,
                    "priority": incident.incident_priority.name,
                    "priority_description":
                    incident.incident_priority.description,
                    "status": incident.status,
                    "ticket_weblink": resolve_attr(incident, "ticket.weblink"),
                    "title": incident.title,
                    "type": incident.incident_type.name,
                    "type_description": incident.incident_type.description,
                }

                if incident.status != IncidentStatus.closed.value:
                    item.update({
                        "button_text":
                        "Join Incident",
                        "button_value":
                        str(incident.id),
                        "button_action":
                        f"{ConversationButtonActions.invite_user.value}-{incident.status}-{idx}",
                    })

                items_grouped.append(item)
            except Exception as e:
                log.exception(e)

    notification_kwargs = {
        "items_grouped": items_grouped,
        "items_grouped_template": items_grouped_template,
    }

    notification_params = {
        "text": INCIDENT_DAILY_REPORT_TITLE,
        "type": MessageType.incident_daily_report,
        "template": INCIDENT_DAILY_REPORT,
        "kwargs": notification_kwargs,
    }

    notification_service.filter_and_send(
        db_session=db_session,
        class_instance=incident,
        notification_params=notification_params)