{"id":13397062,"url":"https://github.com/cabify/gotoprom","last_synced_at":"2026-01-17T08:48:07.510Z","repository":{"id":57490356,"uuid":"152452211","full_name":"cabify/gotoprom","owner":"cabify","description":"Type-safe Prometheus metrics builder library for golang [managed by soy-programador]","archived":false,"fork":false,"pushed_at":"2024-10-09T08:10:16.000Z","size":66,"stargazers_count":108,"open_issues_count":1,"forks_count":3,"subscribers_count":91,"default_branch":"master","last_synced_at":"2025-08-13T23:51:41.063Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cabify.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":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-10-10T16:07:33.000Z","updated_at":"2025-03-15T11:10:53.000Z","dependencies_parsed_at":"2025-03-13T23:42:13.648Z","dependency_job_id":null,"html_url":"https://github.com/cabify/gotoprom","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/cabify/gotoprom","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cabify%2Fgotoprom","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cabify%2Fgotoprom/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cabify%2Fgotoprom/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cabify%2Fgotoprom/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cabify","download_url":"https://codeload.github.com/cabify/gotoprom/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cabify%2Fgotoprom/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28504499,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-17T06:57:29.758Z","status":"ssl_error","status_checked_at":"2026-01-17T06:56:03.931Z","response_time":85,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":[],"created_at":"2024-07-30T18:01:10.376Z","updated_at":"2026-01-17T08:48:07.496Z","avatar_url":"https://github.com/cabify.png","language":"Go","readme":"# gotoprom\n## A Prometheus metrics builder\n\n[![Build Status](https://travis-ci.org/cabify/gotoprom.svg?branch=master)](https://travis-ci.org/cabify/gotoprom)\n[![Coverage Status](https://coveralls.io/repos/github/cabify/gotoprom/badge.svg)](https://coveralls.io/github/cabify/gotoprom)\n[![GoDoc](https://godoc.org/github.com/cabify/gotoprom?status.svg)](https://godoc.org/github.com/cabify/gotoprom)\n[![Mentioned in Awesome Go](https://awesome.re/mentioned-badge.svg)](https://github.com/avelino/awesome-go)  \n\n`gotoprom` offers an easy to use declarative API with type-safe labels for building and using Prometheus metrics.\nIt doesn't replace the [official Prometheus client](https://github.com/prometheus/client_golang)\nbut adds a wrapper on top of it.\n\n`gotoprom` is built for developers who like type safety, navigating the code using IDEs and using a “find usages”\nfunctionality, making refactoring and debugging easier at the cost of performance and writing slightly more verbose code.\n\n\n## Motivation\n\nMain motivation for this library was to have type-safety on the Prometheus labels, which are\njust a `map[string]string` in the original library, and their values can be reported even\nwithout mentioning the label name, just relying on the order they were declared in.\n\nFor example, it replaces:\n```go\nhttpReqs := prometheus.NewCounterVec(\n    prometheus.CounterOpts{\n        Name: \"http_requests_total\",\n        Help: \"How many HTTP requests processed, partitioned by status code and HTTP method.\",\n    },\n    []string{\"code\", \"method\"},\n)\nprometheus.MustRegister(httpReqs)\n\n// ...\n\nhttpReqs.WithLabelValues(\"404\", \"POST\").Add(42)\n```\n\nWith:\n```go\nvar metrics = struct{\n\tReqs func(labels) prometheus.Counter `name:\"requests_total\" help:\"How many HTTP requests processed, partitioned by status code and HTTP method.\"`\n}\n\ntype labels struct {\n\tCode   int    `label:\"code\"`\n\tMethod string `label:\"method\"`\n}\n\ngotoprom.MustInit(\u0026metrics, \"http\")\n\n// ...\n\nmetrics.Reqs(labels{Code: 404, Method: \"POST\"}).Inc()\n```\n\nThis way it's impossible to mess the call by exchanging the order of `\"POST\"` \u0026 `\"404\"` params.\n\n\n## Usage\n\nDefine your metrics:\n\n```go\nvar metrics struct {\n\tSomeCounter                      func() prometheus.Counter   `name:\"some_counter\" help:\"some counter\"`\n\tSomeHistogram                    func() prometheus.Histogram `name:\"some_histogram\" help:\"Some histogram with default prometheus buckets\" buckets:\"\"`\n\tSomeHistogramWithSpecificBuckets func() prometheus.Histogram `name:\"some_histogram_with_buckets\" help:\"Some histogram with custom buckets\" buckets:\".01,.05,.1\"`\n\tSomeGauge                        func() prometheus.Gauge     `name:\"some_gauge\" help:\"Some gauge\"`\n\tSomeSummaryWithSpecificMaxAge    func() prometheus.Summary   `name:\"some_summary_with_specific_max_age\" help:\"Some summary with custom max age\" max_age:\"20m\" objectives:\"0.50,0.95,0.99\"`\n\n\tRequests struct {\n\t\tTotal func(requestLabels) prometheus.Count `name:\"total\" help:\"Total amount of requests served\"`\n\t} `namespace:\"requests\"`\n}\n\ntype requestLabels struct {\n\tService    string `label:\"service\"`\n\tStatusCode int    `label:\"status\"`\n\tSuccess    bool   `label:\"success\"`\n}\n```\n\nInitialize them:\n\n```go\nfunc init() {\n\tgotoprom.MustInit(\u0026metrics, \"namespace\")\n}\n```\n\nMeasure stuff:\n\n```go\nmetrics.SomeGauge().Set(100)\nmetrics.Requests.Total(requestLabels{Service: \"google\", StatusCode: 404, Success: false}).Inc()\n```\n\n\n## Custom metric types\n\nBy default, only some basic metric types are registered when `gotoprom` is intialized:\n* `prometheus.Counter`\n* `prometheus.Histogram`\n* `prometheus.Gauge`\n* `prometheus.Summary`\n\nYou can extend this by adding more types, for instance, if you want to observe time and want\nto avoid repetitive code you can create a `prometheusx.TimeHistogram`:\n```go\npackage prometheusx\n\nimport (\n\t\"reflect\"\n\t\"time\"\n\n\t\"github.com/cabify/gotoprom\"\n\t\"github.com/cabify/gotoprom/prometheusvanilla\"\n\t\"github.com/prometheus/client_golang/prometheus\"\n)\n\nvar (\n\t// TimeHistogramType is the reflect.Type of the TimeHistogram interface\n\tTimeHistogramType = reflect.TypeOf((*TimeHistogram)(nil)).Elem()\n)\n\nfunc init() {\n\tgotoprom.MustAddBuilder(TimeHistogramType, RegisterTimeHistogram)\n}\n\n// RegisterTimeHistogram registers a TimeHistogram after registering the underlying prometheus.Histogram in the prometheus.Registerer provided\n// The function it returns returns a TimeHistogram type as an interface{}\nfunc RegisterTimeHistogram(name, help, namespace string, labelNames []string, tag reflect.StructTag) (func(prometheus.Labels) interface{}, prometheus.Collector, error) {\n\tf, collector, err := prometheusvanilla.BuildHistogram(name, help, namespace, labelNames, tag)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\n\treturn func(labels prometheus.Labels) interface{} {\n\t\treturn timeHistogramAdapter{Histogram: f(labels).(prometheus.Histogram)}\n\t}, collector, nil\n}\n\n// TimeHistogram offers the basic prometheus.Histogram functionality\n// with additional time-observing functions\ntype TimeHistogram interface {\n\tprometheus.Histogram\n\t// Duration observes the duration in seconds\n\tDuration(duration time.Duration)\n\t// Since observes the duration in seconds since the time point provided\n\tSince(time.Time)\n}\n\ntype timeHistogramAdapter struct {\n\tprometheus.Histogram\n}\n\n// Duration observes the duration in seconds\nfunc (to timeHistogramAdapter) Duration(duration time.Duration) {\n\tto.Observe(duration.Seconds())\n}\n\n// Since observes the duration in seconds since the time point provided\nfunc (to timeHistogramAdapter) Since(duration time.Time) {\n\tto.Duration(time.Since(duration))\n}\n```\n\nSo you can later define it as:\n\n```go\nvar metrics struct {\n\tDurationSeconds func() prometheusx.TimeHistogram `name:\"duration_seconds\" help:\"Duration in seconds\" buckets:\".001,.005,.01,.025,.05,.1\"`\n}\n\nfunc init() {\n\tgotoprom.MustInit(\u0026metrics, \"requests\")\n}\n```\n\nAnd use it as:\n\n```go\n// ...\ndefer metrics.DurationSeconds().Since(t0)\n// ...\n```\n\n\n### Replacing metric builders\nIf you don't like the default metric builders, you can replace the `DefaultInitializer` with your own one.\n\n\n## Performance\n\nObviously, there's a performance cost to perform the type-safety mapping magic to the original\nPrometheus client's API.\n\nIn general terms, it takes 3x to increment a counter than with vanilla Prometheus, which is\naround 600ns (we're talking about a portion of a microsecond, less than a thousandth of a millisecond)\n\n```\n$ go test -bench . -benchtime 3s\ngoos: darwin\ngoarch: amd64\npkg: github.com/cabify/gotoprom\nBenchmarkVanilla-4    \t10000000\t       387 ns/op\nBenchmarkGotoprom-4   \t 5000000\t      1049 ns/op\nPASS\nok  \tgithub.com/cabify/gotoprom\t10.611s\n```\n\nIn terms of memory, there's a also a 33% increase in terms of space, and 3x increase in allocations:\n\n```\n$ go test -bench . -benchmem\ngoos: darwin\ngoarch: amd64\npkg: github.com/cabify/gotoprom\nBenchmarkVanilla-4    \t 5000000\t       381 ns/op\t     336 B/op\t       2 allocs/op\nBenchmarkGotoprom-4   \t 1000000\t      1030 ns/op\t     432 B/op\t       6 allocs/op\nPASS\nok  \tgithub.com/cabify/gotoprom\t3.369s\n```\n\nThis costs are probably assumable in most of the applications, especially when measuring\nnetwork accesses, etc. which are magnitudes higher.\n","funding_links":[],"categories":["Go","Microsoft Office","Miscellaneous","杂项","其他杂项","Uncategorized"],"sub_categories":["Uncategorized","Strings","未分类的","暂未分类","暂未分类这些库被放在这里是因为其他类别似乎都不适合。"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcabify%2Fgotoprom","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcabify%2Fgotoprom","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcabify%2Fgotoprom/lists"}