Allow Telegram DMs without channel connection (#142)
* allow posting DM messages to Telegram without connecting a channel * fix get_channel_for_alert_group, add tests * add docs on usage without channel connection
This commit is contained in:
parent
7169b1b563
commit
c8964188e7
7 changed files with 74 additions and 48 deletions
|
|
@ -20,6 +20,8 @@ You can use Telegram to deliver alert group notifications to a dedicated channel
|
|||
|
||||
Each alert group notification is assigned a dedicated discussion. Users can perform notification actions (acknowledge, resolve, silence), create reports, and discuss alerts in the comments section of the discussions.
|
||||
|
||||
In case an integration route is not configured to use a Telegram channel, users will receive messages with alert group contents, logs and actions in their DMs.
|
||||
|
||||
## Connect to Telegram
|
||||
|
||||
Connect your organization's Telegram account to your Grafana OnCall instance by following the instructions provided in OnCall. You can use the following steps as a reference.
|
||||
|
|
|
|||
|
|
@ -1557,14 +1557,6 @@ class AlertGroup(AlertGroupSlackRenderingMixin, EscalationSnapshotMixin, models.
|
|||
else:
|
||||
return True
|
||||
|
||||
@property
|
||||
def notify_in_telegram_enabled(self):
|
||||
channel_filter = self.channel_filter_with_respect_to_escalation_snapshot
|
||||
if channel_filter is not None:
|
||||
return channel_filter.notify_in_telegram
|
||||
else:
|
||||
return True
|
||||
|
||||
@property
|
||||
def is_presented_in_slack(self):
|
||||
return self.slack_message and self.channel.organization.slack_team_identity
|
||||
|
|
|
|||
|
|
@ -162,10 +162,6 @@ def notify_user_task(
|
|||
user_to_be_notified_in_slack = (
|
||||
notification_policy.notify_by == UserNotificationPolicy.NotificationChannel.SLACK
|
||||
)
|
||||
user_to_be_notified_in_telegram = (
|
||||
notification_policy.notify_by == UserNotificationPolicy.NotificationChannel.TELEGRAM
|
||||
)
|
||||
|
||||
if user_to_be_notified_in_slack and alert_group.notify_in_slack_enabled is False:
|
||||
log_record = UserNotificationPolicyLogRecord(
|
||||
author=user,
|
||||
|
|
@ -178,18 +174,6 @@ def notify_user_task(
|
|||
notification_channel=notification_policy.notify_by,
|
||||
notification_error_code=UserNotificationPolicyLogRecord.ERROR_NOTIFICATION_POSTING_TO_SLACK_IS_DISABLED,
|
||||
)
|
||||
elif user_to_be_notified_in_telegram and alert_group.notify_in_telegram_enabled is False:
|
||||
log_record = UserNotificationPolicyLogRecord(
|
||||
author=user,
|
||||
type=UserNotificationPolicyLogRecord.TYPE_PERSONAL_NOTIFICATION_FAILED,
|
||||
notification_policy=notification_policy,
|
||||
alert_group=alert_group,
|
||||
reason=reason,
|
||||
slack_prevent_posting=prevent_posting_to_thread,
|
||||
notification_step=notification_policy.step,
|
||||
notification_channel=notification_policy.notify_by,
|
||||
notification_error_code=UserNotificationPolicyLogRecord.ERROR_NOTIFICATION_POSTING_TO_TELEGRAM_IS_DISABLED,
|
||||
)
|
||||
else:
|
||||
log_record = UserNotificationPolicyLogRecord(
|
||||
author=user,
|
||||
|
|
@ -292,8 +276,7 @@ def perform_notification(log_record_pk):
|
|||
)
|
||||
|
||||
elif notification_channel == UserNotificationPolicy.NotificationChannel.TELEGRAM:
|
||||
if alert_group.notify_in_telegram_enabled is True:
|
||||
TelegramToUserConnector.notify_user(user, alert_group, notification_policy)
|
||||
TelegramToUserConnector.notify_user(user, alert_group, notification_policy)
|
||||
|
||||
# TODO: restore email notifications
|
||||
# elif notification_channel == UserNotificationPolicy.NotificationChannel.EMAIL:
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ class UserNotificationPolicyLogRecord(models.Model):
|
|||
ERROR_NOTIFICATION_MAIL_DELIVERY_FAILED,
|
||||
ERROR_NOTIFICATION_TELEGRAM_BOT_IS_DELETED,
|
||||
ERROR_NOTIFICATION_POSTING_TO_SLACK_IS_DISABLED,
|
||||
ERROR_NOTIFICATION_POSTING_TO_TELEGRAM_IS_DISABLED,
|
||||
ERROR_NOTIFICATION_POSTING_TO_TELEGRAM_IS_DISABLED, # deprecated
|
||||
ERROR_NOTIFICATION_IN_SLACK,
|
||||
ERROR_NOTIFICATION_IN_SLACK_TOKEN_ERROR,
|
||||
ERROR_NOTIFICATION_IN_SLACK_USER_NOT_IN_SLACK,
|
||||
|
|
@ -213,6 +213,7 @@ class UserNotificationPolicyLogRecord(models.Model):
|
|||
self.notification_error_code
|
||||
== UserNotificationPolicyLogRecord.ERROR_NOTIFICATION_POSTING_TO_TELEGRAM_IS_DISABLED
|
||||
):
|
||||
# deprecated
|
||||
result += f"failed to notify {user_verbal} in Telegram, because the incident is not posted to Telegram (reason: Telegram is disabled for the route)"
|
||||
elif (
|
||||
self.notification_error_code
|
||||
|
|
|
|||
|
|
@ -66,11 +66,6 @@ class AlertGroupTelegramRepresentative(AlertGroupAbstractRepresentative):
|
|||
if not isinstance(alert_group, AlertGroup):
|
||||
alert_group = AlertGroup.all_objects.get(pk=alert_group)
|
||||
|
||||
# telegram notification is disabled for channel filter
|
||||
if alert_group.notify_in_telegram_enabled is False:
|
||||
logger.debug(f"Skipping alert group with id {alert_group.pk} since notify_in_telegram is disabled")
|
||||
return
|
||||
|
||||
messages_to_edit = alert_group.telegram_messages.filter(
|
||||
message_type__in=(
|
||||
TelegramMessage.LOG_MESSAGE,
|
||||
|
|
@ -90,13 +85,6 @@ class AlertGroupTelegramRepresentative(AlertGroupAbstractRepresentative):
|
|||
if not isinstance(log_record, AlertGroupLogRecord):
|
||||
log_record = AlertGroupLogRecord.objects.get(pk=log_record)
|
||||
|
||||
# telegram notification is disabled for channel filter
|
||||
if log_record.alert_group.notify_in_telegram_enabled is False:
|
||||
logger.debug(
|
||||
f"Skipping alert group with id {log_record.alert_group.pk} since notify_in_telegram is disabled"
|
||||
)
|
||||
return
|
||||
|
||||
instance = cls(log_record)
|
||||
if instance.is_applicable():
|
||||
handler = instance.get_handler()
|
||||
|
|
@ -104,16 +92,7 @@ class AlertGroupTelegramRepresentative(AlertGroupAbstractRepresentative):
|
|||
|
||||
@staticmethod
|
||||
def on_create_alert(**kwargs):
|
||||
Alert = apps.get_model("alerts", "Alert")
|
||||
|
||||
alert_pk = kwargs["alert"]
|
||||
alert = Alert.objects.get(pk=alert_pk)
|
||||
|
||||
# telegram notification is disabled for channel filter
|
||||
if alert.group.notify_in_telegram_enabled is False:
|
||||
logger.debug(f"Skipping alert with id {alert.pk} since notify_in_telegram is disabled")
|
||||
return
|
||||
|
||||
on_create_alert_telegram_representative_async.apply_async((alert_pk,))
|
||||
|
||||
def get_handler(self):
|
||||
|
|
|
|||
|
|
@ -82,6 +82,9 @@ class TelegramToOrganizationConnector(models.Model):
|
|||
if alert_group.channel_filter is None:
|
||||
return default_channel
|
||||
|
||||
if not alert_group.channel_filter.notify_in_telegram:
|
||||
return None
|
||||
|
||||
return alert_group.channel_filter.telegram_channel or default_channel
|
||||
|
||||
def make_channel_default(self, author):
|
||||
|
|
|
|||
66
engine/apps/telegram/tests/test_channel_connector.py
Normal file
66
engine/apps/telegram/tests/test_channel_connector.py
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
import pytest
|
||||
|
||||
from apps.telegram.models import TelegramMessage, TelegramToOrganizationConnector
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_get_channel_for_alert_group(
|
||||
make_organization, make_alert_receive_channel, make_channel_filter, make_alert_group, make_telegram_channel
|
||||
):
|
||||
organization = make_organization()
|
||||
|
||||
make_telegram_channel(organization, is_default_channel=True)
|
||||
telegram_channel = make_telegram_channel(organization)
|
||||
|
||||
alert_receive_channel = make_alert_receive_channel(organization)
|
||||
channel_filter = make_channel_filter(
|
||||
alert_receive_channel, notify_in_telegram=True, telegram_channel=telegram_channel
|
||||
)
|
||||
|
||||
alert_group = make_alert_group(alert_receive_channel, channel_filter=channel_filter)
|
||||
|
||||
channel = TelegramToOrganizationConnector.get_channel_for_alert_group(alert_group)
|
||||
assert channel is telegram_channel
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_get_channel_telegram_disabled_for_route(
|
||||
make_organization, make_alert_receive_channel, make_channel_filter, make_alert_group, make_telegram_channel
|
||||
):
|
||||
organization = make_organization()
|
||||
|
||||
telegram_channel = make_telegram_channel(organization)
|
||||
|
||||
alert_receive_channel = make_alert_receive_channel(organization)
|
||||
channel_filter = make_channel_filter(
|
||||
alert_receive_channel, notify_in_telegram=False, telegram_channel=telegram_channel
|
||||
)
|
||||
|
||||
alert_group = make_alert_group(alert_receive_channel, channel_filter=channel_filter)
|
||||
|
||||
channel = TelegramToOrganizationConnector.get_channel_for_alert_group(alert_group)
|
||||
assert channel is None
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_get_channel_for_alert_group_dm_messages_exist(
|
||||
make_organization,
|
||||
make_alert_receive_channel,
|
||||
make_channel_filter,
|
||||
make_alert_group,
|
||||
make_telegram_channel,
|
||||
make_telegram_message,
|
||||
):
|
||||
organization = make_organization()
|
||||
|
||||
telegram_channel = make_telegram_channel(organization)
|
||||
alert_receive_channel = make_alert_receive_channel(organization)
|
||||
channel_filter = make_channel_filter(
|
||||
alert_receive_channel, notify_in_telegram=True, telegram_channel=telegram_channel
|
||||
)
|
||||
|
||||
alert_group = make_alert_group(alert_receive_channel, channel_filter=channel_filter)
|
||||
make_telegram_message(alert_group=alert_group, message_type=TelegramMessage.PERSONAL_MESSAGE)
|
||||
|
||||
channel = TelegramToOrganizationConnector.get_channel_for_alert_group(alert_group)
|
||||
assert channel is None
|
||||
Loading…
Add table
Reference in a new issue