refactor: merge internal/sync into internal/garmin, regroup api files and routes
Garmin auth/sync routes move under /api/garmin/*; sync.Service becomes garmin.Sync with garmin.SyncConfig/ClientConfig; applog becomes internal/log; the test mock moves into the garmin package as MockClient (breaking the test-only import cycle the merge created); stale test URLs and type names updated to match. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
|
||||
**Goal:** Emit structured JSON logs on stdout for (1) every HTTP API request and (2) every Garmin wrapper subprocess call, correlated by a per-request id — without touching any existing `log.Printf` call site.
|
||||
|
||||
**Architecture:** A new `internal/applog` package wraps `log/slog` with a JSON handler plus context helpers (`WithLogger`/`FromContext`). `internal/api` gains a `requestLoggingMiddleware` that logs one line per HTTP request and stashes a request-id-tagged logger into the request context. `internal/garmin`'s `client.go` reads that same logger back out of context (via the `ctx` every `Client` method already receives) inside `roundTrip`, the single funnel point all six Garmin calls go through, logging one line per subprocess round-trip.
|
||||
**Architecture:** A new `internal/applog` package wraps `log/slog` with a JSON handler plus context helpers (`WithLogger`/`FromContext`). `internal/api` gains a `loggingMiddleware` that logs one line per HTTP request and stashes a request-id-tagged logger into the request context. `internal/garmin`'s `client.go` reads that same logger back out of context (via the `ctx` every `Client` method already receives) inside `roundTrip`, the single funnel point all six Garmin calls go through, logging one line per subprocess round-trip.
|
||||
|
||||
**Tech Stack:** Go stdlib `log/slog` (no new dependency), `github.com/go-chi/chi/v5/middleware` (already-available subpackage of the existing chi dependency).
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
**Files:**
|
||||
- Create: `backend/internal/applog/applog.go`
|
||||
- Create: `backend/internal/applog/applog_test.go`
|
||||
- Create: `../../../backend/internal/log/log_test.go`
|
||||
|
||||
**Interfaces:**
|
||||
- Produces: `func NewLogger(level string, w io.Writer) *slog.Logger`, `func WithLogger(ctx context.Context, logger *slog.Logger) context.Context`, `func FromContext(ctx context.Context) *slog.Logger` (never nil — falls back to `slog.Default()`).
|
||||
@@ -91,7 +91,7 @@ func TestFromContext_DefaultsWhenNoneSet(t *testing.T) {
|
||||
Run: `cd backend && go test ./internal/applog/... -v`
|
||||
Expected: FAIL — package `internal/applog` doesn't exist yet (build failure).
|
||||
|
||||
- [ ] **Step 3: Create `backend/internal/applog/applog.go`**
|
||||
- [ ] **Step 3: Create `../../../backend/internal/log/log.go`**
|
||||
|
||||
```go
|
||||
// Package applog provides geniusrun's structured JSON logging: a
|
||||
@@ -164,19 +164,19 @@ git commit -m "feat(applog): add JSON logger and context helpers"
|
||||
### Task 2: HTTP access log middleware
|
||||
|
||||
**Files:**
|
||||
- Modify: `backend/internal/config/config.go` (new `LogLevel` field)
|
||||
- Modify: `backend/internal/config/config_test.go` (new tests)
|
||||
- Modify: `../../../backend/internal/config/envconfig.go` (new `LogLevel` field)
|
||||
- Modify: `../../../backend/internal/config/envconfig_test.go` (new tests)
|
||||
- Modify: `backend/cmd/geniusrund/main.go` (wire up `slog.SetDefault`)
|
||||
- Modify: `backend/internal/api/server.go` (`requestLoggingMiddleware`, registered in `Router()`)
|
||||
- Modify: `backend/internal/api/server.go` (`loggingMiddleware`, registered in `Router()`)
|
||||
- Modify: `backend/internal/api/api_test.go` (new tests)
|
||||
|
||||
**Interfaces:**
|
||||
- Consumes: `applog.NewLogger`, `applog.WithLogger`, `applog.FromContext` (Task 1).
|
||||
- Produces: `requestLoggingMiddleware` (unexported chi middleware in `internal/api`), `config.Config.LogLevel string`.
|
||||
- Produces: `loggingMiddleware` (unexported chi middleware in `internal/api`), `config.Config.LogLevel string`.
|
||||
|
||||
- [ ] **Step 1: Write the failing config tests**
|
||||
|
||||
Append to `backend/internal/config/config_test.go`:
|
||||
Append to `../../../backend/internal/config/envconfig_test.go`:
|
||||
|
||||
```go
|
||||
func TestLoad_LogLevelDefaultsToInfo(t *testing.T) {
|
||||
@@ -276,7 +276,7 @@ func TestRequestLoggingMiddleware_5xxLogsAtWarnLevel(t *testing.T) {
|
||||
Run: `cd backend && go test ./internal/config/... ./internal/api/... -run 'TestLoad_LogLevel|TestRequestLoggingMiddleware' -v`
|
||||
Expected: FAIL — `LogLevel` field doesn't exist on `Config`; `applog` import unresolved; no log output produced (middleware doesn't exist).
|
||||
|
||||
- [ ] **Step 4: Add `LogLevel` to `config.go`**
|
||||
- [ ] **Step 4: Add `LogLevel` to `envconfig.go`**
|
||||
|
||||
Change:
|
||||
|
||||
@@ -471,7 +471,7 @@ Expected: `gofmt -l .` empty; everything passes.
|
||||
- [ ] **Step 9: Commit**
|
||||
|
||||
```bash
|
||||
git add backend/internal/config/config.go backend/internal/config/config_test.go backend/cmd/geniusrund/main.go backend/internal/api/server.go backend/internal/api/api_test.go
|
||||
git add backend/internal/config/envconfig.go backend/internal/config/envconfig_test.go backend/cmd/geniusrund/main.go backend/internal/api/server.go backend/internal/api/api_test.go
|
||||
git commit -m "feat(api): add structured JSON access log with request-id correlation"
|
||||
```
|
||||
|
||||
|
||||
Reference in New Issue
Block a user