diff --git a/CHANGELOG.md b/CHANGELOG.md index a6da35f738..273e6f5445 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Change Log +## v1.0.0-rc.2 - Unreleased + +### Changed + +- [#1563](https://github.com/getredash/redash/pull/1563) Send events to webhook as JSON with a schema. + ## v1.0.0-rc.1 - 2017-01-31 This version has two big changes behind the scenes: diff --git a/redash/models.py b/redash/models.py index a387c9f6aa..9f00f44b98 100644 --- a/redash/models.py +++ b/redash/models.py @@ -1316,7 +1316,7 @@ class Event(db.Model): action = Column(db.String(255)) object_type = Column(db.String(255)) object_id = Column(db.String(255), nullable=True) - additional_properties = Column(db.Text, nullable=True) + additional_properties = Column(MutableDict.as_mutable(PseudoJSON), nullable=True, default={}) created_at = Column(db.DateTime(True), default=db.func.now()) __tablename__ = 'events' @@ -1324,6 +1324,17 @@ class Event(db.Model): def __unicode__(self): return u"%s,%s,%s,%s" % (self.user_id, self.action, self.object_type, self.object_id) + def to_dict(self): + return { + 'org_id': self.org_id, + 'user_id': self.user_id, + 'action': self.action, + 'object_type': self.object_type, + 'object_id': self.object_id, + 'additional_properties': self.additional_properties, + 'created_at': self.created_at.isoformat() + } + @classmethod def record(cls, event): org_id = event.pop('org_id') @@ -1333,11 +1344,10 @@ def record(cls, event): object_id = event.pop('object_id', None) created_at = datetime.datetime.utcfromtimestamp(event.pop('timestamp')) - additional_properties = json.dumps(event) event = cls(org_id=org_id, user_id=user_id, action=action, object_type=object_type, object_id=object_id, - additional_properties=additional_properties, + additional_properties=event, created_at=created_at) db.session.add(event) return event diff --git a/redash/tasks/general.py b/redash/tasks/general.py index d10cf7a99a..d03bfc7dc9 100644 --- a/redash/tasks/general.py +++ b/redash/tasks/general.py @@ -10,14 +10,18 @@ @celery.task(name="redash.tasks.record_event", base=BaseTask) -def record_event(event): - original_event = event.copy() - models.Event.record(event) +def record_event(raw_event): + event = models.Event.record(raw_event) models.db.session.commit() + for hook in settings.EVENT_REPORTING_WEBHOOKS: logger.debug("Forwarding event to: %s", hook) try: - response = requests.post(hook, original_event) + data = { + "schema": "iglu:io.redash.webhooks/event/jsonschema/1-0-0", + "data": event.to_dict() + } + response = requests.post(hook, json=data) if response.status_code != 200: logger.error("Failed posting to %s: %s", hook, response.content) except Exception: diff --git a/tests/test_models.py b/tests/test_models.py index cdde989ac2..90576b3b1e 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -409,7 +409,7 @@ def test_records_additional_properties(self): event = models.Event.record(raw_event) - self.assertDictEqual(json.loads(event.additional_properties), additional_properties) + self.assertDictEqual(event.additional_properties, additional_properties) class TestWidgetDeleteInstance(BaseTestCase):