def test_latest_release_with_environment(self): event = self.get_event() self.create_release( project=event.group.project, version="1", date_added=datetime(2020, 9, 1, 3, 8, 24, 880386), environments=[self.environment], ) new_release = self.create_release( project=event.group.project, version="2", date_added=datetime(2020, 9, 2, 3, 8, 24, 880386), environments=[self.environment], ) other_env_release = self.create_release( project=event.group.project, version="4", date_added=datetime(2020, 9, 3, 3, 8, 24, 880386), ) event.data["tags"] = (("release", new_release.version),) environment_rule = self.get_rule(rule=Rule(environment_id=self.environment.id)) self.assertPasses(environment_rule, event) event.data["tags"] = (("release", other_env_release.version),) environment_rule = self.get_rule(rule=Rule(environment_id=self.environment.id)) self.assertDoesNotPass(environment_rule, event)
def _run_test(self, minutes, data, passes, add_events=False): if not self.environment: self.environment = self.create_environment(name="prod") rule = self.get_rule(data=data, rule=Rule(environment_id=None)) environment_rule = self.get_rule(data=data, rule=Rule(environment_id=self.environment.id)) event = self.store_event( data={ "fingerprint": ["something_random"], "timestamp": iso_format(before_now(minutes=minutes)), "user": {"id": uuid4().hex}, }, project_id=self.project.id, ) if add_events: self.increment( event, data["value"] + 1, environment=self.environment.name, timestamp=now() - timedelta(minutes=minutes), ) self.increment( event, data["value"] + 1, timestamp=now() - timedelta(minutes=minutes), ) with freeze_time(before_now(minutes=minutes)): if passes: self.assertPasses(rule, event) self.assertPasses(environment_rule, event) else: self.assertDoesNotPass(rule, event) self.assertDoesNotPass(environment_rule, event)
def test_one_day(self, now): now.return_value = datetime(2016, 8, 1, 0, 0, 0, 0, tzinfo=pytz.utc) event = self.get_event() value = 10 data = {"interval": "1d", "value": six.text_type(value)} rule = self.get_rule(data=data, rule=Rule(environment_id=None)) environment_id = 1 environment_rule = self.get_rule( data=data, rule=Rule(environment_id=environment_id)) self.increment(event, value + 1, environment_id=environment_id, timestamp=now() - timedelta(hours=36)) self.assertDoesNotPass(rule, event) self.assertDoesNotPass(environment_rule, event) self.increment(event, value, environment_id=environment_id) self.assertDoesNotPass(rule, event) self.assertDoesNotPass(environment_rule, event) self.increment(event, 1, environment_id=environment_id) self.assertPasses(rule, event) self.assertPasses(environment_rule, event) self.assertDoesNotPass( self.get_rule(data=data, rule=Rule(environment_id=0)), event)
def _run_test(self, minutes, data, passes, add_events=False): if not self.environment or self.environment.name != "prod": self.environment = self.create_environment(name="prod") if not hasattr(self, "test_event"): self.test_event = self.store_event( data={ "fingerprint": ["something_random"], "timestamp": iso_format(before_now(minutes=minutes)), "user": { "id": uuid4().hex }, "environment": self.environment.name, }, project_id=self.project.id, ) if add_events: self.increment( self.test_event, max(1, int(minutes / 2)) - 1, environment=self.environment.name, timestamp=now() - timedelta(minutes=minutes), ) rule = self.get_rule(data=data, rule=Rule(environment_id=None)) environment_rule = self.get_rule( data=data, rule=Rule(environment_id=self.environment.id)) if passes: self.assertPasses(rule, self.test_event) self.assertPasses(environment_rule, self.test_event) else: self.assertDoesNotPass(rule, self.test_event) self.assertDoesNotPass(environment_rule, self.test_event)
def test_more_than_zero(self, now): now.return_value = datetime(2016, 8, 1, 0, 0, 0, 0, tzinfo=pytz.utc) event = self.get_event() data = { 'interval': '1m', 'value': six.text_type('0'), } rule = self.get_rule( data=data, rule=Rule(environment_id=None), ) environment_id = 1 environment_rule = self.get_rule( data=data, rule=Rule(environment_id=environment_id), ) self.assertDoesNotPass(rule, event) self.assertDoesNotPass(environment_rule, event) self.increment(event, 1, environment_id=environment_id) self.assertPasses(rule, event) self.assertPasses(environment_rule, event) self.assertDoesNotPass( self.get_rule( data=data, rule=Rule(environment_id=0), ), event, )
def test_comparison_empty_comparison_period(self): with freeze_time(before_now(minutes=0)): # Test data is 1 event in the current period and 0 events in the comparison period. This # should always result in 0 and never fire. event = self.store_event( data={ "fingerprint": ["something_random"], "timestamp": iso_format(before_now(minutes=1)), "user": { "id": uuid4().hex }, }, project_id=self.project.id, ) data = { "interval": "1h", "value": 0, "comparisonType": "percent", "comparisonInterval": "1d", } rule = self.get_rule(data=data, rule=Rule(environment_id=None)) self.assertDoesNotPass(rule, event) data = { "interval": "1h", "value": 100, "comparisonType": "percent", "comparisonInterval": "1d", } rule = self.get_rule(data=data, rule=Rule(environment_id=None)) self.assertDoesNotPass(rule, event)
def post(self, request, project): """ Create a rule Create a new rule for the given project. {method} {path} {{ "name": "My rule name", "conditions": [], "actions": [], "actionMatch": "all" }} """ serializer = RuleSerializer( context={'project': project}, data=request.DATA, ) if serializer.is_valid(): rule = serializer.save(rule=Rule()) return Response(serialize(rule, request.user)) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def post(self, request, project): """ Create a rule Create a new rule for the given project. {method} {path} {{ "name": "My rule name", "conditions": [], "actions": [], "actionMatch": "all" }} """ serializer = RuleSerializer(context={"project": project}, data=request.data) if serializer.is_valid(): rule = serializer.save(rule=Rule()) self.create_audit_entry( request=request, organization=project.organization, target_object=rule.id, event=AuditLogEntryEvent.RULE_ADD, data=rule.get_audit_log_data(), ) alert_rule_created.send_robust( user=request.user, project=project, rule=rule, sender=self ) return Response(serialize(rule, request.user)) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def get(self, request, organization, team, project, rule_id=None): if rule_id: try: rule = Rule.objects.get(project=project, id=rule_id) except Rule.DoesNotExist: path = reverse('sentry-project-rules', args=[organization.slug, project.slug]) return self.redirect(path) else: rule = Rule(project=project) action_list = [] condition_list = [] # TODO: conditions need to be based on actions for rule_type, rule_cls in rules: node = rule_cls(project) context = { 'id': node.id, 'label': node.label, 'html': node.render_form(), } if rule_type.startswith('condition/'): condition_list.append(context) elif rule_type.startswith('action/'): action_list.append(context) context = { 'rule': rule, 'page': 'rules', 'action_list': json.dumps(action_list), 'condition_list': json.dumps(condition_list), } return self.respond('sentry/projects/rules/new.html', context)
def get_rules(self): """ Get all of the rules for this project from the DB (or cache). :return: a list of `Rule`s """ return Rule.get_for_project(self.project.id)
def new_event(request): org = Organization( id=1, slug='example', name='Example', ) team = Team( id=1, slug='example', name='Example', organization=org, ) project = Project( id=1, slug='example', name='Example', team=team, organization=org, ) group = Group( id=1, project=project, message='This is an example event.', level=logging.ERROR, ) event = Event( id=1, project=project, group=group, message=group.message, data=load_data('python'), ) rule = Rule(label="An example rule") interface_list = [] for interface in event.interfaces.itervalues(): body = interface.to_email_html(event) if not body: continue interface_list.append((interface.get_title(), mark_safe(body))) preview = MailPreview( html_template='sentry/emails/error.html', text_template='sentry/emails/error.html', context={ 'rule': rule, 'group': group, 'event': event, 'link': 'http://example.com/link', 'interfaces': interface_list, 'tags': event.get_tags(), 'project_label': project.name, }, ) return render_to_response('sentry/debug/mail/preview.html', { 'preview': preview, })
def test_one_hour(self, now): now.return_value = datetime(2016, 8, 1, 0, 0, 0, 0, tzinfo=pytz.utc) event = self.get_event() value = 10 data = { 'interval': '1h', 'value': six.text_type(value), } rule = self.get_rule( data=data, rule=Rule(environment_id=None), ) environment_id = 1 environment_rule = self.get_rule( data=data, rule=Rule(environment_id=environment_id), ) self.increment( event, value + 1, environment_id=environment_id, timestamp=now() - timedelta(minutes=90), ) self.assertDoesNotPass(rule, event) self.assertDoesNotPass(environment_rule, event) self.increment(event, value, environment_id=environment_id) self.assertDoesNotPass(rule, event) self.assertDoesNotPass(environment_rule, event) self.increment(event, 1, environment_id=environment_id) self.assertPasses(rule, event) self.assertPasses(environment_rule, event) self.assertDoesNotPass( self.get_rule( data=data, rule=Rule(environment_id=0), ), event, )
def test_comparison(self): with freeze_time(before_now(minutes=0)): self._make_sessions(10, 1) # Create sessions for previous period self._make_sessions(10, 60 * 24 + 20) # Test data is 2 events in the current period and 1 events in the comparison period. # Number of sessions is 20 in each period, so current period is 20% of sessions, prev # is 10%. Overall a 100% increase comparitively. event = self.store_event( data={ "fingerprint": ["something_random"], "timestamp": iso_format(before_now(minutes=1)), }, project_id=self.project.id, ) self.increment( event, 1, timestamp=now() - timedelta(minutes=1), ) self.increment( event, 1, timestamp=now() - timedelta(days=1, minutes=20), ) data = { "interval": "1h", "value": 99, "comparisonType": "percent", "comparisonInterval": "1d", } rule = self.get_rule(data=data, rule=Rule(environment_id=None)) self.assertPasses(rule, event) data = { "interval": "1h", "value": 101, "comparisonType": "percent", "comparisonInterval": "1d", } rule = self.get_rule(data=data, rule=Rule(environment_id=None)) self.assertDoesNotPass(rule, event)
def test_more_than_zero(self, now): now.return_value = datetime(2016, 8, 1, 0, 0, 0, 0, tzinfo=pytz.utc) event = self.get_event() data = {"interval": "1m", "value": six.text_type("0")} rule = self.get_rule(data=data, rule=Rule(environment_id=None)) environment_id = 1 environment_rule = self.get_rule(data=data, rule=Rule(environment_id=environment_id)) self.assertDoesNotPass(rule, event) self.assertDoesNotPass(environment_rule, event) self.increment(event, 1, environment_id=environment_id) self.assertPasses(rule, event) self.assertPasses(environment_rule, event) self.assertDoesNotPass(self.get_rule(data=data, rule=Rule(environment_id=0)), event)
def setUp(self): from sentry.ownership.grammar import Rule self.user = self.create_user(email='*****@*****.**', is_active=True) self.user2 = self.create_user(email='*****@*****.**', is_active=True) self.organization = self.create_organization(owner=self.user) self.team = self.create_team(organization=self.organization) self.project = self.create_project(name='Test', teams=[self.team]) OrganizationMemberTeam.objects.create( organizationmember=OrganizationMember.objects.get( user=self.user, organization=self.organization, ), team=self.team, ) self.create_member(user=self.user2, organization=self.organization, teams=[self.team]) self.group = self.create_group( first_seen=timezone.now(), last_seen=timezone.now(), project=self.project, message='hello world', logger='root', ) ProjectOwnership.objects.create( project_id=self.project.id, schema=dump_schema([ Rule(Matcher('path', '*.py'), [ Owner('team', self.team.slug), ]), Rule(Matcher('path', '*.jx'), [ Owner('user', self.user2.email), ]), Rule(Matcher('path', '*.cbl'), [ Owner('user', self.user.email), Owner('user', self.user2.email), ]) ]), fallthrough=True, )
def test_alert_added(self): alert_rule_created.send(rule=Rule(id=1), project=self.project, user=self.user, sender=type(Rule)) task = OrganizationOnboardingTask.objects.get( organization=self.organization, task=OnboardingTask.ALERT_RULE, status=OnboardingTaskStatus.COMPLETE, ) assert task is not None
def test_comparison(self): with freeze_time(before_now(minutes=0)): # Test data is 4 events in the current period and 2 events in the comparison period, so # a 100% increase. event = self.store_event( data={ "fingerprint": ["something_random"], "timestamp": iso_format(before_now(minutes=1)), "user": { "id": uuid4().hex }, }, project_id=self.project.id, ) self.increment( event, 3, timestamp=now() - timedelta(minutes=1), ) self.increment( event, 2, timestamp=now() - timedelta(days=1, minutes=20), ) data = { "interval": "1h", "value": 99, "comparisonType": "percent", "comparisonInterval": "1d", } rule = self.get_rule(data=data, rule=Rule(environment_id=None)) self.assertPasses(rule, event) data = { "interval": "1h", "value": 101, "comparisonType": "percent", "comparisonInterval": "1d", } rule = self.get_rule(data=data, rule=Rule(environment_id=None)) self.assertDoesNotPass(rule, event)
def setUp(self): from sentry.ownership.grammar import Rule self.user = self.create_user(email="*****@*****.**", is_active=True) self.user2 = self.create_user(email="*****@*****.**", is_active=True) self.organization = self.create_organization(owner=self.user) self.team = self.create_team(organization=self.organization) self.project = self.create_project(name="Test", teams=[self.team]) OrganizationMemberTeam.objects.create( organizationmember=OrganizationMember.objects.get( user=self.user, organization=self.organization), team=self.team, ) self.create_member(user=self.user2, organization=self.organization, teams=[self.team]) self.group = self.create_group( first_seen=timezone.now(), last_seen=timezone.now(), project=self.project, message="hello world", logger="root", ) ProjectOwnership.objects.create( project_id=self.project.id, schema=dump_schema([ Rule(Matcher("path", "*.py"), [Owner("team", self.team.slug)]), Rule(Matcher("path", "*.jx"), [Owner("user", self.user2.email)]), Rule( Matcher("path", "*.cbl"), [ Owner("user", self.user.email), Owner("user", self.user2.email) ], ), ]), fallthrough=True, )
def test_execute_rule(self, mock_get_rules, mock_execute_rule): action_id = 'sentry.rules.actions.notify_event.NotifyEventAction' condition_id = 'sentry.rules.conditions.first_seen_event.FirstSeenEventCondition' group = self.create_group(project=self.project) event = self.create_event(group=group) mock_get_rules.return_value = [ Rule( id=1, data={ 'actions': [{'id': action_id}], 'conditions': [{'id': condition_id}], } ) ] post_process_group( group=group, event=event, is_new=False, is_regression=False, is_sample=False, ) mock_get_rules.assert_called_once_with(self.project) assert not mock_execute_rule.delay.called post_process_group( group=group, event=event, is_new=True, is_regression=False, is_sample=False, ) assert len(mock_execute_rule.delay.mock_calls) == 1 post_process_group( group=group, event=event, is_new=True, is_regression=False, is_sample=False, ) assert len(mock_execute_rule.delay.mock_calls) == 2
def get(self, request, organization, project, rule_id=None): if rule_id: try: rule = Rule.objects.get( project=project, id=rule_id, status__in=[RuleStatus.ACTIVE, RuleStatus.INACTIVE], ) except Rule.DoesNotExist: path = '/{}/{}/settings/alerts/rules/'.format( organization.slug, project.slug) return self.redirect(absolute_uri(path)) else: rule = Rule(project=project) action_list = [] condition_list = [] # TODO: conditions need to be based on actions for rule_type, rule_cls in rules: node = rule_cls(project) context = { 'id': node.id, 'label': node.label, 'html': node.render_form(), } if not node.is_enabled(): continue if rule_type.startswith('condition/'): condition_list.append(context) elif rule_type.startswith('action/'): action_list.append(context) context = { 'rule': rule, 'page': 'rules', 'action_list': json.dumps(action_list), 'condition_list': json.dumps(condition_list), } return self.respond('sentry/projects/rules/new.html', context)
def test_applies_correctly_with_environment(self): rule = self.get_rule(rule=Rule(environment_id=1), ) self.assertPasses(rule, self.event, is_new=True, is_new_group_environment=True) self.assertPasses(rule, self.event, is_new=False, is_new_group_environment=True) self.assertDoesNotPass(rule, self.event, is_new=True, is_new_group_environment=False) self.assertDoesNotPass(rule, self.event, is_new=False, is_new_group_environment=False)
def digest(request): random = get_random(request) # TODO: Refactor all of these into something more manageable. org = Organization(id=1, slug="example", name="Example Organization") project = Project(id=1, slug="example", name="Example Project", organization=org) rules = { i: Rule(id=i, project=project, label="Rule #%s" % (i,)) for i in range(1, random.randint(2, 4)) } state = { "project": project, "groups": {}, "rules": rules, "event_counts": {}, "user_counts": {}, } records = [] group_generator = make_group_generator(random, project) for i in range(random.randint(1, 30)): group = next(group_generator) state["groups"][group.id] = group offset = timedelta(seconds=0) for i in range(random.randint(1, 10)): offset += timedelta(seconds=random.random() * 120) data = dict(load_data("python")) data["message"] = group.message data.pop("logentry", None) event_manager = EventManager(data) event_manager.normalize() data = event_manager.get_data() data["timestamp"] = random.randint( to_timestamp(group.first_seen), to_timestamp(group.last_seen) ) event = eventstore.create_event( event_id=uuid.uuid4().hex, group_id=group.id, project_id=project.id, data=data.data ) records.append( Record( event.event_id, Notification( event, random.sample(state["rules"], random.randint(1, len(state["rules"]))) ), to_timestamp(event.datetime), ) ) state["event_counts"][group.id] = random.randint(10, 1e4) state["user_counts"][group.id] = random.randint(10, 1e4) digest = build_digest(project, records, state) start, end, counts = get_digest_metadata(digest) context = { "project": project, "counts": counts, "digest": digest, "start": start, "end": end, "referrer": "digest_email", } add_unsubscribe_link(context) return MailPreview( html_template="sentry/emails/digests/body.html", text_template="sentry/emails/digests/body.txt", context=context, ).render(request)
def alert(request): platform = request.GET.get("platform", "python") org = Organization(id=1, slug="example", name="Example") project = Project(id=1, slug="example", name="Example", organization=org) random = get_random(request) group = next(make_group_generator(random, project)) data = dict(load_data(platform)) data["message"] = group.message data["event_id"] = "44f1419e73884cd2b45c79918f4b6dc4" data.pop("logentry", None) data["environment"] = "prod" data["tags"] = [ ("logger", "javascript"), ("environment", "prod"), ("level", "error"), ("device", "Other"), ] event_manager = EventManager(data) event_manager.normalize() data = event_manager.get_data() event = event_manager.save(project.id) # Prevent Percy screenshot from constantly changing if options.get("store.use-django-event"): event.datetime = datetime(2017, 9, 6, 0, 0) else: event.data["timestamp"] = 1504656000.0 # datetime(2017, 9, 6, 0, 0) event_type = event_manager.get_event_type() group.message = event.search_message group.data = {"type": event_type.key, "metadata": event_type.get_metadata(data)} rule = Rule(label="An example rule") # XXX: this interface_list code needs to be the same as in # src/sentry/plugins/sentry_mail/models.py interface_list = [] for interface in six.itervalues(event.interfaces): body = interface.to_email_html(event) if not body: continue text_body = interface.to_string(event) interface_list.append((interface.get_title(), mark_safe(body), text_body)) return MailPreview( html_template="sentry/emails/error.html", text_template="sentry/emails/error.txt", context={ "rule": rule, "group": group, "event": event, "link": "http://example.com/link", "interfaces": interface_list, "tags": event.tags, "project_label": project.slug, "commits": [ { # TODO(dcramer): change to use serializer "repository": { "status": "active", "name": "Example Repo", "url": "https://github.com/example/example", "dateCreated": "2018-02-28T23:39:22.402Z", "provider": {"id": "github", "name": "GitHub"}, "id": "1", }, "score": 2, "subject": "feat: Do something to raven/base.py", "message": "feat: Do something to raven/base.py\naptent vivamus vehicula tempus volutpat hac tortor", "id": "1b17483ffc4a10609e7921ee21a8567bfe0ed006", "shortId": "1b17483", "author": { "username": "******", "isManaged": False, "lastActive": "2018-03-01T18:25:28.149Z", "id": "1", "isActive": True, "has2fa": False, "name": "*****@*****.**", "avatarUrl": "https://secure.gravatar.com/avatar/51567a4f786cd8a2c41c513b592de9f9?s=32&d=mm", "dateJoined": "2018-02-27T22:04:32.847Z", "emails": [{"is_verified": False, "id": "1", "email": "*****@*****.**"}], "avatar": {"avatarUuid": None, "avatarType": "letter_avatar"}, "lastLogin": "******", "email": "*****@*****.**", }, } ], }, ).render(request)
def create_or_edit_rule(request, organization, project, rule_id=None): if rule_id: try: rule = Rule.objects.get(project=project, id=rule_id) except Rule.DoesNotExist: path = reverse('sentry-project-rules', args=[organization.slug, project.slug]) return HttpResponseRedirect(path) else: rule = Rule(project=project) form_data = { 'label': rule.label, 'action_match': rule.data.get('action_match'), } if request.POST: for key, value in request.POST.iteritems(): form_data[key] = value else: for num, node in enumerate(rule.data.get('conditions', [])): prefix = 'condition[%d]' % (num,) for key, value in node.iteritems(): form_data[prefix + '[' + key + ']'] = value for num, node in enumerate(rule.data.get('actions', [])): prefix = 'action[%d]' % (num,) for key, value in node.iteritems(): form_data[prefix + '[' + key + ']'] = value validator = RuleFormValidator(project, form_data) if request.POST and validator.is_valid(): data = validator.cleaned_data.copy() rule.label = data.pop('label') rule.data = data rule.save() messages.add_message( request, messages.SUCCESS, _('Changes to your rule were saved.')) path = reverse('sentry-project-rules', args=[organization.slug, project.slug]) return HttpResponseRedirect(path) action_list = [] condition_list = [] # TODO: conditions need to be based on actions for rule_type, rule in rules: node = rule(project) context = { 'id': node.id, 'label': node.label, 'html': node.render_form(), } if rule_type.startswith('condition/'): condition_list.append(context) elif rule_type.startswith('action/'): action_list.append(context) context = csrf(request) context.update({ 'rule': rule, 'form_is_valid': (not request.POST or validator.is_valid()), 'form_errors': validator.errors, 'form_data': form_data, 'organization': organization, 'team': project.team, 'page': 'rules', 'action_list': json.dumps(action_list), 'condition_list': json.dumps(condition_list), 'project': project, }) return render_to_response('sentry/projects/rules/new.html', context, request)
def create_or_edit_rule(request, team, project, rule_id=None): if rule_id: try: rule = Rule.objects.get(project=project, id=rule_id) except Rule.DoesNotExist: path = reverse('sentry-project-rules', args=[team.slug, project.slug]) return HttpResponseRedirect(path) else: rule = Rule(project=project) form_data = { 'label': rule.label, 'action_match': rule.data.get('action_match'), } if request.POST: for key, value in request.POST.iteritems(): form_data[key] = value else: for num, node in enumerate(rule.data.get('conditions', [])): prefix = 'condition[%d]' % (num,) for key, value in node.iteritems(): form_data[prefix + '[' + key + ']'] = value for num, node in enumerate(rule.data.get('actions', [])): prefix = 'action[%d]' % (num,) for key, value in node.iteritems(): form_data[prefix + '[' + key + ']'] = value validator = RuleFormValidator(project, form_data) if request.POST and validator.is_valid(): data = validator.cleaned_data.copy() rule.label = data.pop('label') rule.data = data rule.save() messages.add_message( request, messages.SUCCESS, _('Changes to your rule were saved.')) path = reverse('sentry-project-rules', args=[team.slug, project.slug]) return HttpResponseRedirect(path) action_list = [] condition_list = [] # TODO: conditions need to be based on actions for rule_type, rule in rules: node = rule(project) context = { 'id': node.id, 'label': node.label, 'html': node.render_form(), } if rule_type.startswith('condition/'): condition_list.append(context) elif rule_type.startswith('action/'): action_list.append(context) context = csrf(request) context.update({ 'rule': rule, 'form_is_valid': (not request.POST or validator.is_valid()), 'form_errors': validator.errors, 'form_data': form_data, 'team': team, 'page': 'rules', 'action_list': json.dumps(action_list), 'condition_list': json.dumps(condition_list), 'project': project, }) return render_to_response('sentry/projects/rules/new.html', context, request)
def create_issue_alert_rule(self, data): """data format { "project": project "environment": environment "name": "My rule name", "owner": actor id, "conditions": [], "actions": [], "actionMatch": "all" } """ rule = Rule() rule.project = data["project"] if "environment" in data: environment = data["environment"] rule.environment_id = int( environment) if environment else environment if data.get("name"): rule.label = data["name"] if data.get("actionMatch"): rule.data["action_match"] = data["actionMatch"] if data.get("actions") is not None: rule.data["actions"] = data["actions"] if data.get("conditions") is not None: rule.data["conditions"] = data["conditions"] if data.get("frequency"): rule.data["frequency"] = data["frequency"] if data.get("date_added"): rule.date_added = data["date_added"] if data.get("owner"): rule.owner = data["owner"] rule.save() return rule
def test_onboarding_complete(self): now = timezone.now() user = self.create_user(email="*****@*****.**") project = self.create_project(first_event=now) second_project = self.create_project(first_event=now) second_event = self.store_event( data={ "platform": "python", "message": "python error message" }, project_id=second_project.id, ) event = self.store_event( data={ "event_id": "a" * 32, "platform": "javascript", "timestamp": iso_format(before_now(minutes=1)), "tags": { "sentry:release": "e1b5d1900526feaf20fe2bc9cad83d392136030a", "sentry:user": "******", }, "user": { "ip_address": "0.0.0.0", "id": "41656", "email": "*****@*****.**" }, "exception": { "values": [{ "stacktrace": { "frames": [{ "data": { "sourcemap": "https://media.sentry.io/_static/29e365f8b0d923bc123e8afa38d890c3/sentry/dist/vendor.js.map" } }] }, "type": "TypeError", }] }, }, project_id=project.id, ) event_data = load_data("transaction") min_ago = iso_format(before_now(minutes=1)) event_data.update({"start_timestamp": min_ago, "timestamp": min_ago}) transaction = self.store_event(data=event_data, project_id=project.id) first_event_received.send(project=project, event=transaction, sender=type(project)) first_transaction_received.send(project=project, event=transaction, sender=type(project)) member = self.create_member(organization=self.organization, teams=[self.team], user=user) event_processed.send(project=project, event=event, sender=type(project)) project_created.send(project=project, user=user, sender=type(project)) project_created.send(project=second_project, user=user, sender=type(second_project)) first_event_received.send(project=project, event=event, sender=type(project)) first_event_received.send(project=second_project, event=second_event, sender=type(second_project)) member_joined.send(member=member, organization=self.organization, sender=type(member)) plugin_enabled.send( plugin=IssueTrackingPlugin(), project=project, user=user, sender=type(IssueTrackingPlugin), ) issue_tracker_used.send( plugin=IssueTrackingPlugin(), project=project, user=user, sender=type(IssueTrackingPlugin), ) alert_rule_created.send( rule=Rule(id=1), project=self.project, user=self.user, rule_type="issue", sender=type(Rule), is_api_token=False, ) assert (OrganizationOption.objects.filter( organization=self.organization, key="onboarding:complete").count() == 1)
def get_rules(self): return Rule.get_for_project(self.project.id)
def test_execute_rule(self, mock_get_rules, mock_execute_rule): action_id = 'sentry.rules.actions.notify_event.NotifyEventAction' condition_id = 'sentry.rules.conditions.first_seen_event.FirstSeenEventCondition' group = self.create_group(project=self.project) event = self.create_event(group=group) mock_get_rules.return_value = [ Rule(id=1, data={ 'actions': [{ 'id': action_id }], 'conditions': [{ 'id': condition_id }], }) ] post_process_group( group=group, event=event, is_new=False, is_regression=False, is_sample=False, ) assert not mock_execute_rule.delay.called post_process_group( group=group, event=event, is_new=True, is_regression=False, is_sample=False, ) mock_execute_rule.delay.assert_called_once_with( rule_id=1, event=event, is_new=True, is_regression=False, is_sample=False, ) # ensure we dont execute again since the object hasnt changed state post_process_group( group=group, event=event, is_new=True, is_regression=False, is_sample=False, ) assert len(mock_execute_rule.mock_calls) == 1 # and finally test the behavior of cycling back to new post_process_group( group=group, event=event, is_new=False, is_regression=False, is_sample=False, ) post_process_group( group=group, event=event, is_new=True, is_regression=False, is_sample=False, ) assert len(mock_execute_rule.mock_calls) == 2
def digest(request): random = get_random(request) # TODO: Refactor all of these into something more manageable. org = Organization( id=1, slug='example', name='Example Organization', ) team = Team( id=1, slug='example', name='Example Team', organization=org, ) project = Project( id=1, slug='example', name='Example Project', team=team, organization=org, ) rules = {i: Rule( id=i, project=project, label="Rule #%s" % (i,), ) for i in range(1, random.randint(2, 4))} state = { 'project': project, 'groups': {}, 'rules': rules, 'event_counts': {}, 'user_counts': {}, } records = [] event_sequence = itertools.count(1) group_generator = make_group_generator(random, project) for i in range(random.randint(1, 30)): group = next(group_generator) state['groups'][group.id] = group offset = timedelta(seconds=0) for i in range(random.randint(1, 10)): offset += timedelta(seconds=random.random() * 120) event = Event( id=next(event_sequence), event_id=uuid.uuid4().hex, project=project, group=group, message=group.message, data=load_data('python'), datetime=to_datetime( random.randint( to_timestamp(group.first_seen), to_timestamp(group.last_seen), ), ) ) records.append( Record( event.event_id, Notification( event, random.sample(state['rules'], random.randint(1, len(state['rules']))), ), to_timestamp(event.datetime), ) ) state['event_counts'][group.id] = random.randint(10, 1e4) state['user_counts'][group.id] = random.randint(10, 1e4) digest = build_digest(project, records, state) start, end, counts = get_digest_metadata(digest) return MailPreview( html_template='sentry/emails/digests/body.html', text_template='sentry/emails/digests/body.txt', context={ 'project': project, 'counts': counts, 'digest': digest, 'start': start, 'end': end, }, ).render(request)
def new_event(request): platform = request.GET.get('platform', 'python') org = Organization( id=1, slug='example', name='Example', ) team = Team( id=1, slug='example', name='Example', organization=org, ) project = Project( id=1, slug='example', name='Example', team=team, organization=org, ) random = get_random(request) group = next( make_group_generator(random, project), ) event = Event( id=1, project=project, group=group, message=group.message, data=load_data(platform), datetime=to_datetime( random.randint( to_timestamp(group.first_seen), to_timestamp(group.last_seen), ), ), ) rule = Rule(label="An example rule") interface_list = [] for interface in six.itervalues(event.interfaces): body = interface.to_email_html(event) if not body: continue interface_list.append((interface.get_title(), mark_safe(body))) return MailPreview( html_template='sentry/emails/error.html', text_template='sentry/emails/error.txt', context={ 'rule': rule, 'group': group, 'event': event, 'link': 'http://example.com/link', 'interfaces': interface_list, 'tags': event.get_tags(), 'project_label': project.name, 'tags': [ ('logger', 'javascript'), ('environment', 'prod'), ('level', 'error'), ('device', 'Other') ] }, ).render(request)