|
@@ -1,12 +1,15 @@
|
|
|
import logging
|
|
|
from typing import Any, Mapping, Optional, Set
|
|
|
|
|
|
-from sentry import options
|
|
|
+from sentry import digests, options
|
|
|
+from sentry.digests import get_option_key as get_digest_option_key
|
|
|
+from sentry.digests.notifications import event_to_record, unsplit_key
|
|
|
from sentry.models import ProjectOption, User
|
|
|
from sentry.notifications.activity.base import ActivityNotification
|
|
|
from sentry.notifications.base import BaseNotification
|
|
|
from sentry.notifications.notify import register_notification_provider
|
|
|
from sentry.notifications.rules import AlertRuleNotification
|
|
|
+from sentry.tasks.digests import deliver_digest
|
|
|
from sentry.types.integrations import ExternalProviders
|
|
|
from sentry.utils import json
|
|
|
from sentry.utils.email import MessageBuilder, group_id_to_email
|
|
@@ -70,7 +73,7 @@ def log_message(notification: BaseNotification, user: User) -> None:
|
|
|
"user_id": user.id,
|
|
|
}
|
|
|
if notification.group:
|
|
|
- extra.update({"group": notification.group.id})
|
|
|
+ extra.update({"group_id": notification.group.id})
|
|
|
|
|
|
if isinstance(notification, AlertRuleNotification):
|
|
|
extra.update(
|
|
@@ -79,6 +82,9 @@ def log_message(notification: BaseNotification, user: User) -> None:
|
|
|
"target_identifier": notification.target_identifier,
|
|
|
}
|
|
|
)
|
|
|
+ if len(notification.rules):
|
|
|
+ extra.update({"rule_id": notification.rules[0].id})
|
|
|
+
|
|
|
elif isinstance(notification, ActivityNotification):
|
|
|
extra.update({"activity": notification.activity})
|
|
|
|
|
@@ -106,6 +112,41 @@ def get_context(
|
|
|
return context
|
|
|
|
|
|
|
|
|
+def get_digest_option(notification: AlertRuleNotification, key: str) -> str:
|
|
|
+ return ProjectOption.objects.get_value(notification.project, get_digest_option_key("mail", key))
|
|
|
+
|
|
|
+
|
|
|
+def get_digest_key(notification: AlertRuleNotification) -> str:
|
|
|
+ return unsplit_key(
|
|
|
+ notification.project, notification.target_type, notification.target_identifier
|
|
|
+ )
|
|
|
+
|
|
|
+
|
|
|
+def add_to_digest(notification: AlertRuleNotification) -> None:
|
|
|
+ digest_key = get_digest_key(notification)
|
|
|
+ immediate_delivery = digests.add(
|
|
|
+ digest_key,
|
|
|
+ event_to_record(notification.event, notification.rules),
|
|
|
+ increment_delay=get_digest_option(notification, "increment_delay"),
|
|
|
+ maximum_delay=get_digest_option(notification, "maximum_delay"),
|
|
|
+ )
|
|
|
+ if immediate_delivery:
|
|
|
+ deliver_digest.delay(digest_key)
|
|
|
+
|
|
|
+ action_key = "dispatched" if immediate_delivery else "digested"
|
|
|
+ logger.info(
|
|
|
+ f"mail.adapter.notification.{action_key}",
|
|
|
+ extra={
|
|
|
+ "group": notification.group.id,
|
|
|
+ "project_id": notification.project.id,
|
|
|
+ "is_from_mail_action_adapter": True,
|
|
|
+ "target_type": notification.target_type.value,
|
|
|
+ "target_identifier": notification.target_identifier,
|
|
|
+ "rule_id": notification.rules[0].id,
|
|
|
+ },
|
|
|
+ )
|
|
|
+
|
|
|
+
|
|
|
@register_notification_provider(ExternalProviders.EMAIL)
|
|
|
def send_notification_as_email(
|
|
|
notification: BaseNotification,
|
|
@@ -113,6 +154,9 @@ def send_notification_as_email(
|
|
|
shared_context: Mapping[str, Any],
|
|
|
extra_context_by_user_id: Optional[Mapping[int, Mapping[str, Any]]],
|
|
|
) -> None:
|
|
|
+ if isinstance(notification, AlertRuleNotification) and digests.enabled(notification.project):
|
|
|
+ return add_to_digest(notification)
|
|
|
+
|
|
|
headers = get_headers(notification)
|
|
|
subject = get_subject_with_prefix(notification)
|
|
|
type = get_email_type(notification)
|