Noções Básicas de Observabilidade
9 exemplos para você começar com Observabilidade - 7 básicos e 2 intermediários.
Busque em todas as páginas da documentação
9 exemplos para você começar com Observabilidade - 7 básicos e 2 intermediários.
mkdir oblab && cd oblab && go mod init example.com/oblab.go get github.com/prometheus/client_golang/prometheus/promhttp e módulos OpenTelemetry conforme necessário.O Go 1.21+ define um logger estruturado padrão que você pode chamar sem configuração.
package main
import (
"log/slog"
)
func main() {
slog.Info("servidor iniciando", "porta", 8080)
}slog.Info grava pares chave-valor após a mensagem.Relacionado: Logging Estruturado com slog - manipuladores e níveis
Logs JSON são analisados de forma limpa em Loki, Elasticsearch e CloudWatch.
package main
import (
"log/slog"
"os"
)
func main() {
logger := slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelInfo}))
slog.SetDefault(logger)
slog.Info("pronto", "serviço", "api")
}NewJSONHandler emite um objeto JSON por linha.SetDefault faz com que as chamadas slog no nível do pacote usem seu manipulador.Level para slog.LevelDebug apenas em desenvolvimento.Relacionado: Go em Produção: Logs, Métricas, Traces e Sinais - visão geral de observabilidade
Anexe um ID de correlação ao contexto para logs e chamadas downstream.
package main
import (
"context"
"crypto/rand"
"encoding/hex"
"net/http"
)
type ctxKey string
const requestIDKey ctxKey = "request_id"
func withRequestID(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
id := r.Header.Get("X-Request-ID")
if id == "" {
var b [16]byte
rand.Read(b[:])
id = hex.EncodeToString(b[:])
}
ctx := context.WithValue(r.Context(), requestIDKey, id)
w.Header().Set("X-Request-ID", id)
next.ServeHTTP(w, r.WithContext(ctx))
})
}X-Request-ID recebido quando presente para continuidade de trace.Relacionado: Cadeias de Middleware e Contexto de Solicitação - envolvendo manipuladores
Registre método, caminho e status para cada solicitação HTTP.
package main
import (
"log/slog"
"net/http"
"time"
)
type statusWriter struct {
http.ResponseWriter
code int
}
func (w *statusWriter) WriteHeader(code int) {
w.code = code
w.ResponseWriter.WriteHeader(code)
}
func loggingMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
sw := &statusWriter{ResponseWriter: w, code: http.StatusOK}
next.ServeHTTP(sw, r)
slog.Info("solicitação",
"método", r.Method,
"caminho", r.URL.Path,
"status", sw.code,
"duração_ms", time.Since(start).Milliseconds(),
)
})
}ResponseWriter para capturar o código de status final.DEBUG em produção para reduzir o ruído.Relacionado: Logging Estruturado com slog - padrões de middleware
/healthzA liveness deve ser barata e nunca chamar sistemas externos.
package main
import (
"net/http"
)
func healthz(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Write([]byte("ok"))
}
func main() {
mux := http.NewServeMux()
mux.HandleFunc("GET /healthz", healthz)
http.ListenAndServe(":8080", mux)
}livenessProbe do Kubernetes acessa este caminho em um intervalo curto.Relacionado: Sondas de Integridade, Prontidão e Liveness - design de sondas
/readyzA prontidão controla o tráfego quando as dependências não estão íntegras.
package main
import (
"net/http"
"sync/atomic"
)
var ready atomic.Bool
func readyz(w http.ResponseWriter, r *http.Request) {
if !ready.Load() {
http.Error(w, "não pronto", http.StatusServiceUnavailable)
return
}
w.WriteHeader(http.StatusOK)
w.Write([]byte("pronto"))
}
func main() {
ready.Store(true)
mux := http.NewServeMux()
mux.HandleFunc("GET /readyz", readyz)
http.ListenAndServe(":8080", mux)
}ready para false durante a inicialização até que as migrações terminem.Relacionado: Sondas de Integridade, Prontidão e Liveness - verificações de dependência
Aplicações 12-factor leem a configuração do ambiente na inicialização.
package main
import (
"log/slog"
"os"
)
func main() {
port := os.Getenv("PORT")
if port == "" {
port = "8080"
}
slog.Info("configuração carregada", "porta", port, "env", os.Getenv("APP_ENV"))
}main quando as variáveis necessárias estiverem ausentes.Relacionado: Gerenciamento de Configuração: Env, Flags e Viper - padrões completos de configuração
/metricsExponha um endpoint de scrape para totais de solicitação.
package main
import (
"net/http"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
var requests = prometheus.NewCounterVec(
prometheus.CounterOpts{Name: "http_requests_total", Help: "HTTP requests"},
[]string{"method", "code"},
)
func main() {
prometheus.MustRegister(requests)
mux := http.NewServeMux()
mux.Handle("GET /metrics", promhttp.Handler())
mux.HandleFunc("GET /hello", func(w http.ResponseWriter, r *http.Request) {
requests.WithLabelValues(r.Method, "200").Inc()
w.Write([]byte("hello"))
})
http.ListenAndServe(":8080", mux)
}main, não por manipulador de solicitação./metrics a redes internas ou middleware de autenticação.Relacionado: Métricas Prometheus e Dashboards RED/USE - dashboards RED
Drene solicitações HTTP em andamento antes da saída do processo.
package main
import (
"context"
"log/slog"
"net/http"
"os"
"os/signal"
"syscall"
"time"
)
func main() {
srv := &http.Server{Addr: ":8080", Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("ok"))
})}
go func() {
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
slog.Error("falha ao escutar", "err", err)
os.Exit(1)
}
}()
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
<-quit
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
defer cancel()
if err := srv.Shutdown(ctx); err != nil {
slog.Error("falha ao desligar", "err", err)
}
slog.Info("servidor parado")
}Shutdown para de aceitar novas conexões e aguarda as solicitações ativas.terminationGracePeriodSeconds do Kubernetes.Relacionado: Desligamento Gracioso e Manipulação de Sinais - padrões de errgroup
Versões da Pilha: Esta página foi escrita para Go 1.26.x (padrão GC Green Tea, modernizadores go fix - verifique o patch na compilação), chi (mais recente - verifique na compilação), gin (mais recente - verifique na compilação), echo (mais recente - verifique na compilação), google.golang.org/grpc (mais recente - verifique na compilação), sigs.k8s.io/controller-runtime (mais recente - verifique na compilação), kubebuilder (mais recente - verifique na compilação), tinygo (mais recente - verifique os alvos de placa na compilação), wazero (mais recente - verifique na compilação) e golangci-lint (mais recente - verifique o conjunto de linters na compilação).
Revisado por Chris St. John·Última atualização: 19 de jul. de 2026