go-http-metrics

repository·master·Indexed 19 days ago

https://github.com/slok/go-http-metrics

A Go library for measuring HTTP metrics based on RED and Four Golden Signals. It supports various Go HTTP frameworks and metric backends, including Prometheus and OpenCensus, tracking request duration, request count, response size, and inflight requests.

Tokens
1.5K
Snippets
1
Records
6
Agent score
16%

What's inside go-http-metrics

  1. What metrics does go-http-metrics measure?

    master

    The middleware measures the following key metrics based on the [RED] and [Four Golden Signals] principles:

    • Request Duration: The time taken to process requests (labeled with code, handler, and method).
    • Request Count: The total number of requests (labeled with code, handler, and method).
    • Response Size: The size of the responses (labeled with code, handler, and method).
    • Inflight Requests: The number of requests currently being handled concurrently (labeled with handler).
  2. Getting Started with go-http-metrics

    master

    To get started, you need to create a middleware factory using middleware.New with a middleware.Config, and then wrap your HTTP handlers using a framework-specific provider (e.g., middlewarestd.Handler for the standard library).

    This example demonstrates using Prometheus as the recorder with the standard Go net/http library:

    package main
    
    import (
        "log"
        "net/http"
    
        "github.com/prometheus/client_golang/prometheus/promhttp"
        metrics "github.com/slok/go-http-metrics/metrics/prometheus"
        "github.com/slok/go-http-metrics/middleware"
        middlewarestd "github.com/slok/go-http-metrics/middleware/std"
    )
    
    func main() {
        // Create our middleware.
        mdlw := middleware.New(middleware.Config{
            Recorder: metrics.NewRecorder(metrics.Config{}),
        })
    
        // Our handler.
        h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
            w.WriteHeader(http.StatusOK)
            w.Write([]byte("hello world!"))
        })
        h = middlewarestd.Handler("", mdlw, h)
    
        // Serve metrics.
        log.Printf("serving metrics at: %s", ":9090")
        go http.ListenAndServe(":9090", promhttp.Handler())
    
        // Serve our handler.
        log.Printf("listening at: %s", ":8080")
        if err := http.ListenAndServe(":8080", h); err != nil {
            log.Panicf("error while serving: %s", err)
        }
    }
  3. Configure Middleware Options

    master

    The middleware.Config object controls how the middleware behaves. Key options include:

    • Recorder: The implementation of the metrics backend (e.g., Prometheus or OpenCensus). Defaults to a dummy recorder.
    • Service: An optional string to set a specific service name on all metrics. Useful for distinguishing between different servers (e.g., API vs Metrics server) using the same recorder.
    • GroupedStatus: If enabled, status codes are grouped into the dxx form (e.g., 4xx instead of 401, 404). This reduces cardinality but loses detail. Disabled by default.
    • DisableMeasureSize: If true, stops measuring response sizes.
    • DisableMeasureInflight: If true, stops measuring concurrent (inflight) requests.
    • IgnoredPaths: A list of paths that will not be measured for duration or response size, though they will still be counted in RequestsInflight.

    Note on Handler IDs: When wrapping a handler, you provide a handlerID.

    • If you pass an empty string "", the handler label is derived from the URL path. This can cause high cardinality if paths contain dynamic parameters (e.g., /p/123/dashboard).
    • If you pass a predefined pattern like "/p/:userID/dashboard/:page", cardinality remains low because dynamic segments are collapsed into the pattern.
  4. Configure Prometheus Recorder Options

    master

    When using the Prometheus recorder, you can customize the following via metrics.Config:

    • Prefix: Adds a prefix to all exposed metrics (e.g., Prefix: "batman" turns http_request_duration_seconds_count into batman_http_request_duration_seconds_count).
    • DurationBuckets: Customizes the histogram buckets for request duration. Default is Prometheus defaults (5ms to 10s). Example: []float64{.5, 1, 2.5, 5, 10, 20, 40, 80, 160, 320}. It is advised not to use more than 10 buckets.
    • SizeBuckets: Customizes the histogram buckets for response size (in bytes). Default is 1B to 1GB.
    • Registry: The Prometheus registry to use. Defaults to the global Prometheus registry.
    • HandlerIDLabel, StatusCodeLabel, MethodLabel, etc.: Allows customizing the names of the labels used in the metrics.
  5. Configure OpenCensus Recorder Options

    master

    When using the OpenCensus recorder, you can customize:

    • DurationBuckets: Customizes the histogram buckets for request duration.
    • SizeBuckets: Customizes the histogram buckets for response size.
    • Label names: Customizes the names of the labels (e.g., HandlerIDLabel, StatusCodeLabel, MethodLabel).
    • UnregisterViewsBeforeRegister: Used to unregister views before registration. This is primarily for testing environments to avoid issues with OpenCensus's global state.
  6. Prometheus Query Examples for HTTP Metrics

    master

    Once your metrics are being collected, use these PromQL queries to analyze your service:

    Request rate by handler:

    sum(
        rate(http_request_duration_seconds_count[30s])
    ) by (handler)

    Request error rate (5xx):

    rate(http_request_duration_seconds_count{code=~"5.."}[30s])

    99th percentile latency for the whole service:

    histogram_quantile(0.99, 
        rate(http_request_duration_seconds_bucket[5m]))

    90th percentile latency per handler:

    histogram_quantile(0.9, 
        sum(
            rate(http_request_duration_seconds_bucket[10m])
        ) by (handler, le)
    )