feat: track monitoring tg poll errors

This commit is contained in:
Grendgi
2026-06-17 17:01:34 +03:00
parent 6cbfdb92e4
commit bd3b54dc7d
4 changed files with 110 additions and 0 deletions

View File

@@ -266,6 +266,7 @@ func (a *app) handleHealthDetail(w http.ResponseWriter, r *http.Request) {
a.probeClassificationQueue(ctx),
a.probeAIJobs(ctx),
a.probePoller(ctx),
a.probePollErrors(ctx),
a.probeMediaStorage(ctx),
a.probeMediaMetadata(ctx),
}
@@ -423,6 +424,43 @@ func (a *app) probePoller(ctx context.Context) componentProbe {
return componentProbe{Name: "poller", Status: "ok", LatencyMs: time.Since(start).Milliseconds()}
}
func (a *app) probePollErrors(ctx context.Context) componentProbe {
start := time.Now()
var total, floodWait, unavailable, other int64
err := a.db.QueryRow(ctx, `
SELECT
COUNT(*) FILTER (WHERE last_poll_status = 'error')::bigint,
COUNT(*) FILTER (WHERE last_poll_status = 'error' AND last_poll_error_code = 'telegram_flood_wait')::bigint,
COUNT(*) FILTER (WHERE last_poll_status = 'error' AND last_poll_error_code = 'telegram_channel_unavailable')::bigint,
COUNT(*) FILTER (
WHERE last_poll_status = 'error'
AND COALESCE(last_poll_error_code, '') NOT IN ('telegram_flood_wait', 'telegram_channel_unavailable')
)::bigint
FROM channels
WHERE is_active = true
AND source_channel_id IS NULL`,
).Scan(&total, &floodWait, &unavailable, &other)
if err != nil {
return componentProbe{Name: "poll_errors", Status: "down", LatencyMs: time.Since(start).Milliseconds(), Error: err.Error()}
}
if total > 0 {
status := "degraded"
if other > 0 {
status = "down"
}
return componentProbe{
Name: "poll_errors",
Status: status,
LatencyMs: time.Since(start).Milliseconds(),
Error: "total=" + strconv.FormatInt(total, 10) +
" flood_wait=" + strconv.FormatInt(floodWait, 10) +
" unavailable=" + strconv.FormatInt(unavailable, 10) +
" other=" + strconv.FormatInt(other, 10),
}
}
return componentProbe{Name: "poll_errors", Status: "ok", LatencyMs: time.Since(start).Milliseconds()}
}
func (a *app) probeMediaStorage(ctx context.Context) componentProbe {
start := time.Now()
if a.minio == nil || a.cfg.MinioBucket == "" {