Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for tornado. #308

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
23 changes: 23 additions & 0 deletions README.md
Expand Up @@ -280,6 +280,29 @@ reactor.listenTCP(8000, factory)
reactor.run()
```

#### Tornado

To use prometheus with [tornado](https://www.tornadoweb.org/), there is `MetricsHandler` which exposes metrics as a tornado handler.

```python
from prometheus_client.tornado import MetricsHandler

import tornado.ioloop
import tornado.web

def make_app():
return tornado.web.Application([
(r"/", MainHandler),
])

if __name__ == "__main__":
app = tornado.web.Application([
(r'/metrics', MetricsHandler)
])
app.listen(8888)
tornado.ioloop.IOLoop.current().start()
```

#### WSGI

To use Prometheus with [WSGI](http://wsgi.readthedocs.org/en/latest/), there is
Expand Down
3 changes: 3 additions & 0 deletions prometheus_client/tornado/__init__.py
@@ -0,0 +1,3 @@
from ._exposition import MetricsHandler

__all__ = ['MetricsHandler']
17 changes: 17 additions & 0 deletions prometheus_client/tornado/_exposition.py
@@ -0,0 +1,17 @@
from __future__ import absolute_import, unicode_literals
from .. import REGISTRY, exposition

import tornado.web


class MetricsHandler(tornado.web.RequestHandler):
"""
Tornado ``Handler`` that serves prometheus metrics.
"""
def initialize(self, registry=REGISTRY):
self.registry = registry

def get(self):
encoder, content_type = exposition.choose_encoder(self.request.headers.get('Accept'))
self.set_header('Content-Type', content_type)
self.write(encoder(self.registry))
2 changes: 2 additions & 0 deletions setup.py
Expand Up @@ -17,9 +17,11 @@
'prometheus_client.bridge',
'prometheus_client.openmetrics',
'prometheus_client.twisted',
'prometheus_client.tornado',
],
extras_require={
'twisted': ['twisted'],
'tornado': ['tornado'],
},
test_suite="tests",
classifiers=[
Expand Down
44 changes: 44 additions & 0 deletions tests/test_tornado.py
@@ -0,0 +1,44 @@
from __future__ import absolute_import, unicode_literals

import sys

if sys.version_info < (2, 7):
from unittest2 import skipUnless
else:
from unittest import skipUnless

from prometheus_client import Counter
from prometheus_client import CollectorRegistry, generate_latest

try:
from prometheus_client.tornado import MetricsHandler

import tornado.ioloop
import tornado.web
import tornado.testing
TestCase = tornado.testing.AsyncHTTPTestCase
HAVE_TORNADO = True
except ImportError:
from unittest import TestCase
HAVE_TORNADO = False


class MetricsResourceTest(TestCase):
def get_app(self):
self.registry = CollectorRegistry()
return tornado.web.Application([
(r'/metrics', MetricsHandler, {'registry': self.registry}),
])

@skipUnless(HAVE_TORNADO, "Don't have tornado installed.")
def test_reports_metrics(self):
"""
``MetricsHandler`` serves the metrics from the provided registry.
"""
c = Counter('cc', 'A counter', registry=self.registry)
c.inc()

resp = self.fetch('/metrics')

self.assertEqual(resp.code, 200)
self.assertEqual(resp.body, generate_latest(self.registry))
1 change: 1 addition & 0 deletions tox.ini
Expand Up @@ -30,6 +30,7 @@ deps =
deps =
{[base]deps}
{py27,py34,py35,py36,pypy}: twisted
{py27,py34,py35,py36,pypy}: tornado
commands = coverage run --parallel -m pytest {posargs}


Expand Down