Go (Golang) Application Monitoring: From Metrics to Profiling
Go (Golang) is a language built for high-load server applications. However, even the most performant code can experience failures, memory leaks, or unjustifiably high latency. Without monitoring, you risk learning about a problem only from angry users. This article covers the key libraries and tools for monitoring Go applications: from collecting metrics to tracing and profiling.
Why Monitor a Go Application?
- Performance: track response time, number of goroutines, CPU and memory usage.
- Reliability: monitor errors, panics, restart count.
- Scaling: understand when to add replicas.
- Business Metrics: number of requests, active users, volume of processed data.
1. Built-in Package expvar
The simplest way is expvar. It provides an HTTP endpoint with basic metrics: number of goroutines, memory usage, uptime. Suitable for a quick start.
package main
import ( "expvar" "net/http")
var requestCount = expvar.NewInt("requests_total")
func handler(w http.ResponseWriter, r *http.Request) { requestCount.Add(1) w.Write([]byte("Hello, Go!"))}
func main() { http.HandleFunc("/", handler) // Metrics available at /debug/vars http.ListenAndServe(":8080", nil)}Run the application and open http://localhost:8080/debug/vars — you will see a JSON with metrics.
2. Prometheus + prometheus/client_golang
Prometheus is the de facto standard for collecting metrics in Go. The prometheus/client_golang library allows you to register custom metrics: counters, histograms, summaries.
package main
import ( "net/http" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp")
var ( httpRequests = prometheus.NewCounterVec( prometheus.CounterOpts{ Name: "http_requests_total", Help: "Total number of HTTP requests.", }, []string{"method", "path"}, ))
func init() { prometheus.MustRegister(httpRequests)}
func handler(w http.ResponseWriter, r *http.Request) { httpRequests.WithLabelValues(r.Method, r.URL.Path).Inc() w.Write([]byte("OK"))}
func main() { http.HandleFunc("/", handler) http.Handle("/metrics", promhttp.Handler()) http.ListenAndServe(":8080", nil)}The /metrics endpoint outputs data in a format that Prometheus understands. You can then configure dashboards in Grafana.
3. Profiling with pprof
The net/http/pprof package adds endpoints for profiling: CPU, memory, blocking, goroutines. This is an indispensable tool for finding bottlenecks.
package main
import ( "net/http" _ "net/http/pprof" // enable profiler)
func main() { http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("Profiling active")) }) http.ListenAndServe(":6060", nil)}Now you can run:
go tool pprof http://localhost:6060/debug/pprof/profile?seconds=30This will collect a 30-second CPU profile. Analyze it interactively or export it to SVG/PDF.
4. OpenTelemetry — Tracing and Metrics
OpenTelemetry (OTel) is a modern standard for observability. It unifies metrics, logs, and traces. For Go, there is the official SDK go.opentelemetry.io/otel.
package main
import ( "context" "log" "net/http" "go.opentelemetry.io Also in library
Chalk for JavaScript (Node.js): Complete Guide with Examples
Working with YAML in JavaScript (Node.js): parsing, generation and validation
Standard Library of JavaScript (Node.js): A Complete Overview
Go (Golang) Standard Library: Complete Overview