Files
bible/kit/patterns/go-logging/contract.md
Michael Chus 40d1c303bb Add shared engineering rule contracts
- go-logging: slog, server-side only, structured attributes
- go-database: MySQL cursor safety, soft delete, GORM tags, fail-fast, N+1 prevention
- go-background-tasks: Task Manager pattern, polling, no SSE
- go-code-style: layering, error wrapping, startup sequence, config, templating
- import-export: CSV Excel-compatible rules (BOM, semicolon, decimal comma, DD.MM.YYYY)
- table-management: filtering and pagination rules added
- CLAUDE.template.md: updated to reference all shared contracts

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-01 16:39:39 +03:00

2.3 KiB

Contract: Logging (Go Web Applications)

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.

// 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.
// 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)