// Package logctx переносит scoped-логдер загрузки через context.Context. // // На приёме/реконсиляции загрузки заводим логгер с её ключами // (download_id [+ infohash], capability) и кладём в ctx; стадии (скачивание → // распознавание → раскладка → ревью) достают его через From и пишут с уже // дописанными ключами — без ручного доклеивания download_id в каждый вызов. package logctx import ( "context" "log/slog" ) type ctxKey struct{} // With возвращает ctx со вложенным логгером. func With(ctx context.Context, log *slog.Logger) context.Context { return context.WithValue(ctx, ctxKey{}, log) } // From достаёт логгер из ctx; при отсутствии — slog.Default(). func From(ctx context.Context) *slog.Logger { return FromOr(ctx, slog.Default()) } // FromOr достаёт логгер из ctx; при отсутствии — fallback (или slog.Default(), // если fallback nil). Удобно во внешних клиентах: внутри стадии загрузки вернёт // scoped-логгер с download_id, при автономном вызове — собственный логгер клиента. func FromOr(ctx context.Context, fallback *slog.Logger) *slog.Logger { if ctx != nil { if log, ok := ctx.Value(ctxKey{}).(*slog.Logger); ok && log != nil { return log } } if fallback != nil { return fallback } return slog.Default() }