|
from typing import Callable |
|
from urllib.parse import parse_qs |
|
|
|
from .exposition import _bake_output |
|
from .registry import CollectorRegistry, REGISTRY |
|
|
|
|
|
def make_asgi_app(registry: CollectorRegistry = REGISTRY, disable_compression: bool = False) -> Callable: |
|
"""Create a ASGI app which serves the metrics from a registry.""" |
|
|
|
async def prometheus_app(scope, receive, send): |
|
assert scope.get("type") == "http" |
|
|
|
params = parse_qs(scope.get('query_string', b'')) |
|
accept_header = ",".join([ |
|
value.decode("utf8") for (name, value) in scope.get('headers') |
|
if name.decode("utf8").lower() == 'accept' |
|
]) |
|
accept_encoding_header = ",".join([ |
|
value.decode("utf8") for (name, value) in scope.get('headers') |
|
if name.decode("utf8").lower() == 'accept-encoding' |
|
]) |
|
|
|
status, headers, output = _bake_output(registry, accept_header, accept_encoding_header, params, disable_compression) |
|
formatted_headers = [] |
|
for header in headers: |
|
formatted_headers.append(tuple(x.encode('utf8') for x in header)) |
|
|
|
payload = await receive() |
|
if payload.get("type") == "http.request": |
|
await send( |
|
{ |
|
"type": "http.response.start", |
|
"status": int(status.split(' ')[0]), |
|
"headers": formatted_headers, |
|
} |
|
) |
|
await send({"type": "http.response.body", "body": output}) |
|
|
|
return prometheus_app |
|
|