Browse Source

Create default rules for projects

David Cramer 10 years ago
parent
commit
77d9e14cc0
3 changed files with 312 additions and 88 deletions
  1. 268 0
      src/sentry/migrations/0118_create_default_rules.py
  2. 44 0
      src/sentry/receivers/rules.py
  3. 0 88
      src/sentry/rules.py

+ 268 - 0
src/sentry/migrations/0118_create_default_rules.py

@@ -0,0 +1,268 @@
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import DataMigration
+from django.db import models
+
+class Migration(DataMigration):
+
+    def forwards(self, orm):
+        from sentry.receivers.rules import create_default_rules
+
+        for project in orm['sentry.Project']:
+            create_default_rules(instance=project, created=True)
+
+    def backwards(self, orm):
+        pass
+
+    models = {
+        'sentry.accessgroup': {
+            'Meta': {'unique_together': "(('team', 'name'),)", 'object_name': 'AccessGroup'},
+            'data': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'date_added': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'managed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'members': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['sentry.User']", 'symmetrical': 'False'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
+            'projects': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['sentry.Project']", 'symmetrical': 'False'}),
+            'team': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sentry.Team']"}),
+            'type': ('django.db.models.fields.IntegerField', [], {'default': '50'})
+        },
+        'sentry.activity': {
+            'Meta': {'object_name': 'Activity'},
+            'data': ('django.db.models.fields.TextField', [], {'null': 'True'}),
+            'datetime': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'event': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sentry.Event']", 'null': 'True'}),
+            'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sentry.Group']", 'null': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'ident': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True'}),
+            'project': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sentry.Project']"}),
+            'type': ('django.db.models.fields.PositiveIntegerField', [], {}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sentry.User']", 'null': 'True'})
+        },
+        'sentry.alert': {
+            'Meta': {'object_name': 'Alert'},
+            'data': ('django.db.models.fields.TextField', [], {'null': 'True'}),
+            'datetime': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sentry.Group']", 'null': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'message': ('django.db.models.fields.TextField', [], {}),
+            'project': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sentry.Project']"}),
+            'related_groups': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'related_alerts'", 'symmetrical': 'False', 'through': "orm['sentry.AlertRelatedGroup']", 'to': "orm['sentry.Group']"}),
+            'status': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'db_index': 'True'})
+        },
+        'sentry.alertrelatedgroup': {
+            'Meta': {'unique_together': "(('group', 'alert'),)", 'object_name': 'AlertRelatedGroup'},
+            'alert': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sentry.Alert']"}),
+            'data': ('django.db.models.fields.TextField', [], {'null': 'True'}),
+            'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sentry.Group']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
+        },
+        'sentry.event': {
+            'Meta': {'unique_together': "(('project', 'event_id'),)", 'object_name': 'Event', 'db_table': "'sentry_message'"},
+            'checksum': ('django.db.models.fields.CharField', [], {'max_length': '32', 'db_index': 'True'}),
+            'data': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'datetime': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'db_index': 'True'}),
+            'event_id': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'db_column': "'message_id'"}),
+            'group': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'event_set'", 'null': 'True', 'to': "orm['sentry.Group']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'message': ('django.db.models.fields.TextField', [], {}),
+            'num_comments': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'null': 'True'}),
+            'platform': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True'}),
+            'project': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sentry.Project']", 'null': 'True'}),
+            'time_spent': ('django.db.models.fields.IntegerField', [], {'null': 'True'})
+        },
+        'sentry.eventmapping': {
+            'Meta': {'unique_together': "(('project', 'event_id'),)", 'object_name': 'EventMapping'},
+            'date_added': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'event_id': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+            'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sentry.Group']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'project': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sentry.Project']"})
+        },
+        'sentry.group': {
+            'Meta': {'unique_together': "(('project', 'checksum'),)", 'object_name': 'Group', 'db_table': "'sentry_groupedmessage'"},
+            'active_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'db_index': 'True'}),
+            'checksum': ('django.db.models.fields.CharField', [], {'max_length': '32', 'db_index': 'True'}),
+            'culprit': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'db_column': "'view'", 'blank': 'True'}),
+            'data': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'first_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'db_index': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_public': ('django.db.models.fields.NullBooleanField', [], {'default': 'False', 'null': 'True', 'blank': 'True'}),
+            'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'db_index': 'True'}),
+            'level': ('django.db.models.fields.PositiveIntegerField', [], {'default': '40', 'db_index': 'True', 'blank': 'True'}),
+            'logger': ('django.db.models.fields.CharField', [], {'default': "'root'", 'max_length': '64', 'db_index': 'True', 'blank': 'True'}),
+            'message': ('django.db.models.fields.TextField', [], {}),
+            'num_comments': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'null': 'True'}),
+            'platform': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True'}),
+            'project': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sentry.Project']", 'null': 'True'}),
+            'resolved_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'db_index': 'True'}),
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+            'status': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'db_index': 'True'}),
+            'time_spent_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+            'time_spent_total': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+            'times_seen': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1', 'db_index': 'True'})
+        },
+        'sentry.groupbookmark': {
+            'Meta': {'unique_together': "(('project', 'user', 'group'),)", 'object_name': 'GroupBookmark'},
+            'group': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'bookmark_set'", 'to': "orm['sentry.Group']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'bookmark_set'", 'to': "orm['sentry.Project']"}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'sentry_bookmark_set'", 'to': "orm['sentry.User']"})
+        },
+        'sentry.groupmeta': {
+            'Meta': {'unique_together': "(('group', 'key'),)", 'object_name': 'GroupMeta'},
+            'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sentry.Group']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'key': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
+            'value': ('django.db.models.fields.TextField', [], {})
+        },
+        'sentry.groupseen': {
+            'Meta': {'unique_together': "(('user', 'group'),)", 'object_name': 'GroupSeen'},
+            'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sentry.Group']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'project': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sentry.Project']"}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sentry.User']", 'db_index': 'False'})
+        },
+        'sentry.grouptagkey': {
+            'Meta': {'unique_together': "(('project', 'group', 'key'),)", 'object_name': 'GroupTagKey'},
+            'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sentry.Group']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'key': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+            'project': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sentry.Project']", 'null': 'True'}),
+            'values_seen': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})
+        },
+        'sentry.grouptagvalue': {
+            'Meta': {'unique_together': "(('project', 'key', 'value', 'group'),)", 'object_name': 'GroupTagValue', 'db_table': "'sentry_messagefiltervalue'"},
+            'first_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'null': 'True', 'db_index': 'True'}),
+            'group': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'grouptag'", 'to': "orm['sentry.Group']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'key': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+            'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'null': 'True', 'db_index': 'True'}),
+            'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'grouptag'", 'null': 'True', 'to': "orm['sentry.Project']"}),
+            'times_seen': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+            'value': ('django.db.models.fields.CharField', [], {'max_length': '200'})
+        },
+        'sentry.lostpasswordhash': {
+            'Meta': {'object_name': 'LostPasswordHash'},
+            'date_added': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'hash': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sentry.User']", 'unique': 'True'})
+        },
+        'sentry.option': {
+            'Meta': {'object_name': 'Option'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'}),
+            'value': ('sentry.db.models.fields.pickle.UnicodePickledObjectField', [], {})
+        },
+        'sentry.pendingteammember': {
+            'Meta': {'unique_together': "(('team', 'email'),)", 'object_name': 'PendingTeamMember'},
+            'date_added': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'team': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'pending_member_set'", 'to': "orm['sentry.Team']"}),
+            'type': ('django.db.models.fields.IntegerField', [], {'default': '50'})
+        },
+        'sentry.project': {
+            'Meta': {'unique_together': "(('team', 'slug'),)", 'object_name': 'Project'},
+            'date_added': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'sentry_owned_project_set'", 'null': 'True', 'to': "orm['sentry.User']"}),
+            'platform': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}),
+            'public': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'null': 'True'}),
+            'status': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'db_index': 'True'}),
+            'team': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sentry.Team']", 'null': 'True'})
+        },
+        'sentry.projectkey': {
+            'Meta': {'object_name': 'ProjectKey'},
+            'date_added': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'null': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'key_set'", 'to': "orm['sentry.Project']"}),
+            'public_key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'unique': 'True', 'null': 'True'}),
+            'roles': ('django.db.models.fields.BigIntegerField', [], {'default': '1'}),
+            'secret_key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'unique': 'True', 'null': 'True'}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sentry.User']", 'null': 'True'}),
+            'user_added': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'keys_added_set'", 'null': 'True', 'to': "orm['sentry.User']"})
+        },
+        'sentry.projectoption': {
+            'Meta': {'unique_together': "(('project', 'key'),)", 'object_name': 'ProjectOption', 'db_table': "'sentry_projectoptions'"},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'key': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
+            'project': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sentry.Project']"}),
+            'value': ('sentry.db.models.fields.pickle.UnicodePickledObjectField', [], {})
+        },
+        'sentry.rule': {
+            'Meta': {'object_name': 'Rule'},
+            'data': ('django.db.models.fields.TextField', [], {}),
+            'date_added': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'label': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
+            'project': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sentry.Project']"})
+        },
+        'sentry.tagkey': {
+            'Meta': {'unique_together': "(('project', 'key'),)", 'object_name': 'TagKey', 'db_table': "'sentry_filterkey'"},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'key': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+            'label': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True'}),
+            'project': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sentry.Project']"}),
+            'values_seen': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})
+        },
+        'sentry.tagvalue': {
+            'Meta': {'unique_together': "(('project', 'key', 'value'),)", 'object_name': 'TagValue', 'db_table': "'sentry_filtervalue'"},
+            'data': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'first_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'null': 'True', 'db_index': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'key': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+            'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'null': 'True', 'db_index': 'True'}),
+            'project': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sentry.Project']", 'null': 'True'}),
+            'times_seen': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+            'value': ('django.db.models.fields.CharField', [], {'max_length': '200'})
+        },
+        'sentry.team': {
+            'Meta': {'object_name': 'Team'},
+            'date_added': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'null': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'members': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'team_memberships'", 'symmetrical': 'False', 'through': "orm['sentry.TeamMember']", 'to': "orm['sentry.User']"}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
+            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sentry.User']"}),
+            'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '50'}),
+            'status': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})
+        },
+        'sentry.teammember': {
+            'Meta': {'unique_together': "(('team', 'user'),)", 'object_name': 'TeamMember'},
+            'date_added': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'team': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'member_set'", 'to': "orm['sentry.Team']"}),
+            'type': ('django.db.models.fields.IntegerField', [], {'default': '50'}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'sentry_teammember_set'", 'to': "orm['sentry.User']"})
+        },
+        'sentry.user': {
+            'Meta': {'object_name': 'User', 'db_table': "'auth_user'"},
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128'})
+        },
+        'sentry.useroption': {
+            'Meta': {'unique_together': "(('user', 'project', 'key'),)", 'object_name': 'UserOption'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'key': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
+            'project': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sentry.Project']", 'null': 'True'}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sentry.User']"}),
+            'value': ('sentry.db.models.fields.pickle.UnicodePickledObjectField', [], {})
+        }
+    }
+
+    complete_apps = ['sentry']
+    symmetrical = True

+ 44 - 0
src/sentry/receivers/rules.py

@@ -0,0 +1,44 @@
+from __future__ import print_function
+
+from django.db.models.signals import post_save
+
+from sentry.models import Project, Rule
+
+
+def create_default_rules(instance, created=True, **kwargs):
+    if not created:
+        return
+
+    Rule.objects.create(
+        project=instance,
+        label='Send a notification for new events',
+        data={
+            'conditions': [
+                {'id': 'sentry.rules.conditions.first_seen_event.FirstSeenEventCondition'},
+            ],
+            'actions': [
+                {'id': 'sentry.rules.actions.notify_event.NotifyEventAction'},
+            ],
+        },
+    )
+
+    Rule.objects.create(
+        project=instance,
+        label='Send a notification for regressions',
+        data={
+            'conditions': [
+                {'id': 'sentry.rules.conditions.first_seen_event.RegressionEventCondition'},
+            ],
+            'actions': [
+                {'id': 'sentry.rules.actions.notify_event.NotifyEventAction'},
+            ],
+        }
+    )
+
+
+post_save.connect(
+    create_default_rules,
+    sender=Project,
+    dispatch_uid="create_default_rules",
+    weak=False,
+)

+ 0 - 88
src/sentry/rules.py

@@ -1,88 +0,0 @@
-"""
-sentry.rules
-~~~~~~~~~~~~
-
-:copyright: (c) 2010-2014 by the Sentry Team, see AUTHORS for more details.
-:license: BSD, see LICENSE for more details.
-
-Rules apply either before an event gets stored, or immediately after.
-
-Basic actions:
-
-- I want to get notified when [X]
-- I want to group events when [X]
-- I want to scrub data when [X]
-
-Expanded:
-
-- I want to get notified when an event is first seen
-- I want to get notified when an event is marked as a regression
-- I want to get notified when the rate of an event increases by [100%]
-- I want to get notified when an event has been seen more than [100] times
-- I want to get notified when an event matches [conditions]
-- I want to group events when an event matches [conditions]
-
-Rules get broken down into two phases:
-
-- An action
-- A rule condition
-
-A condition itself may actually be any number of things, but that is determined
-by the rule's logic. Each rule condition may be associated with a form.
-
-- [ACTION:I want to get notified when] [RULE:an event is first seen]
-- [ACTION:I want to group events when] [RULE:an event matches [FORM]]
-
-"""
-import re
-
-from django.utils.html import escape
-from django.utils.safestring import mark_safe
-
-
-class RuleDescriptor(type):
-    def __new__(cls, *args, **kwargs):
-        new_cls = super(RuleDescriptor, cls).__new__(cls, *args, **kwargs)
-        new_cls.id = '%s.%s' % (new_cls.__module__, new_cls.__name__)
-        return new_cls
-
-
-class RuleBase(object):
-    label = None
-    form_cls = None
-
-    __metaclass__ = RuleDescriptor
-
-    def __init__(self, project, data=None):
-        self.project = project
-        self.data = data or {}
-
-    def get_option(self, key):
-        return self.data.get(key)
-
-    def render_label(self):
-        return self.label.format(**self.data)
-
-    def render_form(self):
-        if not self.form_cls:
-            return self.label
-
-        form = self.form_cls(
-            self.data,
-        )
-
-        def replace_field(match):
-            field = match.group(1)
-            return unicode(form[field])
-
-        return mark_safe(re.sub(r'{([^}]+)}', replace_field, escape(self.label)))
-
-    def validate_form(self):
-        if not self.form_cls:
-            return True
-
-        form = self.form_cls(
-            self.data,
-        )
-
-        return form.is_valid()