def test_simple_notification(self): responses.add( 'POST', 'https://alert.victorops.com/integrations/generic/20131114/alert/secret-api-key/everyone', body=SUCCESS) self.plugin.set_option('api_key', 'secret-api-key', self.project) self.plugin.set_option('routing_key', 'everyone', self.project) group = self.create_group(message='Hello world', culprit='foo.bar') event = self.create_event(group=group, message='Hello world', tags={'level': 'warning'}) rule = Rule.objects.create(project=self.project, label='my rule') notification = Notification(event=event, rule=rule) with self.options({'system.url-prefix': 'http://example.com'}): self.plugin.notify(notification) request = responses.calls[0].request payload = json.loads(request.body) assert { 'message_type': 'WARNING', 'entity_id': group.id, 'entity_display_name': 'Hello world', 'monitoring_tool': 'sentry', 'state_message': 'Stacktrace\n-----------\n\nStacktrace (most recent call last):\n\n File "sentry/models/foo.py", line 29, in build_msg\n string_max_length=self.string_max_length)\n\nMessage\n-----------\n\nHello world', 'timestamp': int(event.datetime.strftime('%s')), } == payload
def rule_notify(self, event, futures): rules = [] for future in futures: rules.append(future.rule) if not future.kwargs: continue raise NotImplementedError( 'The default behavior for notification de-duplication does not support args' ) project = event.group.project if hasattr(self, 'notify_digest') and digests.enabled(project): get_digest_option = lambda key: ProjectOption.objects.get_value( project, get_digest_option_key(self.get_conf_key(), key), ) digest_key = unsplit_key(self, event.group.project) immediate_delivery = digests.add( digest_key, event_to_record(event, rules), increment_delay=get_digest_option('increment_delay'), maximum_delay=get_digest_option('maximum_delay'), ) if immediate_delivery: deliver_digest.delay(digest_key) else: notification = Notification(event=event, rules=rules) self.notify(notification)
def test_notification_without_culprit(self): responses.add('POST', 'http://example.com/slack') self.plugin.set_option('webhook', 'http://example.com/slack', self.project) self.plugin.set_option('exclude_culprit', True, self.project) group = self.create_group(message='Hello world', culprit='foo.bar') event = self.create_event(group=group, message='Hello world', tags={'level': 'warning'}) rule = Rule.objects.create(project=self.project, label='my rule') notification = Notification(event=event, rule=rule) with self.options({'system.url-prefix': 'http://example.com'}): self.plugin.notify(notification) request = responses.calls[0].request payload = json.loads(parse_qs(request.body)['payload'][0]) assert payload == { 'username': '******', 'attachments': [ { 'color': '#f18500', 'fields': [ { 'short': True, 'value': 'foo Bar', 'title': 'Project' }, ], 'fallback': '[foo Bar] Hello world', 'title': 'Hello world', 'title_link': 'http://example.com/baz/bar/issues/1/', }, ], }
def test_simple_notification(self): responses.add( "POST", "https://alert.victorops.com/integrations/generic/20131114/alert/secret-api-key/everyone", body=SUCCESS, ) self.plugin.set_option("api_key", "secret-api-key", self.project) self.plugin.set_option("routing_key", "everyone", self.project) group = self.create_group(message="Hello world", culprit="foo.bar") event = self.create_event(group=group, message="Hello world", tags={"level": "warning"}) rule = Rule.objects.create(project=self.project, label="my rule") notification = Notification(event=event, rule=rule) with self.options({"system.url-prefix": "http://example.com"}): self.plugin.notify(notification) request = responses.calls[0].request payload = json.loads(request.body) assert { "message_type": "WARNING", "entity_id": group.id, "entity_display_name": "Hello world", "monitoring_tool": "sentry", "state_message": 'Stacktrace\n-----------\n\nStacktrace (most recent call last):\n\n File "sentry/models/foo.py", line 29, in build_msg\n string_max_length=self.string_max_length)\n\nMessage\n-----------\n\nHello world', "timestamp": int(event.datetime.strftime("%s")), "issue_url": "http://example.com/organizations/baz/issues/%s/" % group.id, } == payload
def test_notify_users_does_email(self, _send_mail): group = Group( id=2, first_seen=timezone.now(), last_seen=timezone.now(), project=self.project, message='hello world', logger='root', ) event = Event( group=group, message=group.message, project=self.project, datetime=group.last_seen, ) notification = Notification(event=event) with self.options({'system.url-prefix': 'http://example.com'}): self.plugin.notify(notification) assert _send_mail.call_count is 1 args, kwargs = _send_mail.call_args self.assertEquals(kwargs.get('project'), self.project) self.assertEquals(kwargs.get('group'), group) assert kwargs.get('subject') == u"[{0} {1}] ERROR: hello world".format( self.team.name, self.project.name)
def test_simple_notification(self): responses.add(responses.POST, 'http://example.com') group = self.create_group(message='Hello world') event = self.create_event(group=group, message='Hello world', tags={'level': 'warning'}, id=24) rule = Rule.objects.create(project=self.project, label='my rule') notification = Notification(event=event, rule=rule) self.project.update_option('webhooks:urls', 'http://example.com') self.plugin.notify(notification) assert len(responses.calls) == 1 payload = json.loads(responses.calls[0].request.body) assert payload['level'] == 'warning' assert payload['message'] == 'Hello world' assert payload['event']['id'] == 24 assert payload['event']['event_id'] == event.event_id
def test_notify_users_does_email(self, _send_mail): group = Group( id=2, first_seen=timezone.now(), last_seen=timezone.now(), project=self.project, message='hello world', logger='root', short_id=2, ) event = Event( group=group, message=group.message, project=self.project, datetime=group.last_seen, data={'tags': [ ('level', 'error'), ]}, ) notification = Notification(event=event) with self.options({'system.url-prefix': 'http://example.com'}): self.plugin.notify(notification) assert _send_mail.call_count is 1 args, kwargs = _send_mail.call_args self.assertEquals(kwargs.get('project'), self.project) self.assertEquals(kwargs.get('reference'), group) assert kwargs.get('subject') == u'BAR-2 - hello world'
def test_multiline_error(self, _send_mail): event_manager = EventManager({"message": "hello world\nfoo bar", "level": "error"}) event_manager.normalize() event_data = event_manager.get_data() event_type = event_manager.get_event_type() event_data["type"] = event_type.key event_data["metadata"] = event_type.get_metadata(event_data) group = Group( id=2, first_seen=timezone.now(), last_seen=timezone.now(), project=self.project, message=event_manager.get_search_message(), logger="root", short_id=2, data={"type": event_type.key, "metadata": event_type.get_metadata(event_data)}, ) event = Event( group=group, message=group.message, project=self.project, datetime=group.last_seen, data=event_data, ) notification = Notification(event=event) with self.options({"system.url-prefix": "http://example.com"}): self.plugin.notify(notification) assert _send_mail.call_count is 1 args, kwargs = _send_mail.call_args assert kwargs.get("subject") == u"BAR-2 - hello world"
def test_multiline_error(self, _send_mail): group = Group( id=2, first_seen=timezone.now(), last_seen=timezone.now(), project=self.project, message='hello world\nfoo bar', logger='root', ) event = Event( group=group, message=group.message, project=self.project, datetime=group.last_seen, ) notification = Notification(event=event) with self.settings(SENTRY_URL_PREFIX='http://example.com'): self.plugin.notify(notification) _send_mail.assert_called_once() args, kwargs = _send_mail.call_args assert kwargs.get('subject') == u"[{0} {1}] ERROR: hello world".format( self.team.name, self.project.name)
def test_simple_notification(self): responses.add('POST', 'https://api.pushsafer.net/1/messages.json', body=SUCCESS) self.plugin.set_option('privatekey', 'XXXXXXXXXXXXXXXXXXXX', self.project) group = self.create_group(message='Hello world', culprit='foo.bar') event = self.create_event( group=group, message='Hello world', tags={'level': 'warning'}, ) rule = Rule.objects.create(project=self.project, label='my rule') notification = Notification(event=event, rule=rule) with self.options({'system.url-prefix': 'http://example.com'}): self.plugin.notify(notification) request = responses.calls[0].request payload = parse_qs(request.body) assert payload == { 'm': ['{}\n\nTags: level=warning'.format(event.get_legacy_message())], 't': ['Bar: Hello world'], 'u': ['http://example.com/baz/bar/issues/{}/'.format(group.id)], 'ut': ['Issue Details'], 'd': ['a'], 'k': ['XXXXXXXXXXXXXXXXXXXX'], }
def test_notify_users_renders_interfaces_with_utf8(self, _send_mail): group = Group( id=2, first_seen=timezone.now(), last_seen=timezone.now(), project=self.project, ) stacktrace = Mock(spec=Stacktrace) stacktrace.to_email_html.return_value = u'רונית מגן' stacktrace.get_title.return_value = 'Stacktrace' event = Event() event.group = group event.project = self.project event.message = 'hello world' event.interfaces = {'sentry.interfaces.Stacktrace': stacktrace} notification = Notification(event=event) with self.settings(SENTRY_URL_PREFIX='http://example.com'): self.plugin.notify(notification) stacktrace.get_title.assert_called_once_with() stacktrace.to_email_html.assert_called_once_with(event)
def test_emergency_notification(self): responses.add('POST', 'https://api.pushover.net/1/messages.json', body=SUCCESS) self.plugin.set_option('userkey', 'abcdef', self.project) self.plugin.set_option('apikey', 'ghijkl', self.project) self.plugin.set_option('priority', '2', self.project) self.plugin.set_option('expire', 90, self.project) self.plugin.set_option('retry', 30, self.project) group = self.create_group(message='Hello world', culprit='foo.bar') event = self.create_event( group=group, message='Hello world', tags={'level': 'warning'}, ) rule = Rule.objects.create(project=self.project, label='my rule') notification = Notification(event=event, rule=rule) with self.options({'system.url-prefix': 'http://example.com'}): self.plugin.notify(notification) request = responses.calls[0].request payload = parse_qs(request.body) assert payload == { 'message': ['{}\n\nTags: level=warning'.format(event.get_legacy_message())], 'title': ['Bar: Hello world'], 'url': ['http://example.com/baz/bar/issues/{}/'.format(group.id)], 'url_title': ['Issue Details'], 'priority': ['2'], 'user': ['abcdef'], 'token': ['ghijkl'], 'expire': ['90'], 'retry': ['30'], }
def test_multiline_error(self, _send_mail): group = Group( id=2, first_seen=timezone.now(), last_seen=timezone.now(), project=self.project, message='hello world\nfoo bar', logger='root', ) event = Event( group=group, message=group.message, project=self.project, datetime=group.last_seen, data={ 'tags': [ ('level', 'error'), ] }, ) notification = Notification(event=event) with self.options({'system.url-prefix': 'http://example.com'}): self.plugin.notify(notification) assert _send_mail.call_count is 1 args, kwargs = _send_mail.call_args assert kwargs.get('subject') == u"[{0} {1}] ERROR: hello world".format( self.team.name, self.project.name)
def test_notify_users_renders_interfaces_with_utf8(self, _send_mail, _to_email_html, _get_title): group = self.create_group(first_seen=timezone.now(), last_seen=timezone.now(), project=self.project) _to_email_html.return_value = u"רונית מגן" _get_title.return_value = "Stacktrace" event = Event( group_id=group.id, project_id=self.project.id, message="Soubor ji\xc5\xbe existuje", # Create interface so get_title will be called on it. data={"stacktrace": { "frames": [{}] }}, ) notification = Notification(event=event) with self.options({"system.url-prefix": "http://example.com"}): self.plugin.notify(notification) _get_title.assert_called_once_with() _to_email_html.assert_called_once_with(event)
def test_notify_users_renders_interfaces_with_utf8_fix_issue_422(self, _send_mail): group = Group( id=2, first_seen=timezone.now(), last_seen=timezone.now(), project=self.project, ) stacktrace = Mock(spec=Stacktrace) stacktrace.to_email_html.return_value = u'רונית מגן' stacktrace.get_title.return_value = 'Stacktrace' event = Event() event.group = group event.project = self.project event.message = 'Soubor ji\xc5\xbe existuje' event.interfaces = {'sentry.interfaces.Stacktrace': stacktrace} notification = Notification(event=event) with self.options({'system.url-prefix': 'http://example.com'}): self.plugin.notify(notification) stacktrace.get_title.assert_called_once_with() stacktrace.to_email_html.assert_called_once_with(event)
def test_simple_notification(self): responses.add( 'GET', 'https://events.pagerduty.com/generic/2010-04-15/create_event.json', body=INVALID_METHOD) responses.add( 'POST', 'https://events.pagerduty.com/generic/2010-04-15/create_event.json', body=SUCCESS) self.plugin.set_option('service_key', 'abcdef', self.project) group = self.create_group(message='Hello world', culprit='foo.bar') event = self.create_event(group=group, message='Hello world', tags={'level': 'warning'}) rule = Rule.objects.create(project=self.project, label='my rule') notification = Notification(event=event, rule=rule) with self.options({'system.url-prefix': 'http://example.com'}): self.plugin.notify(notification) request = responses.calls[0].request payload = json.loads(request.body) assert payload == { 'client_url': 'http://example.com', 'event_type': 'trigger', 'contexts': [{ 'text': 'Issue Details', 'href': 'http://example.com/baz/bar/issues/{}/'.format(group.id), 'type': 'link', }], 'incident_key': group.id, 'client': 'sentry', 'details': { 'project': self.project.name, 'release': None, 'url': 'http://example.com/baz/bar/issues/1/', 'culprit': group.culprit, 'platform': None, 'event_id': event.event_id, 'tags': { 'level': 'warning', }, 'datetime': event.datetime.strftime('%Y-%m-%dT%H:%M:%S.%fZ'), }, 'service_key': 'abcdef', 'description': event.get_legacy_message(), }
def assert_notify(self, event, emails_sent_to): mail.outbox = [] with self.options({'system.url-prefix': 'http://example.com'}), self.tasks(): self.plugin.notify(Notification(event=event)) assert len(mail.outbox) == len(emails_sent_to) assert sorted(email.to[0] for email in mail.outbox) == sorted(emails_sent_to)
def rule_notify(self, event, futures): rules = [] for future in futures: rules.append(future.rule) if not future.kwargs: continue raise NotImplementedError( 'The default behavior for notification de-duplication does not support args' ) if hasattr(self, 'notify_digest'): project = event.group.project # If digest delivery is disabled, we still need to send a # notification -- we also need to check rate limits, since # ``should_notify`` skips this step if the plugin supports digests. if not features.has('projects:digests:deliver', project): if self.__is_rate_limited(event.group, event): logger = logging.getLogger('sentry.plugins.{0}'.format( self.get_conf_key())) logger.info( 'Notification for project %r dropped due to rate limiting', project) return notification = Notification(event=event, rules=rules) self.notify(notification) if features.has('projects:digests:store', project): get_digest_option = lambda key: ProjectOption.objects.get_value( project, '{0}:digests:{1}'.format(self.get_conf_key(), key), ) digest_key = unsplit_key(self, event.group.project) immediate_delivery = digests.add( digest_key, event_to_record(event, rules), increment_delay=get_digest_option('increment_delay'), maximum_delay=get_digest_option('maximum_delay'), ) if immediate_delivery: deliver_digest.delay(digest_key) else: notification = Notification(event=event, rules=rules) self.notify(notification)
def after(self, event, state): group = event.group notification = Notification(event=event, rule=self.rule) for plugin in self.get_plugins(): if not safe_execute(plugin.should_notify, group=group, event=event): continue safe_execute(plugin.notify, notification)
def rule_notify(self, event, futures): rules = [] for future in futures: rules.append(future.rule) if not future.kwargs: continue raise NotImplementedError('The default behavior for notification de-duplication does not support args') notification = Notification(event=event, rules=rules) self.notify(notification)
def test_notify_users_with_utf8_subject(self): group = self.create_group(message=u'רונית מגן') event = self.create_event(group=group, message='Hello world') notification = Notification(event=event) with self.settings(SENTRY_URL_PREFIX='http://example.com'): self.plugin.notify(notification) msg = mail.outbox[0] assert msg.subject == u'[Sentry] [foo Bar] ERROR: רונית מגן'
def test_notify_users_with_utf8_subject(self): group = self.create_group(message=u'רונית מגן') event = self.create_event(group=group, message='Hello world') notification = Notification(event=event) with self.options({'system.url-prefix': 'http://example.com'}): self.plugin.notify(notification) msg = mail.outbox[0] assert msg.subject == u'[Sentry] [foo Bar] ERROR: רונית מגן'
def test_notify_users_with_utf8_subject(self): group = self.create_group(message="Hello world") event = self.create_event(group=group, message=u"רונית מגן", tags={"level": "error"}) notification = Notification(event=event) with self.options({"system.url-prefix": "http://example.com"}), self.tasks(): self.plugin.notify(notification) assert len(mail.outbox) == 1 msg = mail.outbox[0] assert msg.subject == u"[Sentry] BAR-1 - רונית מגן"
def test_notify_users_with_utf8_subject(self): group = self.create_group(message='Hello world') event = self.create_event(group=group, message=u'רונית מגן', tags={'level': 'error'}) notification = Notification(event=event) with self.options({'system.url-prefix': 'http://example.com'}), self.tasks(): self.plugin.notify(notification) assert len(mail.outbox) == 1 msg = mail.outbox[0] assert msg.subject == u'[Sentry] BAR-1 - רונית מגן'
def send_notification_helper(self): self.initialized_plugin.set_option('receivers', '123', self.project) self.initialized_plugin.set_option('api_token', 'api:token', self.project) self.initialized_plugin.set_option( 'message_template', '*[Sentry]* {project_name} {tag[level]}: {title}\n{message}\n{url}', self.project, ) event = create_sample_event(self.project, platform='python') notification = Notification(event=event) with patch('requests.sessions.Session.request') as request: self.initialized_plugin.notify(notification) return request
def test_simple_notification(self): group = self.create_group(message='Hello world') event = self.create_event(group=group, message='Hello world', tags={'level': 'error'}) rule = Rule.objects.create(project=self.project, label='my rule') notification = Notification(event=event, rule=rule) with self.options({'system.url-prefix': 'http://example.com'}), self.tasks(): self.plugin.notify(notification) msg = mail.outbox[0] assert msg.subject == '[Sentry] [foo Bar] ERROR: Hello world' assert 'my rule' in msg.alternatives[0][0]
def test_simple_notification(self): group = self.create_group(message="Hello world") event = self.create_event(group=group, message="Hello world", tags={"level": "error"}) rule = Rule.objects.create(project=self.project, label="my rule") notification = Notification(event=event, rule=rule) with self.options({"system.url-prefix": "http://example.com"}), self.tasks(): self.plugin.notify(notification) msg = mail.outbox[0] assert msg.subject == "[Sentry] BAR-1 - Hello world" assert "my rule" in msg.alternatives[0][0]
def rule_notify(self, event, futures): from sentry.models import ProjectOption # Django 1.9 setup issue rules = [] extra = { 'event_id': event.id, 'group_id': event.group_id, 'plugin': self.slug, } log_event = 'dispatched' for future in futures: rules.append(future.rule) extra['rule_id'] = future.rule.id if not future.kwargs: continue raise NotImplementedError( 'The default behavior for notification de-duplication does not support args' ) project = event.group.project extra['project_id'] = project.id if hasattr(self, 'notify_digest') and digests.enabled(project): def get_digest_option(key): return ProjectOption.objects.get_value( project, get_digest_option_key(self.get_conf_key(), key), ) digest_key = unsplit_key(self, event.group.project) extra['digest_key'] = digest_key immediate_delivery = digests.add( digest_key, event_to_record(event, rules), increment_delay=get_digest_option('increment_delay'), maximum_delay=get_digest_option('maximum_delay'), ) if immediate_delivery: deliver_digest.delay(digest_key) else: log_event = 'digested' else: notification = Notification( event=event, rules=rules, ) self.notify(notification) self.logger.info('notification.%s' % log_event, extra=extra)
def test_notify_with_suspect_commits(self): release = self.create_release(project=self.project, user=self.user) group = self.create_group(project=self.project, first_release=release) event = self.create_event(group=group, tags={'sentry:release': release.version}) notification = Notification(event=event) with self.tasks(), self.options({'system.url-prefix': 'http://example.com'}), self.feature('organizations:suggested-commits'): self.plugin.notify(notification) assert len(mail.outbox) >= 1 msg = mail.outbox[-1] assert 'Suspect Commits' in msg.body
def test_simple_notification(self): group = self.create_group(message='Hello world') event = self.create_event(group=group, message='Hello world') rule = Rule.objects.create(project=self.project, label='my rule') notification = Notification(event=event, rule=rule) with self.settings(SENTRY_URL_PREFIX='http://example.com'): self.plugin.notify(notification) msg = mail.outbox[0] assert msg.subject == '[Sentry] [foo Bar] ERROR: Hello world' print dir(msg) assert 'my rule' in msg.alternatives[0][0]