Skip to content

Commit 8aa22d6

Browse files
committed
Log HTTP request codes & timings to Prometheus
Code adapted from JupyterHub
1 parent a764f90 commit 8aa22d6

File tree

2 files changed

+41
-1
lines changed

2 files changed

+41
-1
lines changed

notebook/log.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
import json
99
from tornado.log import access_log
10+
from .metrics import prometheus_log_method
1011

1112
def log_request(handler):
1213
"""log a bit more information about each request than tornado's default
@@ -45,4 +46,4 @@ def log_request(handler):
4546
# log all headers if it caused an error
4647
log_method(json.dumps(dict(request.headers), indent=2))
4748
log_method(msg.format(**ns))
48-
49+
prometheus_log_method(handler)

notebook/metrics.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
"""
2+
Prometheus metrics exported by Jupyter Notebook Server
3+
4+
Read https://prometheus.io/docs/practices/naming/ for naming
5+
conventions for metrics & labels. We generally prefer naming them
6+
`<noun>_<verb>_<type_suffix>`. So a histogram that's tracking
7+
the duration (in seconds) of servers spawning would be called
8+
SERVER_SPAWN_DURATION_SECONDS.
9+
"""
10+
11+
from prometheus_client import Histogram
12+
13+
REQUEST_DURATION_SECONDS = Histogram(
14+
'request_duration_seconds',
15+
'request duration for all HTTP requests',
16+
['method', 'handler', 'code'],
17+
)
18+
19+
def prometheus_log_method(handler):
20+
"""
21+
Tornado log handler for recording RED metrics.
22+
23+
We record the following metrics:
24+
Rate – the number of requests, per second, your services are serving.
25+
Errors – the number of failed requests per second.
26+
Duration – The amount of time each request takes expressed as a time interval.
27+
28+
We use a fully qualified name of the handler as a label,
29+
rather than every url path to reduce cardinality.
30+
31+
This function should be either the value of or called from a function
32+
that is the 'log_function' tornado setting. This makes it get called
33+
at the end of every request, allowing us to record the metrics we need.
34+
"""
35+
REQUEST_DURATION_SECONDS.labels(
36+
method=handler.request.method,
37+
handler='{}.{}'.format(handler.__class__.__module__, type(handler).__name__),
38+
code=handler.get_status()
39+
).observe(handler.request.request_time())

0 commit comments

Comments
 (0)