eduardo-sl/go-agent-skills

go-observability

Structured logging, distributed tracing, metrics, and health checks for Go services.

View source

How to use

  1. Copy the installation command and review the source package before installing it in your own agent environment.
  2. Check the source document for required tools, credentials and supported hosts.
  3. Describe your input and desired deliverable; review the output against the source material.
npx skills add https://github.com/eduardo-sl/go-agent-skills --skill go-observability

Before you start

  • Installation does not include a model subscription, API allowance or permission to access your files.
  • Repository stars and installation counts describe activity, not an independent quality or security test.
Original skill document

Rendered from the source repository. Headings, examples, code, tables, links, and referenced images are preserved.

Go Observability

Observability is not optional for production services. Every service must produce structured logs, expose metrics, and propagate trace context. Use the stdlib log/slog for logging and OpenTelemetry for tracing and metrics.

Detailed reference material, loaded on demand:

  • references/slog.md — handler setup, logger injection, child loggers.
  • references/tracing.md — tracer provider, spans, propagation, shutdown.
  • references/metrics.md — metric definitions, HTTP instrumentation.

Read a reference file only when the section below is not enough.

1. Structured Logging with slog

Use log/slog (Go 1.21+) with a JSON handler in production. Every line is key-value pairs, never a formatted sentence:

go
// ✅ Good — structured, leveled
logger.Info("user created", slog.String("user_id", user.ID), slog.Duration("latency", elapsed))

// ❌ Bad — unparseable in production
log.Printf("user %s created in %v", user.ID, elapsed)

Inject the logger as a dependency; never reach for a package-level global. Derive child loggers with logger.With(...) so component, method and request ID are attached once instead of at every call site. See references/slog.md.

Log levels — use them consistently

LevelUse for
DebugVerbose diagnostic info, disabled in production
InfoNormal operations: request received, job completed
WarnRecoverable issues: retry succeeded, deprecated usage
ErrorFailures requiring attention: DB down, external call failed

NEVER log at Error level for expected conditions (user not found → Info or Warn).

Sensitive data — NEVER log

  • Passwords, tokens, API keys
  • Full credit card numbers, SSNs
  • Raw request bodies containing PII
go
// ✅ Good — redacted
logger.Info("auth attempt", slog.String("user", email), slog.Bool("success", ok))

// ❌ Bad — leaks credentials
logger.Info("auth attempt", slog.String("password", password))

2. Distributed Tracing with OpenTelemetry

Start a span for every operation worth seeing on a waterfall — inbound requests, DB calls, outbound HTTP, meaningful business steps — and always defer span.End().

Rules the reference examples follow:

  • Name the span after the operation (GetUser, db.query), never after the

fully-qualified function, and never doStuff.

  • On failure call span.RecordError(err) and span.SetStatus(codes.Error, ...),

or the trace shows a green span for a failed request.

  • Pass ctx down the whole chain. A context.Background() mid-chain silently

starts a new trace and breaks the parent link.

Setup and examples in references/tracing.md.

3. Metrics with OpenTelemetry / Prometheus

TypeUse forExample
CounterMonotonically increasing valuesRequests total, errors total
GaugeValues that go up and downActive connections, queue depth
HistogramDistribution of valuesRequest latency, response size

Naming is <namespace>_<subsystem>_<name>_<unit>:

text
http_request_duration_seconds     ✅ (unit in name)
http_requests_total               ✅ (counter with _total suffix)
db_connections_active             ✅ (gauge, no suffix needed)
user_signups                      ❌ (missing _total for counter)
requestLatency                    ❌ (camelCase, no unit)

Keep cardinality bounded. Label with the route pattern, method and status — never a user ID, request ID or raw r.URL.Path, each of which mints a new time series per value and eventually takes the metrics backend down.

Definitions and middleware in references/metrics.md.

4. Connecting Logs, Traces, and Metrics

A log line without a trace ID cannot be joined to the request that produced it. Pull trace.SpanContextFromContext(ctx) and attach trace_id and span_id to the logger at the top of each handler or service method.

5. Graceful Shutdown of Telemetry

The batch span processor holds spans in memory. Call tp.Shutdown(ctx) with its own timeout on the way out, or the last seconds before a crash — the interesting ones — never reach the collector.

Both examples in references/tracing.md.

Verification Checklist

  1. All logging uses log/slog with structured key-value pairs, not fmt.Printf or log.Printf
  2. Logger is injected as a dependency, not used as a global
  3. No sensitive data (passwords, tokens, PII) in log output
  4. Trace context is propagated through all function calls via context.Context
  5. Spans are created for significant operations (DB calls, HTTP requests, business logic)
  6. Spans record errors with span.RecordError(err) and set error status
  7. Metrics follow naming conventions: _seconds, _total, _bytes
  8. No high-cardinality labels (user IDs, request IDs) in metrics
  9. Telemetry providers are shut down gracefully on service exit
  10. Trace IDs are included in log entries for correlation

Related by task

from this repository

More skills

All skills
eduardo-sl
Community

go-ci

Continuous integration for Go projects: GitHub Actions pipelines, caching, golangci-lint setup, test/coverage gates, vulnerability scanning, build matrices, and Makefile targets. Use when: "set up CI", "GitHub Actions for Go", "add lint to the pipeline", "CI is slow", "coverage gate", "build matrix", "write a Makefile", "run govulncheck in CI". Not for: commit conventions (git-commit), choosing or auditing dependencies (go-dependency-audit), writing the tests themselves (go-test-quality).

installs
1
GitHub stars
71
Updated
Aug 18
eduardo-sl
Community

go-cli

Build command-line tools in Go: flag handling, subcommands, stdin/stdout discipline, exit codes, signal handling, and when Cobra/Viper earn their weight over the standard library. Use when: "build a CLI", "add a subcommand", "parse flags", "exit codes", "handle Ctrl+C", "cobra command", "read from stdin", "CLI UX". Not for: HTTP APIs (go-api-design), scaffolding (go-project-layout), service configuration (go-architecture-review).

installs
1
GitHub stars
71
Updated
Aug 18
eduardo-sl
Community

go-coding-standards

Go coding standards and style conventions grounded in Effective Go, Go Code Review Comments, and production-proven idioms. Use when writing or reviewing Go code, enforcing naming conventions, import ordering, variable declarations, struct initialization, or formatting rules. Trigger examples: "check Go style", "fix formatting", "review naming", "Go conventions". Not for: architecture (go-architecture-review), concurrency (go-concurrency-review), performance tuning (go-performance-review).

installs
1
GitHub stars
71
Updated
Aug 18
eduardo-sl
Community

go-context

Correct usage of context.Context in Go: propagation, cancellation, timeouts, deadlines, values, and common anti-patterns. Use when: "context usage", "context.Context", "context cancellation", "timeout", "context.WithTimeout", "context.WithCancel", "context values", "context propagation". Not for: concurrency beyond context (go-concurrency-review), HTTP middleware (go-api-design), error handling (go-error-handling).

installs
1
GitHub stars
71
Updated
Aug 18