Содержание
GlitchTip: чтение событий после выпуска
Назначение: наблюдение известных issue после выпуска без повторного чтения всей истории. Проверено 22.10.2026 на https://glitchtip.olvery.ru, GlitchTip 6.1.6. Это сервисный рецепт, не изменение collector или сервера.
Поддержка установленного API
У следующих списков нет серверных фильтров release и времени:
GET /api/0/issues/{issue_id}/events/;GET /api/0/projects/{organization_slug}/{project_slug}/events/.
Параметры release, query, start, end здесь не применяются. HTTP200, пустая выборка, наличие параметров в следующей Link-ссылке или совместимость SDK с Sentry не доказывают поддержку фильтра.
Рабочий путь — limit и штатный cursor из Link, локальные проверки release/времени. Не конструировать курсор самостоятельно. Для запроса достаточно существующего glitchtip-olv3729 через штатный helper; токен и полный ответ не выводить и не сохранять.
Короткий пример одного GET
Пример читает одну запись известной issue, выводит только HTTP-код, release, времена и наличие следующей страницы. Это не полный observation и не доказательство исправности приложения.
/home/olvr/bin/olvr-secret run glitchtip-olv3729 -- python3 - <<'PY'
import json, os, urllib.parse, urllib.request
url = "https://glitchtip.olvery.ru/api/0/issues/29879/events/"
url += "?" + urllib.parse.urlencode({"limit": 1})
req = urllib.request.Request(url, headers={
"Authorization": "Bearer " + os.environ["OLVR_SECRET"]})
with urllib.request.urlopen(req, timeout=25) as r:
rows = json.load(r)
link = r.headers.get("Link", "")
print("http", r.status, "rows", len(rows))
for e in rows:
tags = e.get("tags") or {}
if isinstance(tags, list):
tags = {t.get("key"): t.get("value") for t in tags}
release = tags.get("release") or e.get("release")
if isinstance(release, dict):
release = release.get("version")
print({"release": release,
"dateReceived": e.get("dateReceived") or e.get("date_received"),
"dateCreated": e.get("dateCreated") or e.get("date_created")})
print("has_next", any('rel="next"' in p and 'results="true"' in p
for p in link.split(",")))
PY
Для обычного обхода используется ?limit=100. urllib.parse.urlencode кодирует query-значения; литеральный плюс в 4.6.5+9716 должен стать %2B, а не пробелом. Это правило encoding, не обещание наличия release-фильтра.
Минимальный штатный обход
- Начать с issue events без самодельного cursor. Читать страницы вперёд по Link с
rel=«next»иresults=«true»; перед передачей Authorization проверять тот же HTTPS-hostglitchtip.olvery.ruи API-путь.limit=100— размер страницы, не общий предел. - Нормализовать
dateReceived/date_receivedкак UTC datetime. Это серверное поступление.dateCreated/date_created— время события от клиента; им нельзя заменять границу поступления. - Локально сравнивать exact release, без prefix/substrings. Для семантики исходного PSTU observation: release равен
com.tpark_it.pstu@4.6.5+9716ИЛИ app context содержитapp_identifier=com.tpark_it.pstu,app_version=4.6.5,app_build=9716. Проверка только release уже этого исходного контракта. Версия/build без app identifier также недостаточны. - Для результата «после выпуска» учитывать только события с
dateReceived >= 2026-10-22T12:17:07Z. Проверять все события нужного временного диапазона, независимо от release. - Списки этой версии упорядочены по
-idUUIDv7, что соответствует невозрастанию серверногоdateReceived. На странице, пересёкшей cutoff, обработать подходящие события; когда встретилось серверное время строго меньше cutoff, более старые страницы для post-cutoff результата не нужны. Равное cutoff время включается. При отсутствующем/неразбираемом времени или нарушенном порядке не объявлять раннюю остановку полным доказательством: сохранить gap. - Если Link закончился раньше cutoff, завершена доступная выдача этого endpoint. Если нужен итог по всей сохранённой истории, а не только после cutoff, раннюю остановку по времени не применять.
Отсутствие событий с ошибкой не доказывает успешные сессии. List endpoint читает свой queryset; полноценность cold-storage-истории этим рецептом не обещается.
Почему фильтрам нельзя доверять
Минимальный read-only control на issue 29879, 22.10.2026 16:20:17Z:
?limit=1→ HTTP200, 1 событие: releasecom.tpark_it.pstu@4.6.1+7740, received2026-10-22T08:17:55.915Z;- те же
limit=1плюсrelease=jfVY-no-such-release-2099,start=2099-01-01T00:00:00Z,end=2099-01-02T00:00:00Z,query=release:«jfVY-no-such-release-2099» timestamp:>2099-01-01→ HTTP200, та же запись2026.
Идентичность сравнивалась в памяти; идентификаторы и пользовательский payload не сохранялись. В отличие от пустого ответа, непустой контрпример показывает игнорирование переданных ограничений; точный набор поддержанных параметров установлен исходником.
Версия, evidence и пересмотр
Фактический target: srv-glitchtip.olvr, glitchtip-web-1, glitchtip/glitchtip:6, running. GLITCHTIP_VERSION=6.1.6.
- Image ID:
sha256:8476bbdf291f946850fc6430d2cab62836918638ced34f4791593081bc067128; - RepoDigest:
glitchtip/glitchtip@sha256:f45485d296697531464b4484ee9bb40a51a774df820f74128a2b2ae0c5a0b00f; /code/apps/issue_events/api/events.py:20–35,77–85,209–226: queryset ограничен доступом и issue/project; оба списка не принимают фильтры и сортируют по-id;- SHA256 этого файла:
1eae9be2df11f27cc5bbc29c24a73dce7d875be1f23c22e030507672ecb1eaac; /code/apps/issue_events/schema.py:214–219: created→timestamp, received→received;/code/apps/issue_events/models.py:308–317: received извлекается из серверного UUIDv7 с миллисекундной точностью;/code/glitchtip/api/pagination.py: AsyncLinkHeaderPagination, limit/cursor и Link. Возвращаемый Link сохраняет исходные query-параметры, но это не означает их применение.
GET /api/0/ возвращает API version 0, не версию приложения.
Evidence: Card jfVY, receipts OvtbEO, 0r9VZC, XEu7hX, 4XP9Pe. Безопасные artifacts: /home/BVNq/work/jfVY/installed-api-contract.txt, filter-controls-safe.json и соответствующие диагностические скрипты. Источник исходного observation — 3kfw/0dgUUT; его collector и принятое observation не менялись и не переаттестовывались.
После смены GlitchTip image/version сверять затронутый API-контракт заново. Доработка сервера, новый collector, runner или общий механизм фильтрации в этот рецепт не входят.
