fix(observability): убрать 83% мусора из трекера ошибок #2906
No reviewers
Labels
No labels
Fable 5 ревью
GG-форсайт
admin
analytics
auth
automation
bug
business
chore
ci
compliance
data
data-moat
docs
duplicate
dx
enhancement
feedback/max
generative
needs-discussion
needs-human
observability
pause-bots
performance
priority/p0
priority/p1
priority/p2
priority/p3
scope/backend
scope/db
scope/devops
scope/frontend
scope/qa
scrapers
security
site-finder
stage/1
stage/2
status/blocked
status/done
status/needs-analysis
status/needs-fix
status/qa
status/ready
status/review
status/wip
tech-debt
tradein
ux
week ревью 1
wontfix
ИРД
вторичка
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: lekss361/gendesign#2906
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "fix/tradein-glitchtip-noise"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Проблема
Из аудита 15.08. В GlitchTip 7 461 issue, из них unresolved 7 460. Содержательного — около 700.
Это не косметика. Пока 83% трекера — мусор, заводить получателя алертов бессмысленно: канал утонет в первый же день. Поэтому фикс идёт перед подключением уведомлений, а не после.
Что сделано
401 от неаутентифицированного запроса больше не уходит в трекер. Это сканеры-боты, ломящиеся в закрытый basic_auth сайт, — не ошибка сервиса. Отсечка на источнике, в
before_send, а не чистка постфактум в интерфейсе.RetryError стабилизирован. Здесь первый круг ревью нашёл, что исходная правка проблему не решала, а переименовывала:
reraise=Trueпропускает наверх исходное исключение с тем же нестабильным текстом. Проверено эмпирически — в сообщении httpx лежит полный URL с адресом пользователя в query, поэтому каждый запрос порождал новый issue. Теперь query вырезается, host и path остаются.Разные подсистемы больше не сливаются в один issue. Прежний fingerprint затирал дефолт целиком, и отказ геокодера схлопывался с отказом скрапера, если тип причины совпал. Это было бы хуже исходного шума — потеря сигнала вместо потери тишины. В ключ добавлен источник события.
Плюс сравнение типа исключения по имени класса заменено на честный
isinstanceс прямым импортом.Что осознанно не сделано
Второй источник
RetryErrorнайден, но не тронут —BaseScraper._http_getвscraper_kit. Там URL варьируется в пути (id объявления), а не в query, поэтому та же правка не помогла бы, а вмешательство в транспорт скраперов выходит за рамки этого PR. Задокументировано в коде.Уже накопленные 7 460 issue не чищены — это действие в проде, отдельным шагом.
Test plan
OperationalErrorпроходят83% of tracker issues (7460 total) were pure noise drowning real signal: - basic_auth 401 (3738 issues, 2019 distinct titles) — ops/glitchtip-auth- forwarder sent EVERY 401 from bots scanning gendsgn.ru (GET /wp-admin/ install.php etc.) as an individual GlitchTip event, remote_ip baked into message/tags inflated cardinality. Not an application error — expected bot-scan traffic against a basic_auth-protected site. - RetryError (2462 issues) — geocoder.py's three tenacity @retry-wrapped Nominatim helpers (lookup/suggest/reverse) raised tenacity.RetryError on exhaustion without reraise=True; RetryError.__str__() embeds a Future repr() with a memory address that differs every call, so GlitchTip grouped each exhausted retry as a distinct issue instead of one. Fix at the source, not post-hoc issue cleanup: - forwarder.py: before_send drops events tagged event_type in {basic_auth_failed, basic_auth_storm}; forwarder's own capture_exception (real script bugs) carries no such tag and passes through untouched. - geocoder.py: reraise=True on all three @retry decorators — propagates the real underlying exception (stable type + stacktrace) instead of the unstable RetryError wrapper. - sentry_scrub.stabilize_retry_error_fingerprint: belt-and-suspenders before_send hook, composed into both app/main.py and scheduler_main.py (geocoder runs in both processes — FastAPI request path and the overnight geocode_missing_listings batch). Collapses any RetryError that still slips through into one persistent issue per cause-exception type name only — never IP/address/listing-id. Content-ful categories (OperationalError, city-sweep, harvest_quarter, cian/avito/yandex sweep failures, scrape_freshness_check — ~700 issues) are untouched: filters key off event_type tag / exception type name only.