def notify_digest(self, project, digest, target_type, target_identifier=None): metrics.incr("mail_adapter.notify_digest") user_ids = self.get_send_to(project, target_type, target_identifier)[ ExternalProviders.EMAIL ] logger.info( "mail.adapter.notify_digest", extra={ "project_id": project.id, "target_type": target_type.value, "target_identifier": target_identifier, "user_ids": user_ids, }, ) for user_id, digest in get_personalized_digests(target_type, project.id, digest, user_ids): start, end, counts = get_digest_metadata(digest) # If there is only one group in this digest (regardless of how many # rules it appears in), we should just render this using the single # notification template. If there is more than one record for a group, # just choose the most recent one. if len(counts) == 1: group = next(iter(counts)) record = max( itertools.chain.from_iterable( groups.get(group, []) for groups in digest.values() ), key=lambda record: record.timestamp, ) notification = Notification(record.value.event, rules=record.value.rules) return self.notify(notification, target_type, target_identifier) context = { "start": start, "end": end, "project": project, "digest": digest, "counts": counts, } headers = { "X-Sentry-Project": project.slug, "X-SMTPAPI": json.dumps({"category": "digest_email"}), } group = next(iter(counts)) subject = self.get_digest_subject(group, counts, start) self.add_unsubscribe_link(context, user_id, project, "alert_digest") self._send_mail( subject=subject, template="sentry/emails/digests/body.txt", html_template="sentry/emails/digests/body.html", project=project, reference=project, headers=headers, type="notify.digest", context=context, send_to=[user_id], )
def assert_get_personalized_digests(self, project, digest, user_ids, expected_result): result_user_ids = [] for user_id, user_digest in get_personalized_digests(project.id, digest, user_ids): assert user_id in expected_result assert expected_result[user_id] == get_event_from_groups_in_digest(user_digest) result_user_ids.append(user_id) assert sorted(expected_result.keys()) == sorted(result_user_ids)
def assert_get_personalized_digests(self, project, digest, user_ids, expected_result): result_user_ids = [] for user_id, user_digest in get_personalized_digests(project.id, digest, user_ids): assert user_id in expected_result assert expected_result[user_id] == get_event_from_groups_in_digest(user_digest) result_user_ids.append(user_id) assert sorted(expected_result.keys()) == sorted(result_user_ids)
def notify_digest(self, project, digest, target_type, target_identifier=None): user_ids = self.get_send_to(project, target_type, target_identifier) for user_id, digest in get_personalized_digests( project.id, digest, user_ids): start, end, counts = get_digest_metadata(digest) # If there is only one group in this digest (regardless of how many # rules it appears in), we should just render this using the single # notification template. If there is more than one record for a group, # just choose the most recent one. if len(counts) == 1: group = six.next(iter(counts)) record = max( itertools.chain.from_iterable( groups.get(group, []) for groups in six.itervalues(digest)), key=lambda record: record.timestamp, ) notification = Notification(record.value.event, rules=record.value.rules) return self.notify(notification, target_type, target_identifier) context = { "start": start, "end": end, "project": project, "digest": digest, "counts": counts, } headers = {"X-Sentry-Project": project.slug} group = six.next(iter(counts)) subject = self.get_digest_subject(group, counts, start) self.add_unsubscribe_link(context, user_id, project, "alert_digest") self._send_mail( subject=subject, template="sentry/emails/digests/body.txt", html_template="sentry/emails/digests/body.html", project=project, reference=project, headers=headers, type="notify.digest", context=context, send_to=[user_id], )
def assert_get_personalized_digests( self, project, digest, user_ids, expected_result, target_type=ActionTargetType.ISSUE_OWNERS ): result_user_ids = [] for user_id, user_digest in get_personalized_digests( target_type, project.id, digest, user_ids ): assert user_id in expected_result assert {e.event_id for e in get_event_from_groups_in_digest(user_digest)} == { e.event_id for e in expected_result[user_id] } result_user_ids.append(user_id) assert sorted(expected_result.keys()) == sorted(result_user_ids)
def notify_digest(self, project, digest): user_ids = self.get_send_to(project) for user_id, digest in get_personalized_digests(project.id, digest, user_ids): start, end, counts = get_digest_metadata(digest) # If there is only one group in this digest (regardless of how many # rules it appears in), we should just render this using the single # notification template. If there is more than one record for a group, # just choose the most recent one. if len(counts) == 1: group = six.next(iter(counts)) record = max( itertools.chain.from_iterable( groups.get(group, []) for groups in six.itervalues(digest) ), key=lambda record: record.timestamp, ) notification = Notification(record.value.event, rules=record.value.rules) return self.notify(notification) context = { 'start': start, 'end': end, 'project': project, 'digest': digest, 'counts': counts, } headers = { 'X-Sentry-Project': project.slug, } group = six.next(iter(counts)) subject = self.get_digest_subject(group, counts, start) self.add_unsubscribe_link(context, user_id, project) self._send_mail( subject=subject, template='sentry/emails/digests/body.txt', html_template='sentry/emails/digests/body.html', project=project, reference=project, headers=headers, type='notify.digest', context=context, send_to=[user_id], )
def get_extra_context(self, recipient_ids: Iterable[int]) -> Mapping[int, Mapping[str, Any]]: extra_context = {} for user_id, digest in get_personalized_digests( self.target_type, self.project.id, self.digest, recipient_ids ): start, end, counts = get_digest_metadata(digest) group = next(iter(counts)) extra_context[user_id] = { "counts": counts, "digest": digest, "group": group, "end": end, "start": start, } return extra_context
def test_team_without_members(self): team = self.create_team() project = self.create_project(teams=[team], fire_project_created=True) ProjectOwnership.objects.create( project_id=project.id, schema=dump_schema([Rule(Matcher("path", "*.cpp"), [Owner("team", team.slug)])]), fallthrough=True, ) rule = project.rule_set.all()[0] records = [ event_to_record(event, (rule,)) for event in self.create_events_from_filenames( project, ["hello.py", "goodbye.py", "hola.py", "adios.py"] ) ] digest = build_digest(project, sort_records(records)) user_ids = [member.user_id for member in team.member_set] assert not user_ids for user_id, user_digest in get_personalized_digests(project.id, digest, user_ids): assert False # no users in this team no digests should be processed
def test_team_without_members(self): team = self.create_team() project = self.create_project(teams=[team]) ProjectOwnership.objects.create( project_id=project.id, schema=dump_schema([ Rule(Matcher('path', '*.cpp'), [ Owner('team', team.slug), ]), ]), fallthrough=True, ) rule = project.rule_set.all()[0] records = [ event_to_record(event, (rule, )) for event in self.create_events(timezone.now(), project, [ 'hello.py', 'goodbye.py', 'hola.py', 'adios.py']) ] digest = build_digest(project, sort_records(records)) user_ids = [member.user_id for member in team.member_set] assert not user_ids for user_id, user_digest in get_personalized_digests(project.id, digest, user_ids): assert False # no users in this team no digests should be processed
def test_team_without_members(self): team = self.create_team() project = self.create_project(teams=[team]) ProjectOwnership.objects.create( project_id=project.id, schema=dump_schema([ Rule(Matcher('path', '*.cpp'), [ Owner('team', team.slug), ]), ]), fallthrough=True, ) rule = project.rule_set.all()[0] records = [ event_to_record(event, (rule, )) for event in self.create_events(timezone.now( ), project, ['hello.py', 'goodbye.py', 'hola.py', 'adios.py']) ] digest = build_digest(project, sort_records(records)) user_ids = [member.user_id for member in team.member_set] assert not user_ids for user_id, user_digest in get_personalized_digests( project.id, digest, user_ids): assert False # no users in this team no digests should be processed