Exemple #1
0
    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)
Exemple #2
0
    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)
Exemple #4
0
 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)
Exemple #7
0
    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)
Exemple #8
0
    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)
Exemple #9
0
    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)
Exemple #10
0
    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)
Exemple #11
0
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)
Exemple #15
0
    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)
Exemple #18
0
    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,
        )
Exemple #19
0
    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
Exemple #20
0
    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)
Exemple #22
0
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)
Exemple #23
0
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)
Exemple #24
0
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)
Exemple #25
0
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)
Exemple #26
0
    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)
Exemple #28
0
 def get_rules(self):
     return Rule.get_for_project(self.project.id)
Exemple #29
0
    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
Exemple #30
0
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)
Exemple #31
0
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)