Merge ~andreserl/maas:prometheus_handler into maas:master

Proposed by Andres Rodriguez
Status: Merged
Approved by: Andres Rodriguez
Approved revision: e5eacbf606a33c6c658ed243e36e061845370373
Merge reported by: MAAS Lander
Merged at revision: not available
Proposed branch: ~andreserl/maas:prometheus_handler
Merge into: maas:master
Diff against target: 137 lines (+51/-1)
4 files modified
src/maasserver/middleware.py (+2/-0)
src/maasserver/prometheus.py (+15/-1)
src/maasserver/tests/test_prometheus.py (+32/-0)
src/maasserver/urls.py (+2/-0)
Reviewer Review Type Date Requested Status
Newell Jensen (community) Approve
Mike Pontillo (community) Approve
MAAS Lander Approve
Alberto Donato Pending
Review via email: mp+356836@code.launchpad.net

This proposal supersedes a proposal from 2018-10-03.

Commit message

Add handler to provide a metrics endpoint on /MAAS/metrics.

To post a comment you must log in.
Revision history for this message
Alberto Donato (ack) :
Revision history for this message
MAAS Lander (maas-lander) wrote :

UNIT TESTS
-b prometheus_handler lp:~andreserl/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: SUCCESS
COMMIT: 98432fd6bdc4f23b0e5357fa3c1d4398cc51d724

review: Approve
Revision history for this message
MAAS Lander (maas-lander) wrote :

UNIT TESTS
-b prometheus_handler lp:~andreserl/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: SUCCESS
COMMIT: bb37acc8271eb45cbe1749f6fc272d55d3a8f4a7

review: Approve
Revision history for this message
Mike Pontillo (mpontillo) wrote :

Looks good; I have a couple minor suggestions below.

review: Approve
Revision history for this message
Newell Jensen (newell-jensen) wrote :

LGTM, one inline question, not going to block.

review: Approve
Revision history for this message
Andres Rodriguez (andreserl) wrote :

addressed comments, which can be handled in a follow up branch.

Revision history for this message
MAAS Lander (maas-lander) wrote :
~andreserl/maas:prometheus_handler updated
e5eacbf... by Andres Rodriguez

Fix tests

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/src/maasserver/middleware.py b/src/maasserver/middleware.py
2index bcad2e8..1de6072 100644
3--- a/src/maasserver/middleware.py
4+++ b/src/maasserver/middleware.py
5@@ -75,6 +75,8 @@ PUBLIC_URL_PREFIXES = [
6 reverse('metadata'),
7 # RPC information is for use by rack controllers; no login.
8 reverse('rpc-info'),
9+ # Prometheus stats
10+ reverse('metrics'),
11 # API meta-information is publicly visible.
12 reverse('api_version'),
13 reverse('api_v1_error'),
14diff --git a/src/maasserver/prometheus.py b/src/maasserver/prometheus.py
15index d30aad3..55c58df 100644
16--- a/src/maasserver/prometheus.py
17+++ b/src/maasserver/prometheus.py
18@@ -11,6 +11,10 @@ __all__ = [
19 from datetime import timedelta
20 import json
21
22+from django.http import (
23+ HttpResponse,
24+ HttpResponseNotFound,
25+)
26 from maasserver.models import Config
27 from maasserver.stats import get_maas_stats
28 from maasserver.utils.orm import transactional
29@@ -24,6 +28,7 @@ try:
30 CollectorRegistry,
31 Gauge,
32 push_to_gateway,
33+ generate_latest,
34 )
35 PROMETHEUS = True
36 except:
37@@ -32,13 +37,22 @@ except:
38 log = LegacyLogger()
39
40
41+def prometheus_handler(request):
42+ if not Config.objects.get_config('prometheus_enabled'):
43+ return HttpResponseNotFound()
44+
45+ return HttpResponse(
46+ content=generate_latest(get_stats_for_prometheus()),
47+ content_type="text/plain")
48+
49+
50 def get_stats_for_prometheus():
51 registry = CollectorRegistry()
52 stats = json.loads(get_maas_stats())
53
54 # Gather counter for machines per status
55 counter = Gauge(
56- "machine_status", "Number per machines per stats",
57+ "machine_status", "Number of machines per status",
58 ["status"], registry=registry)
59 for status, machines in stats['machine_status'].items():
60 counter.labels(status).set(machines)
61diff --git a/src/maasserver/tests/test_prometheus.py b/src/maasserver/tests/test_prometheus.py
62index 66c1af6..fc93872 100644
63--- a/src/maasserver/tests/test_prometheus.py
64+++ b/src/maasserver/tests/test_prometheus.py
65@@ -5,6 +5,7 @@
66
67 __all__ = []
68
69+import http.client
70 import json
71
72 from django.db import transaction
73@@ -19,6 +20,7 @@ from maasserver.testing.testcase import (
74 MAASServerTestCase,
75 MAASTransactionServerTestCase,
76 )
77+from maasserver.utils.django_urls import reverse
78 from maastesting.matchers import (
79 MockCalledOnce,
80 MockCalledOnceWith,
81@@ -31,6 +33,36 @@ from twisted.application.internet import TimerService
82 from twisted.internet.defer import fail
83
84
85+class TestPrometheusHandler(MAASServerTestCase):
86+
87+ def test_prometheus_handler_returns_http_not_found(self):
88+ Config.objects.set_config('prometheus_enabled', False)
89+ response = self.client.get(reverse('metrics'))
90+ self.assertEqual("text/html; charset=utf-8", response["Content-Type"])
91+ self.assertEquals(response.status_code, http.client.NOT_FOUND)
92+
93+ def test_prometheus_handler_returns_success(self):
94+ Config.objects.set_config('prometheus_enabled', True)
95+ self.patch(prometheus, "CollectorRegistry")
96+ self.patch(prometheus, "Gauge")
97+ self.patch(prometheus, "generate_latest").return_value = {}
98+ response = self.client.get(reverse('metrics'))
99+ self.assertEqual("text/plain", response["Content-Type"])
100+ self.assertEquals(response.status_code, http.client.OK)
101+
102+ def test_prometheus_handler_returns_metrics(self):
103+ Config.objects.set_config('prometheus_enabled', True)
104+ metrics = (
105+ '# HELP machine_status Number per machines per stats'
106+ '# TYPE machine_status counter'
107+ 'machine_status={status="deployed"} 100')
108+ self.patch(prometheus, "CollectorRegistry")
109+ self.patch(prometheus, "Gauge")
110+ self.patch(prometheus, "generate_latest").return_value = metrics
111+ response = self.client.get(reverse('metrics'))
112+ self.assertEqual(metrics, response.content.decode("unicode_escape"))
113+
114+
115 class TestPrometheus(MAASServerTestCase):
116
117 def test_get_stats_for_prometheus(self):
118diff --git a/src/maasserver/urls.py b/src/maasserver/urls.py
119index 6c9c849..14dda55 100755
120--- a/src/maasserver/urls.py
121+++ b/src/maasserver/urls.py
122@@ -21,6 +21,7 @@ from maasserver.bootresources import (
123 simplestreams_stream_handler,
124 )
125 from maasserver.macaroon_auth import MacaroonDischargeRequest
126+from maasserver.prometheus import prometheus_handler
127 from maasserver.views import (
128 settings,
129 TextTemplateView,
130@@ -83,6 +84,7 @@ urlpatterns += [
131 r'^images-stream/(?P<os>.*)/(?P<arch>.*)/(?P<subarch>.*)/'
132 '(?P<series>.*)/(?P<version>.*)/(?P<filename>.*)$',
133 simplestreams_file_handler, name='simplestreams_file_handler'),
134+ url(r'^metrics$', prometheus_handler, name='metrics'),
135 url(
136 r'^robots\.txt$', TextTemplateView.as_view(
137 template_name='maasserver/robots.txt'),

Subscribers

People subscribed via source and target branches