/
hooks.py
65 lines (46 loc) · 1.79 KB
/
hooks.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
"""Gunicorn integration for web-top.
This module provides hooks you can refer in Gunicorn config.
See `Gunicorn settings <https://docs.gunicorn.org/en/stable/settings.html>`_
"""
import os
from gunicorn.http import Request
from gunicorn.http.wsgi import Response
from gunicorn.workers.base import Worker
from top.integration import get_tracker_by_url_config
from top.web.task import HTTPTask
tracker_url = os.environ.get("TOP_TRACKER_URL")
if not tracker_url:
raise RuntimeError("You must pass TOP_TRACKER_URL env variable if you wish to use gunicorn top integration")
#: A global initialisation per worker, etc.
#: Not sure if gunicorn offers us a smarter approach to do this,
#: e.g. by worker?
#:
#: Explicit set URL to None to force reading the backend
#: URL from TOP_TRACKER_URL environment variable.
#:
tracker = get_tracker_by_url_config(HTTPTask, url=None)
def when_ready(server):
"""Called when the web server restarts."""
tracker.clear()
def pre_request(worker: Worker, req: Request):
"""Gunicorn pre_request hook."""
task_id = id(req)
task = HTTPTask.create_from_current_thread(
task_id,
path=req.path,
method=req.method,
processor_name=str(worker),
request_headers=req.headers,
client_ip_address=str(req.peer_addr[0]), # ip, port tuple
)
tracker.start_task(task)
req.tracked_task = task
def post_request(worker: Worker, req: Request, environ: dict, resp: Response):
"""Gunicorn post_request hook."""
task: HTTPTask = getattr(req, "tracked_task", None)
assert task is not None, "Request did not carry tracking information"
if resp is not None:
task.status_code = resp.status_code
task.status_message = resp.status
task.response_headers = resp.headers
tracker.end_task(task)