Files
bible/rules/patterns/go-logging/contract.md
2026-03-01 17:16:50 +03:00

67 lines
2.3 KiB
Markdown

# Contract: Logging (Go Web Applications)
Version: 1.0
## Core Rule
**All logging goes to the server binary's stdout/stderr — never to the browser console.**
- `console.log`, `console.error`, `console.warn` in JavaScript are for debugging only.
Remove them before committing. They are not a substitute for server-side logging.
- Diagnostic information (errors, slow queries, ingest results, background task status) must be
logged server-side so it is visible in the terminal where the binary runs.
## Go Logging Standard
Use the standard library `log/slog` (Go 1.21+) or `log` for simpler projects.
```go
// correct — structured, visible in binary console
slog.Info("export started", "user", userID, "rows", count)
slog.Error("db query failed", "err", err)
// wrong — goes to browser devtools, invisible in production
// (JS template rendered in HTML)
// console.log("export started")
```
## Log Levels
| Level | When to use |
|---------|-------------|
| `Debug` | Detailed flow tracing; disabled in production builds |
| `Info` | Normal operation milestones: server start, request handled, export done |
| `Warn` | Recoverable anomaly: retry, fallback used, deprecated path |
| `Error` | Operation failed; always include `"err", err` as a structured attribute |
## What to Always Log
- Server startup: address, port, config source.
- Background task start/finish/error with task name and duration.
- CSV/file export: scope, row count, duration.
- Ingest/import: file name, rows accepted, rows rejected, error summary.
- Any `500` response: handler name + error.
## What Not to Log
- Do not log full request bodies or CSV content — can contain PII or large payloads.
- Do not log passwords, tokens, or secrets even partially.
- Do not add `fmt.Println` for debugging and leave it in committed code.
## htmx / Browser-rendered Responses
- Handler errors that result in an htmx partial re-render must still log the error server-side.
- Do not rely on the browser network tab as the only visibility into server errors.
## Format
- Use structured key-value attributes, not concatenated strings.
```go
// correct
slog.Error("sync failed", "component", comp.Serial, "err", err)
// wrong — hard to grep, hard to parse
log.Printf("sync failed for component %s: %v", comp.Serial, err)
```