{"id":13491718,"url":"https://github.com/slok/go-http-metrics","last_synced_at":"2025-04-11T03:29:37.464Z","repository":{"id":34326758,"uuid":"176080676","full_name":"slok/go-http-metrics","owner":"slok","description":"Go modular http middleware to measure HTTP requests independent of metrics backend (with Prometheus and OpenCensus as backend implementations) and http framework/library","archived":false,"fork":false,"pushed_at":"2025-04-02T11:06:49.000Z","size":831,"stargazers_count":411,"open_issues_count":26,"forks_count":74,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-03T19:51:47.695Z","etag":null,"topics":["echo","echo-framework","gin","gin-framework","go","golang","http","http-metrics","http-middleware","instrumentation","metrics","middleware","observability","opencensus","opencensus-recorder","prometheus"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/slok.png","metadata":{"files":{"readme":"Readme.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-03-17T09:30:53.000Z","updated_at":"2025-04-01T09:06:59.000Z","dependencies_parsed_at":"2024-02-27T10:27:55.617Z","dependency_job_id":"16dbda28-1d1c-44be-b90e-1658904cd1f8","html_url":"https://github.com/slok/go-http-metrics","commit_stats":{"total_commits":159,"total_committers":7,"mean_commits":"22.714285714285715","dds":"0.44025157232704404","last_synced_commit":"7668c45d29d376962ffd09c2524d8ddeada2a822"},"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/slok%2Fgo-http-metrics","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/slok%2Fgo-http-metrics/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/slok%2Fgo-http-metrics/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/slok%2Fgo-http-metrics/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/slok","download_url":"https://codeload.github.com/slok/go-http-metrics/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248335236,"owners_count":21086540,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["echo","echo-framework","gin","gin-framework","go","golang","http","http-metrics","http-middleware","instrumentation","metrics","middleware","observability","opencensus","opencensus-recorder","prometheus"],"created_at":"2024-07-31T19:00:59.604Z","updated_at":"2025-04-11T03:29:37.445Z","avatar_url":"https://github.com/slok.png","language":"Go","funding_links":[],"categories":["Go","Integrations"],"sub_categories":["Go"],"readme":"# go-http-metrics [![Build Status][github-actions-image]][github-actions-url] [![Go Report Card][goreport-image]][goreport-url] [![GoDoc][godoc-image]][godoc-url]\n\ngo-http-metrics knows how to measure http metrics in different metric formats and Go HTTP framework/libs. The metrics measured are based on [RED] and/or [Four golden signals], follow standards and try to be measured in a efficient way.\n\n## Table of contents\n\n- [Metrics](#metrics)\n- [Metrics recorder implementations](#metrics-recorder-implementations)\n- [Framework compatibility middlewares](#framework-compatibility-middlewares)\n- [Getting Started](#getting-started)\n- [Prometheus query examples](#prometheus-query-examples)\n- [Options](#options)\n  - [Middleware Options](#middleware-options)\n  - [Prometheus recorder options](#prometheus-recorder-options)\n  - [OpenCensus recorder options](#opencensus-recorder-options)\n- [Benchmarks](#benchmarks)\n\n## Metrics\n\nThe metrics obtained with this middleware are the [most important ones][red] for a HTTP service.\n\n- Records the duration of the requests(with: code, handler, method).\n- Records the count of the requests(with: code, handler, method).\n- Records the size of the responses(with: code, handler, method).\n- Records the number requests being handled concurrently at a given time a.k.a inflight requests (with: handler).\n\n## Metrics recorder implementations\n\ngo-http-metrics is easy to extend to different metric backends by implementing `metrics.Recorder` interface.\n\n- [Prometheus][prometheus-recorder]\n- [OpenCensus][opencensus-recorder]\n\n## Framework compatibility middlewares\n\nThe middleware is mainly focused to be compatible with Go std library using http.Handler, but it comes with helpers to get middlewares for other frameworks or libraries.\n\n**When `go-http-metrics` is imported as a dependency, it will only import the libraries being used, this is safe because each lib/framework is in its own package. More information [here][import-information-1] and [here][import-information-2]**\n\n- [Alice][alice-example]\n- [Chi][chi-example]\n- [Echo][echo-example]\n- [Fasthttp][fasthttp-example]\n- [Gin][gin-example]\n- [Go http.Handler][default-example]\n- [Go-restful][gorestful-example]\n- [Goji][goji-example]\n- [Gorilla][gorilla-example]\n- [Httprouter][httprouter-example]\n- [Iris][iris-example]\n- [Negroni][negroni-example]\n\nIt supports any framework that supports http.Handler provider type middleware `func(http.Handler) http.Handler` (e.g Chi, Alice, Gorilla...). Use [`std.HandlerProvider`][handler-provider-docs]\n\n## Getting Started\n\nA simple example that uses Prometheus as the recorder with the standard Go handler.\n\n```golang\npackage main\n\nimport (\n    \"log\"\n    \"net/http\"\n\n    \"github.com/prometheus/client_golang/prometheus/promhttp\"\n    metrics \"github.com/slok/go-http-metrics/metrics/prometheus\"\n    \"github.com/slok/go-http-metrics/middleware\"\n    middlewarestd \"github.com/slok/go-http-metrics/middleware/std\"\n)\n\nfunc main() {\n    // Create our middleware.\n    mdlw := middleware.New(middleware.Config{\n        Recorder: metrics.NewRecorder(metrics.Config{}),\n    })\n\n    // Our handler.\n    h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n        w.WriteHeader(http.StatusOK)\n        w.Write([]byte(\"hello world!\"))\n    })\n    h = middlewarestd.Handler(\"\", mdlw, h)\n\n    // Serve metrics.\n    log.Printf(\"serving metrics at: %s\", \":9090\")\n    go http.ListenAndServe(\":9090\", promhttp.Handler())\n\n    // Serve our handler.\n    log.Printf(\"listening at: %s\", \":8080\")\n    if err := http.ListenAndServe(\":8080\", h); err != nil {\n        log.Panicf(\"error while serving: %s\", err)\n    }\n}\n```\n\nFor more examples check the [examples]. [default][default-example] and [custom][custom-example] are the examples for Go net/http std library users.\n\n## Prometheus query examples\n\nGet the request rate by handler:\n\n```text\nsum(\n    rate(http_request_duration_seconds_count[30s])\n) by (handler)\n```\n\nGet the request error rate:\n\n```text\nrate(http_request_duration_seconds_count{code=~\"5..\"}[30s])\n```\n\nGet percentile 99 of the whole service:\n\n```text\nhistogram_quantile(0.99,\n    rate(http_request_duration_seconds_bucket[5m]))\n```\n\nGet percentile 90 of each handler:\n\n```text\nhistogram_quantile(0.9,\n    sum(\n        rate(http_request_duration_seconds_bucket[10m])\n    ) by (handler, le)\n)\n```\n\n## Options\n\n### Middleware Options\n\nThe factory options are the ones that are passed in the moment of creating the middleware factory using the `middleware.Config` object.\n\n#### Recorder\n\nThis is the implementation of the metrics backend, by default it's a dummy recorder.\n\n#### Service\n\nThis is an optional argument that can be used to set a specific service on all the middleware metrics, this is helpful when the service uses multiple middlewares on the same app, for example for the HTTP api server and the metrics server. This also gives the ability to use the same recorder with different middlewares.\n\n#### GroupedStatus\n\nStoring all the status codes could increase the cardinality of the metrics, usually this is not a common case because the used status codes by a service are not too much and are finite, but some services use a lot of different status codes, grouping the status on the `\\dxx` form could impact the performance (in a good way) of the queries on Prometheus (as they are already aggregated), on the other hand it losses detail. For example the metrics code `code=\"401\"`, `code=\"404\"`, `code=\"403\"` with this enabled option would end being `code=\"4xx\"` label. By default is disabled.\n\n#### DisableMeasureSize\n\nThis setting will disable measuring the size of the responses. By default measuring the size is enabled.\n\n#### DisableMeasureInflight\n\nThis settings will disable measuring the number of requests being handled concurrently by the handlers.\n\n#### IgnoredPaths\n\nThis setting is a list of paths that will not be measured for the request duration and the response size. They will still be counted in the RequestsInflight metric.\n\n#### Custom handler ID\n\nOne of the options that you need to pass when wrapping the handler with the middleware is `handlerID`, this has 2 working ways.\n\n- If an empty string is passed `mdwr.Handler(\"\", h)` it will get the `handler` label from the url path. This will create very high cardnialty on the metrics because `/p/123/dashboard/1`, `/p/123/dashboard/2` and `/p/9821/dashboard/1` would have different `handler` labels. **This method is only recomended when the URLs are fixed (not dynamic or don't have parameters on the path)**.\n\n- If a predefined handler ID is passed, `mdwr.Handler(\"/p/:userID/dashboard/:page\", h)` this will keep cardinality low because `/p/123/dashboard/1`, `/p/123/dashboard/2` and `/p/9821/dashboard/1` would have the same `handler` label on the metrics.\n\nThere are different parameters to set up your middleware factory, you can check everything on the [docs] and see the usage in the [examples].\n\n### Prometheus recorder options\n\n#### Prefix\n\nThis option will make exposed metrics have a `{PREFIX}_` in fornt of the metric. For example if a regular exposed metric is `http_request_duration_seconds_count` and I use `Prefix: batman` my exposed metric will be `batman_http_request_duration_seconds_count`. By default this will be disabled or empty, but can be useful if all the metrics of the app are prefixed with the app name.\n\n#### DurationBuckets\n\nDurationBuckets are the buckets used for the request duration histogram metric, by default it will use Prometheus defaults, this is from 5ms to 10s, on a regular HTTP service this is very common and in most cases this default works perfect, but on some cases where the latency is very low or very high due the nature of the service, this could be changed to measure a different range of time. Example, from 500ms to 320s `Buckets: []float64{.5, 1, 2.5, 5, 10, 20, 40, 80, 160, 320}`. Is not adviced to use more than 10 buckets.\n\n#### SizeBuckets\n\nThis works the same as the `DurationBuckets` but for the metric that measures the size of the responses. It's measured in bytes and by default goes from 1B to 1GB.\n\n#### Registry\n\nThe Prometheus registry to use, by default it will use Prometheus global registry (the default one on Prometheus library).\n\n#### Label names\n\nThe label names of the Prometheus metrics can be configured using `HandlerIDLabel`, `StatusCodeLabel`, `MethodLabel`...\n\n### OpenCensus recorder options\n\n#### DurationBuckets\n\nSame option as the Prometheus recorder.\n\n#### SizeBuckets\n\nSame option as the Prometheus recorder.\n\n#### Label names\n\nSame options as the Prometheus recorder.\n\n#### UnregisterViewsBeforeRegister\n\nThis Option is used to unregister the Recorder views before are being registered, this is option is mainly due to the nature of OpenCensus implementation and the huge usage fo global state making impossible to run multiple tests. On regular usage of the library this setting is very rare that needs to be used.\n\n[github-actions-image]: https://github.com/slok/go-http-metrics/workflows/CI/badge.svg\n[github-actions-url]: https://github.com/slok/go-http-metrics/actions\n[goreport-image]: https://goreportcard.com/badge/github.com/slok/go-http-metrics\n[goreport-url]: https://goreportcard.com/report/github.com/slok/go-http-metrics\n[godoc-image]: https://pkg.go.dev/badge/github.com/slok/go-http-metrics\n[godoc-url]: https://pkg.go.dev/github.com/slok/go-http-metrics\n[docs]: https://godoc.org/github.com/slok/go-http-metrics\n[examples]: examples/\n[red]: https://www.weave.works/blog/the-red-method-key-metrics-for-microservices-architecture/\n[four golden signals]: https://landing.google.com/sre/book/chapters/monitoring-distributed-systems.html#xref_monitoring_golden-signals\n[default-example]: examples/default\n[custom-example]: examples/custom\n[negroni-example]: examples/negroni\n[httprouter-example]: examples/httprouter\n[iris-example]: examples/iris\n[gorestful-example]: examples/gorestful\n[gin-example]: examples/gin\n[echo-example]: examples/echo\n[goji-example]: examples/goji\n[chi-example]: examples/chi\n[alice-example]: examples/alice\n[gorilla-example]: examples/gorilla\n[prometheus-recorder]: metrics/prometheus\n[opencensus-recorder]: metrics/opencensus\n[handler-provider-docs]: https://pkg.go.dev/github.com/slok/go-http-metrics/middleware/std#HandlerProvider\n[fasthttp-example]: examples/fasthttp\n[import-information-1]: https://github.com/slok/go-http-metrics/issues/46\n[import-information-2]: https://github.com/slok/go-http-metrics-imports\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fslok%2Fgo-http-metrics","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fslok%2Fgo-http-metrics","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fslok%2Fgo-http-metrics/lists"}