Monitoreo avanzado de aplicaciones Go: desde métricas hasta alertas
En el desarrollo moderno con Go (Golang), el registro básico y los Health Check no son suficientes. Para sistemas en producción se requiere una observabilidad profunda: recolección de métricas personalizadas, su exportación a Prometheus, visualización en Grafana y alertas automáticas. En este artículo analizaremos el nivel avanzado de monitoreo de aplicaciones Go, desde la arquitectura de métricas hasta la configuración de alertas basadas en lógica de negocio.
Arquitectura de monitoreo: Prometheus + Go
El stack estándar de monitoreo para Go incluye:
- Prometheus — sistema de recolección y almacenamiento de métricas (modelo pull).
- Cliente Go de Prometheus (
prometheus/client_golang) — biblioteca para exportar métricas. - Grafana — visualización de paneles.
- Alertmanager — gestión de alertas (email, Slack, Telegram).
La aplicación Go debe proporcionar un endpoint HTTP (generalmente /metrics) desde el cual Prometheus recolecta los datos. Veamos la configuración básica.
package main
import ( "net/http" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp")
func main() { // Registro de métricas estándar de Go (runtime, GC, goroutines) prometheus.MustRegister(prometheus.NewProcessCollector(prometheus.ProcessCollectorOpts{})) prometheus.MustRegister(prometheus.NewGoCollector())
http.Handle("/metrics", promhttp.Handler()) http.ListenAndServe(":8080", nil)}Al ejecutar la aplicación, obtendrá métricas estándar: go_goroutines, process_cpu_seconds_total, go_memstats_alloc_bytes y otras. Pero para un monitoreo avanzado esto no es suficiente: se necesitan métricas personalizadas.
Creación de métricas personalizadas: Gauge, Counter, Histogram
Prometheus admite cuatro tipos principales de métricas. Veámoslos con el ejemplo de una aplicación Go que procesa solicitudes HTTP.
Counter (contador) — número de eventos
Se utiliza para contar solicitudes, errores, ejecución de tareas.
var requestCounter = prometheus.NewCounterVec( prometheus.CounterOpts{ Name: "http_requests_total", Help: "Número total de solicitudes HTTP", }, []string{"method", "endpoint", "status"},)
func init() { prometheus.MustRegister(requestCounter)}
func handler(w http.ResponseWriter, r *http.Request) { // Procesamiento de la solicitud requestCounter.WithLabelValues(r.Method, r.URL.Path, "200").Inc()}Gauge (medidor) — valores actuales
Ideal para monitorear colas, pools de conexiones, temperatura.
var queueSize = prometheus.NewGauge( prometheus.GaugeOpts{ Name: "task_queue_size", Help: "Tamaño actual de la cola de tareas", },)
func addToQueue() { queueSize.Inc()}
func processFromQueue() { queueSize.Dec()}Histogram (histograma) — distribución de valores
Se utiliza para medir el tiempo de respuesta o el tamaño de los datos.
var requestDuration = prometheus.NewHistogramVec( prometheus.HistogramOpts{ Name: "http_request_duration_seconds", Help: "Histograma del tiempo de procesamiento de solicitudes", Buckets: prometheus.DefBuckets, // 0.005, 0.01, 0.025, 0.05, ... }, []string{"endpoint"},)
func measureRequest(endpoint string, duration float64) { requestDuration.WithLabelValues(endpoint).Observe(duration)}Summary (resumen) — cuantiles
Similar al histograma, pero calcula cuantiles precisos (p50, p95, p99).
var requestLatency = prometheus.NewSummaryVec( prometheus.SummaryOpts{ Name: "http_request_latency_seconds", Help: "Latencia de solicitudes (cuantiles)",