Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Disable certain prometheus metrics #109

Open
ivanovaleksandar opened this issue Feb 1, 2024 · 3 comments
Open

Disable certain prometheus metrics #109

ivanovaleksandar opened this issue Feb 1, 2024 · 3 comments

Comments

@ivanovaleksandar
Copy link

ivanovaleksandar commented Feb 1, 2024

Hi all

Is there a way to disable certain type of metrics at the moment? For example, disable request_size_bytes_bucket or just completely disable histograms for any type of metric.

In my case, i am doing a proxy type of a setup with at least 20 routes, so having histogram, bytes, etc generates tons of metrics.

@aldas
Copy link
Contributor

aldas commented Feb 1, 2024

Nope, requests_total, request_duration_seconds, response_size_bytes, request_size_bytes are built in.

but if you are OK not having histograms then it leaves you only with requests_total as this is counter. You could strip down the middleware to something like that and add your custom metrics if needed.

func myPrometheusRoute() echo.HandlerFunc {
	gatherer := prometheus.DefaultGatherer
	h := promhttp.HandlerFor(gatherer, promhttp.HandlerOpts{DisableCompression: true})

	if r, ok := gatherer.(prometheus.Registerer); ok {
		h = promhttp.InstrumentMetricHandler(r, h)
	}

	return func(c echo.Context) error {
		h.ServeHTTP(c.Response(), c.Request())
		return nil
	}
}

func myPrometheusMW() (echo.MiddlewareFunc, error) {
	requestCount := prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Namespace: "",
			Subsystem: "MY_APP",
			Name:      "requests_total",
			Help:      "How many HTTP requests processed, partitioned by status code and HTTP method.",
		},
		[]string{"code", "method", "host", "url"},
	)
	if err := prometheus.DefaultRegisterer.Register(requestCount); err != nil {
		return nil, err
	}

	return func(next echo.HandlerFunc) echo.HandlerFunc {
		return func(c echo.Context) error {
			err := next(c)
			status := c.Response().Status
			if err != nil {
				var httpError *echo.HTTPError
				if errors.As(err, &httpError) {
					status = httpError.Code
				}
				if status == 0 || status == http.StatusOK {
					status = http.StatusInternalServerError
				}
			}

			url := c.Path() // contains route path ala `/users/:id`
			if url == "" {
				// as of Echo v4.10.1 path is empty for 404 cases (when router did not find any matching routes)
				// in this case we use actual path from request to have some distinction in Prometheus
				url = c.Request().URL.Path
			}

			requestCount.WithLabelValues(
				strconv.Itoa(status),
				c.Request().Method,
				c.Request().Host,
				url,
			).Inc()
			return err
		}
	}, nil
}

This is https://github.com/labstack/echo-contrib/tree/master/echoprometheus stripped down

@aldas
Copy link
Contributor

aldas commented Feb 1, 2024

NB: you might need custom registry. This does not contain prometheus own default metrics

customRegistry := prometheus.NewRegistry() // create custom registry for your custom metrics

and make sure that you Route takes that registry in as gatherer

e.GET("/metrics", myPrometheusRoute(customRegistry))

and myPrometheusMW needs to use that same customRegistry to register metrics

@ivanovaleksandar
Copy link
Author

@aldas thank you for providing a workaround. I replicated almost the same locally, but was wondering if there is something that I am missing here.

Anyways, is it something that you want implemented? I mean, the optional disabling of these types of metrics.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants