Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 68 additions & 1 deletion src/om1_utils/httpx/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,17 @@

import httpx

from ..prometheus import (
om1_http_proxy_total_last_seconds,
om1_http_proxy_total_seconds,
om1_http_request_duration_last_seconds,
om1_http_request_duration_seconds,
om1_http_upstream_total_last_seconds,
om1_http_upstream_total_seconds,
om1_http_upstream_ttfb_last_seconds,
om1_http_upstream_ttfb_seconds,
)


def get_httpx_event_hooks() -> dict[str, list]:
"""
Expand Down Expand Up @@ -34,7 +45,14 @@ def log_response(response: httpx.Response):
response : httpx.Response
The HTTP response object to log.
"""
start_time = response.request.extensions.get("start_time", 0)
start_time = response.request.extensions.get("start_time", None)
if start_time is None:
logging.warning(
f"HTTP {response.request.method} {response.request.url} - "
"No start_time recorded, skipping metrics"
)
return

elapsed = (time.perf_counter() - start_time) * 1000
http_version = response.http_version
proxy_parse_total_time = response.headers.get("x-proxy-parse-ms", "?")
Expand All @@ -52,6 +70,55 @@ def log_response(response: httpx.Response):
f"Proxy Total Time: {proxy_total_time} ms"
)

method = response.request.method
status_code = str(response.status_code)
host = str(response.request.url.host)
path = str(response.request.url.path)
elapsed_s = elapsed / 1000.0

om1_http_request_duration_seconds.labels(
host=host, path=path, method=method, status_code=status_code
).observe(elapsed_s)
om1_http_request_duration_last_seconds.labels(
host=host, path=path, method=method, status_code=status_code
).set(elapsed_s)

if upstream_total_time != "?":
try:
val = float(upstream_total_time) / 1000.0
om1_http_upstream_total_seconds.labels(
host=host, path=path, method=method, status_code=status_code
).observe(val)
om1_http_upstream_total_last_seconds.labels(
host=host, path=path, method=method, status_code=status_code
).set(val)
except ValueError:
pass

if upstream_ttfb_time != "?":
try:
val = float(upstream_ttfb_time) / 1000.0
om1_http_upstream_ttfb_seconds.labels(
host=host, path=path, method=method, status_code=status_code
).observe(val)
om1_http_upstream_ttfb_last_seconds.labels(
host=host, path=path, method=method, status_code=status_code
).set(val)
except ValueError:
pass

if proxy_total_time != "?":
try:
val = float(proxy_total_time) / 1000.0
om1_http_proxy_total_seconds.labels(
host=host, path=path, method=method, status_code=status_code
).observe(val)
om1_http_proxy_total_last_seconds.labels(
host=host, path=path, method=method, status_code=status_code
).set(val)
except ValueError:
pass

return {
"request": [log_request],
"response": [log_response],
Expand Down
49 changes: 49 additions & 0 deletions src/om1_utils/prometheus/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
from prometheus_client import Gauge, Histogram

om1_http_request_duration_seconds = Histogram(
"om1_http_request_duration_seconds",
"Total HTTP request duration (client-side) in seconds",
["host", "path", "method", "status_code"],
)

om1_http_upstream_total_seconds = Histogram(
"om1_http_upstream_total_seconds",
"Upstream total time in seconds (from x-upstream-total-ms header)",
["host", "path", "method", "status_code"],
)

om1_http_upstream_ttfb_seconds = Histogram(
"om1_http_upstream_ttfb_seconds",
"Upstream TTFB in seconds (from x-upstream-ttfb-ms header)",
["host", "path", "method", "status_code"],
)

om1_http_proxy_total_seconds = Histogram(
"om1_http_proxy_total_seconds",
"Proxy total time in seconds (from x-proxy-total-ms header)",
["host", "path", "method", "status_code"],
)

om1_http_request_duration_last_seconds = Gauge(
"om1_http_request_duration_last_seconds",
"Most recent HTTP request duration (client-side) in seconds",
["host", "path", "method", "status_code"],
)

om1_http_upstream_total_last_seconds = Gauge(
"om1_http_upstream_total_last_seconds",
"Most recent upstream total time in seconds",
["host", "path", "method", "status_code"],
)

om1_http_upstream_ttfb_last_seconds = Gauge(
"om1_http_upstream_ttfb_last_seconds",
"Most recent upstream TTFB in seconds",
["host", "path", "method", "status_code"],
)

om1_http_proxy_total_last_seconds = Gauge(
"om1_http_proxy_total_last_seconds",
"Most recent proxy total time in seconds",
["host", "path", "method", "status_code"],
)
Loading