0
0
Fork 0
mirror of https://github.com/healthchecks/healthchecks.git synced 2025-04-10 23:40:11 +00:00

Improve performance of loading ping body previews

Defer loading body_raw, instead load its first 150 bytes
as "body_raw_preview". This reduces both network I/O to database,
and disk I/O on the database host if the database contains large
request bodies.

cc: 
This commit is contained in:
Pēteris Caune 2024-07-11 17:38:25 +03:00
parent 3e5080d9eb
commit 1b695c6970
No known key found for this signature in database
GPG key ID: E28D7679E9A9EDE2
4 changed files with 15 additions and 1 deletions
CHANGELOG.md
hc/front
templates/front

View file

@ -3,6 +3,9 @@ All notable changes to this project will be documented in this file.
## v3.5-dev - Unreleased ## v3.5-dev - Unreleased
### Improvements
- Improve performance of loading ping body previews (#1023)
### Bug Fixes ### Bug Fixes
- Fix Check.ping() to lock the check before updating (#1023) - Fix Check.ping() to lock the check before updating (#1023)

View file

@ -282,3 +282,8 @@ def fix_asterisks(s: str) -> str:
@register.filter @register.filter
def pct(v: float) -> str: def pct(v: float) -> str:
return str(int(v * 10000) / 100) return str(int(v * 10000) / 100)
@register.filter
def decode(v: bytes) -> str:
return bytes(v).decode(errors="replace")

View file

@ -26,6 +26,7 @@ from django.contrib.auth.models import User
from django.core import signing from django.core import signing
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
from django.db.models import Case, Count, F, Q, QuerySet, When from django.db.models import Case, Count, F, Q, QuerySet, When
from django.db.models.functions import Substr
from django.http import ( from django.http import (
Http404, Http404,
HttpRequest, HttpRequest,
@ -867,6 +868,11 @@ def _get_events(
kinds_filter = kinds_filter | Q(kind__isnull=True) | Q(kind="") kinds_filter = kinds_filter | Q(kind__isnull=True) | Q(kind="")
pq = pq.filter(kinds_filter) pq = pq.filter(kinds_filter)
# Optimization: defer loading body_raw, instead load its first 150 bytes
# as "body_raw_preview". This reduces both network I/O to database, and disk I/O
# on the database host if the database contains large request bodies.
pq = pq.defer("body_raw")
pq = pq.annotate(body_raw_preview=Substr("body_raw", 1, 151))
pings = list(pq[:page_limit]) pings = list(pq[:page_limit])
# Optimization: the template will access Ping.duration, which would generate a # Optimization: the template will access Ping.duration, which would generate a

View file

@ -17,7 +17,7 @@
{% if event.rid %}<span class="label rid">{{ event.rid|first5 }}</span> {% endif %} {% if event.rid %}<span class="label rid">{{ event.rid|first5 }}</span> {% endif %}
{% if event.scheme == "email" %}{{ event.ua }}{% else %} {% if event.scheme == "email" %}{{ event.ua }}{% else %}
{{ event.scheme|upper }} {{ event.method }}{% if event.remote_addr %} from {{ event.remote_addr }}{% endif %} {{ event.scheme|upper }} {{ event.method }}{% if event.remote_addr %} from {{ event.remote_addr }}{% endif %}
<code>{% if event.body_raw %}- {{ event.get_body|truncatechars:150 }}{% elif event.object_size %}- {{ event.object_size }} byte body{% endif %}{% if event.ua %} - {{ event.ua|truncatechars:80 }}{% endif %}</code> <code>{% if event.body_raw_preview %}- {{ event.body_raw_preview|decode }}{% elif event.object_size %}- {{ event.object_size }} byte body{% endif %}{% if event.ua %} - {{ event.ua|truncatechars:80 }}{% endif %}</code>
{% endif %} {% endif %}
</td> </td>
</tr> </tr>