← Назад к вопросам

Как отследить медленную работу запроса?

2.0 Middle🔥 191 комментариев
#Observability#Производительность и оптимизация

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Методы отслеживания медленных запросов в Go

Отслеживание медленных запросов — критически важная задача для поддержания производительности приложения. Вот комплексный подход к мониторингу производительности API в Go-приложениях.

Инструментарий и подходы

1. Встроенные средства Go

Используйте middleware для измерения времени выполнения запросов:

package main

import (
    "log"
    "net/http"
    "time"
)

// Middleware для логирования времени выполнения
func loggingMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        start := time.Now()
        
        // Создаем кастомный ResponseWriter для перехвата статуса
        rw := &responseWriter{ResponseWriter: w, statusCode: http.StatusOK}
        
        next.ServeHTTP(rw, r)
        
        duration := time.Since(start)
        
        // Логируем медленные запросы (например, > 500ms)
        if duration > 500*time.Millisecond {
            log.Printf("SLOW REQUEST: %s %s - %d - %v", 
                r.Method, r.URL.Path, rw.statusCode, duration)
        }
    })
}

type responseWriter struct {
    http.ResponseWriter
    statusCode int
}

func (rw *responseWriter) WriteHeader(code int) {
    rw.statusCode = code
    rw.ResponseWriter.WriteHeader(code)
}

2. Использование pprof для профилирования

Go предоставляет мощный инструмент pprof для анализа производительности:

import (
    _ "net/http/pprof"
    "net/http"
)

func main() {
    // Регистрируем pprof endpoints
    go func() {
        http.ListenAndServe("localhost:6060", nil)
    }()
    
    // Теперь можно анализировать:
    // - /debug/pprof/profile?seconds=30 (CPU профиль)
    // - /debug/pprof/heap (профиль памяти)
    // - /debug/pprof/trace?seconds=5 (трассировка)
}

Практические стратегии мониторинга

Уровень приложения

  1. Структурированное логирование с использованием zap или logrus:
import "go.uber.org/zap"

func trackRequest(logger *zap.Logger, method, path string, start time.Time) {
    duration := time.Since(start)
    if duration > time.Second {
        logger.Warn("Slow request detected",
            zap.String("method", method),
            zap.String("path", path),
            zap.Duration("duration", duration),
            zap.Time("timestamp", start),
        )
    }
}
  1. Метрики и экспорт в Prometheus:
import (
    "github.com/prometheus/client_golang/prometheus"
    "github.com/prometheus/client_golang/prometheus/promhttp"
)

var requestDuration = prometheus.NewHistogramVec(
    prometheus.HistogramOpts{
        Name:    "http_request_duration_seconds",
        Help:    "Duration of HTTP requests",
        Buckets: prometheus.DefBuckets,
    },
    []string{"method", "endpoint", "status"},
)

func init() {
    prometheus.MustRegister(requestDuration)
}

Уровень базы данных

Для отслеживания медленных SQL-запросов:

  1. Контексты с таймаутами:
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()

row := db.QueryRowContext(ctx, "SELECT * FROM users WHERE id = $1", userID)
  1. Логирование запросов в драйвере БД:
import "gorm.io/gorm/logger"

newLogger := logger.New(
    log.New(os.Stdout, "\r\n", log.LstdFlags),
    logger.Config{
        SlowThreshold: 200 * time.Millisecond,
        LogLevel:      logger.Warn,
    },
)

Распределенная трассировка

Для микросервисных архитектур используйте OpenTelemetry:

import (
    "go.opentelemetry.io/otel"
    "go.opentelemetry.io/otel/exporters/jaeger"
)

func initTracer() {
    exporter, _ := jaeger.New(jaeger.WithCollectorEndpoint(
        jaeger.WithEndpoint("http://jaeger:14268/api/traces"),
    ))
    
    tp := sdktrace.NewTracerProvider(
        sdktrace.WithBatcher(exporter),
        sdktrace.WithResource(resource.NewWithAttributes(
            semconv.SchemaURL,
            semconv.ServiceNameKey.String("my-service"),
        )),
    )
    
    otel.SetTracerProvider(tp)
}

Проактивные меры и алертинг

Мониторинг в реальном времени

  1. Настройка алертов в Prometheus/Grafana:
# prometheus.yml
rules:
  - alert: SlowAPIRequests
    expr: histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m])) > 1
    for: 2m
  1. Дашборды Grafana с ключевыми метриками:
    • Перцентили времени ответа (p95, p99)
    • Количество медленных запросов в минуту
    • Топ-5 самых медленных эндпоинтов

Анализ и оптимизация

  1. Профилирование CPU/Memory через pprof
  2. Анализ blocking profile для горутин
  3. Трассировка для понимания полного пути запроса

Рекомендации по внедрению

  1. Начните с middleware для базового отслеживания
  2. Внедрите структурированное логирование с четкими порогами
  3. Добавьте метрики для долгосрочного анализа
  4. Настройте алертинг для критических эндпоинтов
  5. Проводите регулярные нагрузки тесты для выявления деградации

Ключевой принцип: не просто отслеживайте медленные запросы, а автоматизируйте их анализ и создавайте петлю обратной связи для разработчиков. Интегрируйте данные о производительности в ваш CI/CD pipeline для предотвращения регрессий.