Categorygithub.com/Depado/ginprom
modulepackage
1.8.1
Repository: https://github.com/depado/ginprom.git
Documentation: pkg.go.dev

# README

Ginprom

Gin Prometheus metrics exporter

Sourcegraph Go Report Card Build Status codecov License godoc

Inspired by github.com/zsais/go-gin-prometheus

Install

Simply run: go get -u github.com/Depado/ginprom

Differences with go-gin-prometheus

  • No support for Prometheus' Push Gateway
  • Options on constructor
  • Adds a path label to get the matched route
  • Ability to ignore routes

Usage

package main

import (
	"github.com/Depado/ginprom"
	"github.com/gin-gonic/gin"
)

func main() {
	r := gin.Default()
	p := ginprom.New(
		ginprom.Engine(r),
		ginprom.Subsystem("gin"),
		ginprom.Path("/metrics"),
	)
	r.Use(p.Instrument())

	r.GET("/hello/:id", func(c *gin.Context) {})
	r.GET("/world/:id", func(c *gin.Context) {})
	r.Run("127.0.0.1:8080")
}

Options

Custom counters

Add custom counters to add own values to the metrics

r := gin.New()
p := ginprom.New(
	ginprom.Engine(r),
)
p.AddCustomCounter("custom", "Some help text to provide", []string{"label"})
r.Use(p.Instrument())

Save p and use the following functions:

  • IncrementCounterValue
  • AddCounterValue

Custom gauges

Add custom gauges to add own values to the metrics

r := gin.New()
p := ginprom.New(
	ginprom.Engine(r),
)
p.AddCustomGauge("custom", "Some help text to provide", []string{"label"})
r.Use(p.Instrument())

Save p and use the following functions:

  • IncrementGaugeValue
  • DecrementGaugeValue
  • SetGaugeValue

Custom histograms

Add custom histograms to add own values to the metrics

r := gin.New()
p := ginprom.New(
  ginprom.Engine(r),
)
p.AddCustomHistogram("internal_request_latency", "Duration of internal HTTP requests", []string{"url", "method", "status"})
r.Use(p.Instrument())

Save p and use the following functions:

  • AddCustomHistogramValue

Path

Override the default path (/metrics) on which the metrics can be accessed:

r := gin.New()
p := ginprom.New(
	ginprom.Engine(r),
	ginprom.Path("/custom/metrics"),
)
r.Use(p.Instrument())

Namespace

Override the default namespace (gin):

r := gin.New()
p := ginprom.New(
	ginprom.Engine(r),
	ginprom.Namespace("custom_ns"),
)
r.Use(p.Instrument())

Subsystem

Override the default (gonic) subsystem:

r := gin.New()
p := ginprom.New(
	ginprom.Engine(r),
	ginprom.Subsystem("your_subsystem"),
)
r.Use(p.Instrument())

Engine

The preferred way to pass the router to ginprom:

r := gin.New()
p := ginprom.New(
	ginprom.Engine(r),
)
r.Use(p.Instrument())

The alternative being to call the Use method after initialization:

p := ginprom.New()
// ...
r := gin.New()
p.Use(r)
r.Use(p.Instrument())

Prometheus Registry

Use a custom prometheus.Registry instead of prometheus client's global registry. This option allows to use ginprom in multiple gin engines in the same process, or if you would like to integrate ginprom with your own prometheus Registry.

registry := prometheus.NewRegistry() // creates new prometheus metric registry
r := gin.New()
p := ginprom.New(
    ginprom.Registry(registry),
)
r.Use(p.Instrument())

HandlerNameFunc

Change the way the handler label is computed. By default, the (*gin.Context).HandlerName function is used. This option is useful when wanting to group different functions under the same handler label or when using gin with decorated handlers.

r := gin.Default()
p := ginprom.New(
	HandlerNameFunc(func (c *gin.Context) string {
		return "my handler"
	}),
)
r.Use(p.Instrument())

RequestPathFunc

Change how the path label is computed. By default, the (*gin.Context).FullPath function is used. This option is useful when wanting to group different requests under the same path label or when wanting to process unknown routes (the default (*gin.Context).FullPath returns an empty string for unregistered routes). Note that requests for which f returns the empty string are ignored.

To specifically ignore certain paths, see the Ignore option.

r := gin.Default()
p := ginprom.New(
	// record a metric for unregistered routes under the path label "<unknown>"
	RequestPathFunc(func (c *gin.Context) string {
		if fullpath := c.FullPath(); fullpath != "" {
			return fullpath
		}
		return "<unknown>"
	}),
)
r.Use(p.Instrument())

CustomCounterLabels

Add custom labels to the counter metric.

r := gin.Default()
p := ginprom.New(
  ginprom.CustomCounterLabels([]string{"client_id"}, func(c *gin.Context) map[string]string {
    client_id := c.GetHeader("x-client-id")
    if client_id == "" {
      client_id = "unknown"
    }
    return map[string]string{"client_id": client_id}
  }),
)
r.Use(p.Instrument())

Ignore

Ignore allows to completely ignore some routes. Even though you can apply the middleware to the only groups you're interested in, it is sometimes useful to have routes not instrumented.

r := gin.New()
p := ginprom.New(
	ginprom.Engine(r),
	ginprom.Ignore("/api/no/no/no", "/api/super/secret/route")
)
r.Use(p.Instrument())

Note that most of the time this can be solved by gin groups:

r := gin.New()
p := ginprom.New(ginprom.Engine(r))

// Add the routes that do not need instrumentation
g := r.Group("/api/")
g.Use(p.Instrument())
{
	// Instrumented routes
}

Token

Specify a secret token which Prometheus will use to access the endpoint. If the token is invalid, the endpoint will return an error.

r := gin.New()
p := ginprom.New(
	ginprom.Engine(r),
	ginprom.Token("supersecrettoken")
)
r.Use(p.Instrument())

Bucket size

Specify the bucket size for the request duration histogram according to your expected durations.

r := gin.New()
p := ginprom.New(
	ginprom.Engine(r),
	ginprom.BucketSize([]float64{.005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10}),
)
r.Use(p.Instrument())

Troubleshooting

The instrumentation doesn't seem to work

Make sure you have set the gin.Engine in the ginprom middleware, either when initializing it using ginprom.New(ginprom.Engine(r)) or using the Use function after the initialization like this :

p := ginprom.New(
	ginprom.Namespace("gin"),
	ginprom.Subsystem("gonic"),
	ginprom.Path("/metrics"),
)
p.Use(r)
r.Use(p.Instrument())

By design, if the middleware was to panic, it would do so when a route is called. That's why it just silently fails when no engine has been set.

# Functions

BucketSize is used to define the default bucket size when initializing with New.
No description provided by the author
Engine is an option allowing to set the gin engine when intializing with New.
HandlerNameFunc is an option allowing to set the HandlerNameFunc with New.
HandlerOpts is an option allowing to set the promhttp.HandlerOpts.
Ignore is used to disable instrumentation on some routes.
Namespace is an option allowing to set the namespace when initializing with New.
New will initialize a new Prometheus instance with the given options.
Path is an option allowing to set the metrics path when initializing with New.
Registry is an option allowing to set a *prometheus.Registry with New.
RequestCounterMetricName is an option allowing to set the request counter metric name.
RequestDurationMetricName is an option allowing to set the request duration metric name.
RequestPathFunc is an option allowing to set the RequestPathFunc with New.
RequestSizeMetricName is an option allowing to set the request size metric name.
ResponseSizeMetricName is an option allowing to set the response size metric name.
Subsystem is an option allowing to set the subsystem when initializing with New.
Token is an option allowing to set the bearer token in prometheus with New.

# Variables

ErrCustomCounter is returned when the custom counter can't be found.
ErrCustomGauge is returned when the custom gauge can't be found.
ErrInvalidToken is returned when the provided token is invalid or missing.

# Structs

Prometheus contains the metrics gathered by the instance and its path.

# Type aliases

No description provided by the author