Files
avandClaude Opus 4.8 f8fb4fabb3 Логирование: доменная граница ошибок + защита секретов в логах
Приём торрента через Telegram молча падал без записи в логах. Разобрали
цепочку и починили логирование/обработку ошибок по конвенции logging.md
(логирует граница домена один раз, транспорты — нет).

Доменная граница логирует исход:
- ingest.Ingest: сбой БД → ERROR, невалидный источник → DEBUG;
- команды воркера (Apply/Cancel/Retry/Refine/…) — единый чокпоинт logCmd
  (ERROR для инфраструктурного сбоя; DEBUG для conflict/not-ready/not-found),
  закрывает и Telegram-, и HTTP-путь; дублирующие ERROR-логи в tgbot сняты;
- внутренний логгер tgbotapi заведён в slog: сбои long-poll getUpdates
  больше не уходят в stdlib log мимо структурированных логов;
- тихое закрытие канала обновлений бота → ERROR.

Защита секретов (инвариант «секреты не в логи»):
- общий logging.SanitizeErr убирает URL из *url.Error;
- закрыты утечки токена бота (getMe на старте, getFile, Send/Request)
  и api_key TMDB (query-параметр, попадавший в *url.Error на ERROR);
- покрыто тестом internal/logging/sanitize_test.go.

Ревью двумя сабагентами (fable): инфраструктурные и доменные ошибки.
Отложено (не в scope этого коммита): обёртка ErrConflict в
Cancel/Defer/Retry и классификация 500→409/400, обновление docs/conventions.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 14:29:38 +03:00

47 lines
2.1 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package tgbot
import (
"fmt"
"log/slog"
"strings"
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
)
// SetLibraryLogger направляет внутренние логи клиента tgbotapi в наш slog.
//
// Зачем: библиотека логирует сбои long-poll `getUpdates` через собственный
// (stdlib `log`) логгер — МИМО slog. Из-за этого сетевые/API-ошибки поллинга не
// попадали в структурированные JSON-логи: входящее сообщение молча не
// подхватывалось, а в логах — пусто (см. logging.md). После вызова такие сбои
// видны как `telegram library` (WARN).
//
// Токен вырезается из текста: строка ошибки транспорта — `*url.Error` с URL вида
// `…/bot<TOKEN>/getUpdates`, писать её как есть нельзя (утечка секрета в логи).
// Замена по подстроке страхует и от прочих мест, где токен мог бы просочиться.
//
// Логгер в tgbotapi — глобальный на пакет; вызывать один раз при старте.
func SetLibraryLogger(log *slog.Logger, token string) error {
return tgbotapi.SetLogger(libLogger{log: log, token: token})
}
type libLogger struct {
log *slog.Logger
token string
}
func (l libLogger) Println(v ...any) { l.emit(fmt.Sprintln(v...)) }
func (l libLogger) Printf(format string, v ...any) { l.emit(fmt.Sprintf(format, v...)) }
func (l libLogger) emit(msg string) {
msg = strings.TrimSpace(msg)
if l.token != "" {
msg = strings.ReplaceAll(msg, l.token, "***")
}
// Сбои поллинга транзиентны (библиотека повторяет через 3 с) — WARN
// («retry внешнего вызова»); устойчивый сбой станет потоком WARN — сигнал
// разбираться, но не ERROR на каждый повтор.
l.log.Warn("telegram library", "detail", msg)
}