diff --git a/CHANGELOG.md b/CHANGELOG.md
index c57187a5..99abd110 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,10 +1,11 @@
# Changelog
All notable changes to this project will be documented in this file.
-## v1.14.0 - Unreleased
+## v1.14.0-dev - Unreleased
### Improvements
- Improved UI to invite users from account's other projects (#258)
+- Experimental Prometheus metrics endpoint (#300)
### Bug Fixes
- The "render_docs" command checks if markdown and pygments is installed (#329)
diff --git a/hc/api/models.py b/hc/api/models.py
index a5ee60ad..013d745e 100644
--- a/hc/api/models.py
+++ b/hc/api/models.py
@@ -199,6 +199,11 @@ class Check(models.Model):
codes = self.channel_set.order_by("code").values_list("code", flat=True)
return ",".join(map(str, codes))
+ @property
+ def unique_key(self):
+ code_half = self.code.hex[:16]
+ return hashlib.sha1(code_half.encode()).hexdigest()
+
def to_dict(self, readonly=False):
result = {
@@ -216,8 +221,7 @@ class Check(models.Model):
result["last_duration"] = int(self.last_duration.total_seconds())
if readonly:
- code_half = self.code.hex[:16]
- result["unique_key"] = hashlib.sha1(code_half.encode()).hexdigest()
+ result["unique_key"] = self.unique_key
else:
update_rel_url = reverse("hc-api-update", args=[self.code])
pause_rel_url = reverse("hc-api-pause", args=[self.code])
diff --git a/hc/front/tests/test_metrics.py b/hc/front/tests/test_metrics.py
new file mode 100644
index 00000000..27204285
--- /dev/null
+++ b/hc/front/tests/test_metrics.py
@@ -0,0 +1,43 @@
+from hc.api.models import Check
+from hc.test import BaseTestCase
+
+
+class MetricsTestCase(BaseTestCase):
+ def setUp(self):
+ super(MetricsTestCase, self).setUp()
+ self.project.api_key_readonly = "R" * 32
+ self.project.save()
+
+ self.check = Check(project=self.project, name="Alice Was Here")
+ self.check.tags = "foo"
+ self.check.save()
+
+ key = "R" * 32
+ self.url = "/projects/%s/checks/metrics/?api_key=%s" % (self.project.code, key)
+
+ def test_it_works(self):
+ r = self.client.get(self.url)
+ self.assertEqual(r.status_code, 200)
+ self.assertContains(r, 'name="Alice Was Here"')
+ self.assertContains(r, 'tags="foo"')
+ self.assertContains(r, 'tag="foo"')
+ self.assertContains(r, "hc_checks_total 1")
+
+ def test_it_escapes_newline(self):
+ self.check.name = "Line 1\nLine2"
+ self.check.tags = "A\\C"
+ self.check.save()
+
+ r = self.client.get(self.url)
+ self.assertEqual(r.status_code, 200)
+ self.assertContains(r, "Line 1\\nLine2")
+ self.assertContains(r, "A\\\\C")
+
+ def test_it_checks_api_key_length(self):
+ r = self.client.get(self.url + "R")
+ self.assertEqual(r.status_code, 400)
+
+ def test_it_checks_api_key(self):
+ url = "/projects/%s/checks/metrics/?api_key=%s" % (self.project.code, "X" * 32)
+ r = self.client.get(url)
+ self.assertEqual(r.status_code, 403)
diff --git a/hc/front/urls.py b/hc/front/urls.py
index c2aac38d..84203970 100644
--- a/hc/front/urls.py
+++ b/hc/front/urls.py
@@ -70,6 +70,7 @@ urlpatterns = [
path("projects/
{{ project.api_key_readonly }}
+ Prometheus metrics endpoint: + here +
{% endif %}