package prometheus

import "github.com/prometheus/client_golang/prometheus"

Package prometheus provides metrics primitives to instrument code for
monitoring. It also offers a registry for metrics. Sub-packages allow to
expose the registered metrics via HTTP (package promhttp) or push them to a
Pushgateway (package push).

All exported functions and methods are safe to be used concurrently unless
specified otherwise.

The number of exported identifiers in this package might appear a bit
overwhelming. However, in addition to the basic plumbing shown in the example
above, you only need to understand the different metric types and their
vector versions for basic usage.

Above, you have already touched the Counter and the Gauge. There are two more
advanced metric types: the Summary and Histogram. A more thorough description
of those four metric types can be found in the Prometheus docs:
https://prometheus.io/docs/concepts/metric_types/

A fifth "type" of metric is Untyped. It behaves like a Gauge, but signals the
Prometheus server not to assume anything about its type.

In addition to the fundamental metric types Gauge, Counter, Summary,
Histogram, and Untyped, a very important part of the Prometheus data model is
the partitioning of samples along dimensions called labels, which results in
metric vectors. The fundamental types are GaugeVec, CounterVec, SummaryVec,
HistogramVec, and UntypedVec.

While only the fundamental metric types implement the Metric interface, both
the metrics and their vector versions implement the Collector interface. A
Collector manages the collection of a number of Metrics, but for convenience,
a Metric can also “collect itself”. Note that Gauge, Counter, Summary,
Histogram, and Untyped are interfaces themselves while GaugeVec, CounterVec,
SummaryVec, HistogramVec, and UntypedVec are not.

To create instances of Metrics and their vector versions, you need a suitable
…Opts struct, i.e. GaugeOpts, CounterOpts, SummaryOpts, HistogramOpts, or
UntypedOpts.

While you could create your own implementations of Metric, most likely you
will only ever implement the Collector interface on your own. At a first
glance, a custom Collector seems handy to bundle Metrics for common
registration (with the prime example of the different metric vectors above,
which bundle all the metrics of the same name but with different labels).

There is a more involved use case, too: If you already have metrics
available, created outside of the Prometheus context, you don't need the
interface of the various Metric types. You essentially want to mirror the
existing numbers into Prometheus Metrics during collection. An own
implementation of the Collector interface is perfect for that. You can create
Metric instances “on the fly” using NewConstMetric, NewConstHistogram, and
NewConstSummary (and their respective Must… versions). That will happen in
the Collect method. The Describe method has to return separate Desc
instances, representative of the “throw-away” metrics to be created later.
NewDesc comes in handy to create those Desc instances.

The Collector example illustrates the use case. You can also look at the
source code of the processCollector (mirroring process metrics), the
goCollector (mirroring Go metrics), or the expvarCollector (mirroring expvar
metrics) as examples that are used in this package itself.

If you just need to call a function to get a single float value to collect as
a metric, GaugeFunc, CounterFunc, or UntypedFunc might be interesting
shortcuts.

While MustRegister is the by far most common way of registering a Collector,
sometimes you might want to handle the errors the registration might cause.
As suggested by the name, MustRegister panics if an error occurs. With the
Register function, the error is returned and can be handled.

An error is returned if the registered Collector is incompatible or
inconsistent with already registered metrics. The registry aims for
consistency of the collected metrics according to the Prometheus data model.
Inconsistencies are ideally detected at registration time, not at collect
time. The former will usually be detected at start-up time of a program,
while the latter will only happen at scrape time, possibly not even on the
first scrape if the inconsistency only becomes relevant later. That is the
main reason why a Collector and a Metric have to describe themselves to the
registry.

So far, everything we did operated on the so-called default registry, as it
can be found in the global DefaultRegisterer variable. With NewRegistry, you
can create a custom registry, or you can even implement the Registerer or
Gatherer interfaces yourself. The methods Register and Unregister work in the
same way on a custom registry as the global functions Register and Unregister
on the default registry.

There are a number of uses for custom registries: You can use registries with
special properties, see NewPedanticRegistry. You can avoid global state, as
it is imposed by the DefaultRegisterer. You can use multiple registries at
the same time to expose different metrics in different ways. You can use
separate registries for testing purposes.

Also note that the DefaultRegisterer comes registered with a Collector for Go
runtime metrics (via NewGoCollector) and a Collector for process metrics (via
NewProcessCollector). With a custom registry, you are in control and decide
yourself about the Collectors to register.

The Registry implements the Gatherer interface. The caller of the Gather
method can then expose the gathered metrics in some way. Usually, the metrics
are served via HTTP on the /metrics endpoint. That's happening in the example
above. The tools to expose metrics via HTTP are in the promhttp sub-package.
(The top-level functions in the prometheus package are deprecated.)

const (
// DefMaxAge is the default duration for which observations stay
// relevant.DefMaxAgetime.Duration = 10 * time.Minute// DefAgeBuckets is the default number of buckets used to calculate the
// age of observations.DefAgeBuckets = 5
// DefBufCap is the standard buffer size for collecting Summary observations.DefBufCap = 500
)

DefaultRegisterer and DefaultGatherer are the implementations of the
Registerer and Gatherer interface a number of convenience functions in this
package act on. Initially, both variables point to the same Registry, which
has a process collector (see NewProcessCollector) and a Go collector (see
NewGoCollector) already registered. This approach to keep default instances
as global state mirrors the approach of other packages in the Go standard
library. Note that there are caveats. Change the variables with caution and
only if you understand the consequences. Users who want to avoid global state
altogether should not use the convenience function and act on custom
instances instead.

DefBuckets are the default Histogram buckets. The default buckets are
tailored to broadly measure the response time (in seconds) of a network
service. Most likely, however, you will be required to define buckets
customized to your use case.

BuildFQName joins the given three name components by "_". Empty name
components are ignored. If the name parameter itself is empty, an empty
string is returned, no matter what. Metric implementations included in this
library use this function internally to generate the fully-qualified metric
name from the name component in their Opts. Users of the library will only
need this function if they implement their own Metric or instantiate a Desc
(with NewDesc) directly.

ExponentialBuckets creates 'count' buckets, where the lowest bucket has an
upper bound of 'start' and each following bucket's upper bound is 'factor'
times the previous bucket's upper bound. The final +Inf bucket is not counted
and not included in the returned slice. The returned slice is meant to be
used for the Buckets field of HistogramOpts.

The function panics if 'count' is 0 or negative, if 'start' is 0 or negative,
or if 'factor' is less than or equal 1.

Handler returns an HTTP handler for the DefaultGatherer. It is
already instrumented with InstrumentHandler (using "prometheus" as handler
name).

Deprecated: Please note the issues described in the doc comment of
InstrumentHandler. You might want to consider using promhttp.Handler instead
(which is not instrumented, but can be instrumented with the tooling provided
in package promhttp).

InstrumentHandler wraps the given HTTP handler for instrumentation. It
registers four metric collectors (if not already done) and reports HTTP
metrics to the (newly or already) registered collectors: http_requests_total
(CounterVec), http_request_duration_microseconds (Summary),
http_request_size_bytes (Summary), http_response_size_bytes (Summary). Each
has a constant label named "handler" with the provided handlerName as
value. http_requests_total is a metric vector partitioned by HTTP method
(label name "method") and HTTP status code (label name "code").

Deprecated: InstrumentHandler has several issues. Use the tooling provided in
package promhttp instead. The issues are the following:

- It uses Summaries rather than Histograms. Summaries are not useful if
aggregation across multiple instances is required.

- It uses microseconds as unit, which is deprecated and should be replaced by
seconds.

- The size of the request is calculated in a separate goroutine. Since this
calculator requires access to the request header, it creates a race with
any writes to the header performed during request handling.
httputil.ReverseProxy is a prominent example for a handler
performing such writes.

// Handle the "/doc" endpoint with the standard http.FileServer handler.
// By wrapping the handler with InstrumentHandler, request count,
// request and response sizes, and request latency are automatically
// exported to Prometheus, partitioned by HTTP status code and method
// and by the handler name (here "fileserver").
http.Handle("/doc", prometheus.InstrumentHandler(
"fileserver", http.FileServer(http.Dir("/usr/share/doc")),
))
// The Prometheus handler still has to be registered to handle the
// "/metrics" endpoint. The handler returned by prometheus.Handler() is
// already instrumented - with "prometheus" as the handler name. In this
// example, we want the handler name to be "metrics", so we instrument
// the uninstrumented Prometheus handler ourselves.
http.Handle("/metrics", prometheus.InstrumentHandler(
"metrics", prometheus.UninstrumentedHandler(),
))

InstrumentHandlerFuncWithOpts works like InstrumentHandlerFunc (and shares
the same issues) but provides more flexibility (at the cost of a more complex
call syntax). See InstrumentHandlerWithOpts for details how the provided
SummaryOpts are used.

Deprecated: InstrumentHandlerFuncWithOpts is deprecated for the same reasons
as InstrumentHandler is. Use the tooling provided in package promhttp instead.

InstrumentHandlerWithOpts works like InstrumentHandler (and shares the same
issues) but provides more flexibility (at the cost of a more complex call
syntax). As InstrumentHandler, this function registers four metric
collectors, but it uses the provided SummaryOpts to create them. However, the
fields "Name" and "Help" in the SummaryOpts are ignored. "Name" is replaced
by "requests_total", "request_duration_microseconds", "request_size_bytes",
and "response_size_bytes", respectively. "Help" is replaced by an appropriate
help string. The names of the variable labels of the http_requests_total
CounterVec are "method" (get, post, etc.), and "code" (HTTP status code).

If InstrumentHandlerWithOpts is called as follows, it mimics exactly the
behavior of InstrumentHandler:

Technical detail: "requests_total" is a CounterVec, not a SummaryVec, so it
cannot use SummaryOpts. Instead, a CounterOpts struct is created internally,
and all its fields are set to the equally named fields in the provided
SummaryOpts.

Deprecated: InstrumentHandlerWithOpts is deprecated for the same reasons as
InstrumentHandler is. Use the tooling provided in package promhttp instead.

LinearBuckets creates 'count' buckets, each 'width' wide, where the lowest
bucket has an upper bound of 'start'. The final +Inf bucket is not counted
and not included in the returned slice. The returned slice is meant to be
used for the Buckets field of HistogramOpts.

// Imagine you have a worker pool and want to count the tasks completed.
taskCounter := prometheus.NewCounter(prometheus.CounterOpts{
Subsystem: "worker_pool",
Name: "completed_tasks_total",
Help: "Total number of tasks completed.",
})
// This will register fine.
if err := prometheus.Register(taskCounter); err != nil {
fmt.Println(err)
} else {
fmt.Println("taskCounter registered.")
}
// Don't forget to tell the HTTP server about the Prometheus handler.
// (In a real program, you still need to start the HTTP server...)
http.Handle("/metrics", prometheus.Handler())
// Now you can start workers and give every one of them a pointer to
// taskCounter and let it increment it whenever it completes a task.
taskCounter.Inc() // This has to happen somewhere in the worker code.
// But wait, you want to see how individual workers perform. So you need
// a vector of counters, with one element for each worker.
taskCounterVec := prometheus.NewCounterVec(
prometheus.CounterOpts{
Subsystem: "worker_pool",
Name: "completed_tasks_total",
Help: "Total number of tasks completed.",
},
[]string{"worker_id"},
)
// Registering will fail because we already have a metric of that name.
if err := prometheus.Register(taskCounterVec); err != nil {
fmt.Println("taskCounterVec not registered:", err)
} else {
fmt.Println("taskCounterVec registered.")
}
// To fix, first unregister the old taskCounter.
if prometheus.Unregister(taskCounter) {
fmt.Println("taskCounter unregistered.")
}
// Try registering taskCounterVec again.
if err := prometheus.Register(taskCounterVec); err != nil {
fmt.Println("taskCounterVec not registered:", err)
} else {
fmt.Println("taskCounterVec registered.")
}
// Bummer! Still doesn't work.
// Prometheus will not allow you to ever export metrics with
// inconsistent help strings or label names. After unregistering, the
// unregistered metrics will cease to show up in the /metrics HTTP
// response, but the registry still remembers that those metrics had
// been exported before. For this example, we will now choose a
// different name. (In a real program, you would obviously not export
// the obsolete metric in the first place.)
taskCounterVec = prometheus.NewCounterVec(
prometheus.CounterOpts{
Subsystem: "worker_pool",
Name: "completed_tasks_by_id",
Help: "Total number of tasks completed.",
},
[]string{"worker_id"},
)
if err := prometheus.Register(taskCounterVec); err != nil {
fmt.Println("taskCounterVec not registered:", err)
} else {
fmt.Println("taskCounterVec registered.")
}
// Finally it worked!
// The workers have to tell taskCounterVec their id to increment the
// right element in the metric vector.
taskCounterVec.WithLabelValues("42").Inc() // Code from worker 42.
// Each worker could also keep a reference to their own counter element
// around. Pick the counter at initialization time of the worker.
myCounter := taskCounterVec.WithLabelValues("42") // From worker 42 initialization code.
myCounter.Inc() // Somewhere in the code of that worker.
// Note that something like WithLabelValues("42", "spurious arg") would
// panic (because you have provided too many label values). If you want
// to get an error instead, use GetMetricWithLabelValues(...) instead.
notMyCounter, err := taskCounterVec.GetMetricWithLabelValues("42", "spurious arg")
if err != nil {
fmt.Println("Worker initialization failed:", err)
}
if notMyCounter == nil {
fmt.Println("notMyCounter is nil.")
}
// A different (and somewhat tricky) approach is to use
// ConstLabels. ConstLabels are pairs of label names and label values
// that never change. You might ask what those labels are good for (and
// rightfully so - if they never change, they could as well be part of
// the metric name). There are essentially two use-cases: The first is
// if labels are constant throughout the lifetime of a binary execution,
// but they vary over time or between different instances of a running
// binary. The second is what we have here: Each worker creates and
// registers an own Counter instance where the only difference is in the
// value of the ConstLabels. Those Counters can all be registered
// because the different ConstLabel values guarantee that each worker
// will increment a different Counter metric.
counterOpts := prometheus.CounterOpts{
Subsystem: "worker_pool",
Name: "completed_tasks",
Help: "Total number of tasks completed.",
ConstLabels: prometheus.Labels{"worker_id": "42"},
}
taskCounterForWorker42 := prometheus.NewCounter(counterOpts)
if err := prometheus.Register(taskCounterForWorker42); err != nil {
fmt.Println("taskCounterVForWorker42 not registered:", err)
} else {
fmt.Println("taskCounterForWorker42 registered.")
}
// Obviously, in real code, taskCounterForWorker42 would be a member
// variable of a worker struct, and the "42" would be retrieved with a
// GetId() method or something. The Counter would be created and
// registered in the initialization code of the worker.
// For the creation of the next Counter, we can recycle
// counterOpts. Just change the ConstLabels.
counterOpts.ConstLabels = prometheus.Labels{"worker_id": "2001"}
taskCounterForWorker2001 := prometheus.NewCounter(counterOpts)
if err := prometheus.Register(taskCounterForWorker2001); err != nil {
fmt.Println("taskCounterVForWorker2001 not registered:", err)
} else {
fmt.Println("taskCounterForWorker2001 registered.")
}
taskCounterForWorker2001.Inc()
taskCounterForWorker42.Inc()
taskCounterForWorker2001.Inc()
// Yet another approach would be to turn the workers themselves into
// Collectors and register them. See the Collector example for details.

Output:

taskCounter registered.
taskCounterVec not registered: a previously registered descriptor with the same fully-qualified name as Desc{fqName: "worker_pool_completed_tasks_total", help: "Total number of tasks completed.", constLabels: {}, variableLabels: [worker_id]} has different label names or a different help string
taskCounter unregistered.
taskCounterVec not registered: a previously registered descriptor with the same fully-qualified name as Desc{fqName: "worker_pool_completed_tasks_total", help: "Total number of tasks completed.", constLabels: {}, variableLabels: [worker_id]} has different label names or a different help string
taskCounterVec registered.
Worker initialization failed: inconsistent label cardinality
notMyCounter is nil.
taskCounterForWorker42 registered.
taskCounterForWorker2001 registered.

AlreadyRegisteredError is returned by the Register method if the Collector to
be registered has already been registered before, or a different Collector
that collects the same metrics has been registered before. Registration fails
in that case, but you can detect from the kind of error what has
happened. The error contains fields for the existing Collector and the
(rejected) new Collector that equals the existing one. This can be used to
find out if an equal Collector has been registered before and switch over to
using the old one, as demonstrated in the example.

type Collector interface {
// Describe sends the super-set of all possible descriptors of metrics
// collected by this Collector to the provided channel and returns once
// the last descriptor has been sent. The sent descriptors fulfill the
// consistency and uniqueness requirements described in the Desc
// documentation. (It is valid if one and the same Collector sends
// duplicate descriptors. Those duplicates are simply ignored. However,
// two different Collectors must not send duplicate descriptors.) This
// method idempotently sends the same descriptors throughout the
// lifetime of the Collector. If a Collector encounters an error while
// executing this method, it must send an invalid descriptor (created
// with NewInvalidDesc) to signal the error to the registry.Describe(chan<- *Desc)
// Collect is called by the Prometheus registry when collecting
// metrics. The implementation sends each collected metric via the
// provided channel and returns once the last metric has been sent. The
// descriptor of each sent metric is one of those returned by
// Describe. Returned metrics that share the same descriptor must differ
// in their variable label values. This method may be called
// concurrently and must therefore be implemented in a concurrency safe
// way. Blocking occurs at the expense of total performance of rendering
// all registered metrics. Ideally, Collector implementations support
// concurrent readers.Collect(chan<- Metric)
}

Collector is the interface implemented by anything that can be used by
Prometheus to collect metrics. A Collector has to be registered for
collection. See Registerer.Register.

The stock metrics provided by this package (Gauge, Counter, Summary,
Histogram, Untyped) are also Collectors (which only ever collect one metric,
namely itself). An implementer of Collector may, however, collect multiple
metrics in a coordinated fashion and/or create metrics on the fly. Examples
for collectors already implemented in this library are the metric vectors
(i.e. collection of multiple instances of the same Metric but with different
label values) like GaugeVec or SummaryVec, and the ExpvarCollector.

package main
import "github.com/prometheus/client_golang/prometheus"
// ClusterManager is an example for a system that might have been built without
// Prometheus in mind. It models a central manager of jobs running in a
// cluster. To turn it into something that collects Prometheus metrics, we
// simply add the two methods required for the Collector interface.
//
// An additional challenge is that multiple instances of the ClusterManager are
// run within the same binary, each in charge of a different zone. We need to
// make use of ConstLabels to be able to register each ClusterManager instance
// with Prometheus.
type ClusterManager struct {
Zone string
OOMCountDesc *prometheus.Desc
RAMUsageDesc *prometheus.Desc
// ... many more fields
}
// ReallyExpensiveAssessmentOfTheSystemState is a mock for the data gathering a
// real cluster manager would have to do. Since it may actually be really
// expensive, it must only be called once per collection. This implementation,
// obviously, only returns some made-up data.
func (c *ClusterManager) ReallyExpensiveAssessmentOfTheSystemState() (
oomCountByHost map[string]int, ramUsageByHost map[string]float64,
) {
// Just example fake data.
oomCountByHost = map[string]int{
"foo.example.org": 42,
"bar.example.org": 2001,
}
ramUsageByHost = map[string]float64{
"foo.example.org": 6.023e23,
"bar.example.org": 3.14,
}
return
}
// Describe simply sends the two Descs in the struct to the channel.
func (c *ClusterManager) Describe(ch chan<- *prometheus.Desc) {
ch <- c.OOMCountDesc
ch <- c.RAMUsageDesc
}
// Collect first triggers the ReallyExpensiveAssessmentOfTheSystemState. Then it
// creates constant metrics for each host on the fly based on the returned data.
//
// Note that Collect could be called concurrently, so we depend on
// ReallyExpensiveAssessmentOfTheSystemState to be concurrency-safe.
func (c *ClusterManager) Collect(ch chan<- prometheus.Metric) {
oomCountByHost, ramUsageByHost := c.ReallyExpensiveAssessmentOfTheSystemState()
for host, oomCount := range oomCountByHost {
ch <- prometheus.MustNewConstMetric(
c.OOMCountDesc,
prometheus.CounterValue,
float64(oomCount),
host,
)
}
for host, ramUsage := range ramUsageByHost {
ch <- prometheus.MustNewConstMetric(
c.RAMUsageDesc,
prometheus.GaugeValue,
ramUsage,
host,
)
}
}
// NewClusterManager creates the two Descs OOMCountDesc and RAMUsageDesc. Note
// that the zone is set as a ConstLabel. (It's different in each instance of the
// ClusterManager, but constant over the lifetime of an instance.) Then there is
// a variable label "host", since we want to partition the collected metrics by
// host. Since all Descs created in this way are consistent across instances,
// with a guaranteed distinction by the "zone" label, we can register different
// ClusterManager instances with the same registry.
func NewClusterManager(zone string) *ClusterManager {
return &ClusterManager{
Zone: zone,
OOMCountDesc: prometheus.NewDesc(
"clustermanager_oom_crashes_total",
"Number of OOM crashes.",
[]string{"host"},
prometheus.Labels{"zone": zone},
),
RAMUsageDesc: prometheus.NewDesc(
"clustermanager_ram_usage_bytes",
"RAM usage as reported to the cluster manager.",
[]string{"host"},
prometheus.Labels{"zone": zone},
),
}
}
func main() {
workerDB := NewClusterManager("db")
workerCA := NewClusterManager("ca")
// Since we are dealing with custom Collector implementations, it might
// be a good idea to try it out with a pedantic registry.
reg := prometheus.NewPedanticRegistry()
reg.MustRegister(workerDB)
reg.MustRegister(workerCA)
}

NewExpvarCollector returns a newly allocated expvar Collector that still has
to be registered with a Prometheus registry.

An expvar Collector collects metrics from the expvar interface. It provides a
quick way to expose numeric values that are already exported via expvar as
Prometheus metrics. Note that the data models of expvar and Prometheus are
fundamentally different, and that the expvar Collector is inherently slower
than native Prometheus metrics. Thus, the expvar Collector is probably great
for experiments and prototying, but you should seriously consider a more
direct implementation of Prometheus metrics for monitoring production
systems.

The exports map has the following meaning:

The keys in the map correspond to expvar keys, i.e. for every expvar key you
want to export as Prometheus metric, you need an entry in the exports
map. The descriptor mapped to each key describes how to export the expvar
value. It defines the name and the help string of the Prometheus metric
proxying the expvar value. The type will always be Untyped.

For descriptors without variable labels, the expvar value must be a number or
a bool. The number is then directly exported as the Prometheus sample
value. (For a bool, 'false' translates to 0 and 'true' to 1). Expvar values
that are not numbers or bools are silently ignored.

If the descriptor has one variable label, the expvar value must be an expvar
map. The keys in the expvar map become the various values of the one
Prometheus label. The values in the expvar map must be numbers or bools again
as above.

For descriptors with more than one variable label, the expvar must be a
nested expvar map, i.e. where the values of the topmost map are maps again
etc. until a depth is reached that corresponds to the number of labels. The
leaves of that structure must be numbers or bools as above to serve as the
sample values.

NewProcessCollector returns a collector which exports the current state of
process metrics including cpu, memory and file descriptor usage as well as
the process start time for the given process id under the given namespace.

NewProcessCollectorPIDFn returns a collector which exports the current state
of process metrics including cpu, memory and file descriptor usage as well
as the process start time under the given namespace. The given pidFn is
called on each collect and is used to determine the process to export
metrics for.

type Counter interface {
MetricCollector// Inc increments the counter by 1. Use Add to increment it by arbitrary
// non-negative values.Inc()
// Add adds the given value to the counter. It panics if the value is <
// 0.Add(float64)
}

Counter is a Metric that represents a single numerical value that only ever
goes up. That implies that it cannot be used to count items whose number can
also go down, e.g. the number of currently running goroutines. Those
"counters" are represented by Gauges.

NewCounterFunc creates a new CounterFunc based on the provided
CounterOpts. The value reported is determined by calling the given function
from within the Write method. Take into account that metric collection may
happen concurrently. If that results in concurrent calls to Write, like in
the case where a CounterFunc is directly registered with Prometheus, the
provided function must be concurrency-safe. The function should also honor
the contract for a Counter (values only go up, not down), but compliance will
not be checked.

CounterVec is a Collector that bundles a set of Counters that all share the
same Desc, but have different values for their variable labels. This is used
if you want to count the same thing partitioned by various dimensions
(e.g. number of HTTP requests, partitioned by response code and
method). Create instances with NewCounterVec.

httpReqs := prometheus.NewCounterVec(
prometheus.CounterOpts{
Name: "http_requests_total",
Help: "How many HTTP requests processed, partitioned by status code and HTTP method.",
},
[]string{"code", "method"},
)
prometheus.MustRegister(httpReqs)
httpReqs.WithLabelValues("404", "POST").Add(42)
// If you have to access the same set of labels very frequently, it
// might be good to retrieve the metric only once and keep a handle to
// it. But beware of deletion of that metric, see below!
m := httpReqs.WithLabelValues("200", "GET")
for i := 0; i < 1000000; i++ {
m.Inc()
}
// Delete a metric from the vector. If you have previously kept a handle
// to that metric (as above), future updates via that handle will go
// unseen (even if you re-create a metric with the same label set
// later).
httpReqs.DeleteLabelValues("200", "GET")
// Same thing with the more verbose Labels syntax.
httpReqs.Delete(prometheus.Labels{"method": "GET", "code": "200"})

Delete deletes the metric where the variable labels are the same as those
passed in as labels. It returns true if a metric was deleted.

It is not an error if the number and names of the Labels are inconsistent
with those of the VariableLabels in Desc. However, such inconsistent Labels
can never match an actual metric, so the method will always return false in
that case.

This method is used for the same purpose as DeleteLabelValues(...string). See
there for pros and cons of the two methods.

DeleteLabelValues removes the metric where the variable labels are the same
as those passed in as labels (same order as the VariableLabels in Desc). It
returns true if a metric was deleted.

It is not an error if the number of label values is not the same as the
number of VariableLabels in Desc. However, such inconsistent label count can
never match an actual metric, so the method will always return false in that
case.

Note that for more than one label value, this method is prone to mistakes
caused by an incorrect order of arguments. Consider Delete(Labels) as an
alternative to avoid that type of mistake. For higher label numbers, the
latter has a much more readable (albeit more verbose) syntax, but it comes
with a performance overhead (for creating and processing the Labels map).
See also the CounterVec example.

GetMetricWith returns the Counter for the given Labels map (the label names
must match those of the VariableLabels in Desc). If that label map is
accessed for the first time, a new Counter is created. Implications of
creating a Counter without using it and keeping the Counter for later use are
the same as for GetMetricWithLabelValues.

An error is returned if the number and names of the Labels are inconsistent
with those of the VariableLabels in Desc.

This method is used for the same purpose as
GetMetricWithLabelValues(...string). See there for pros and cons of the two
methods.

GetMetricWithLabelValues returns the Counter for the given slice of label
values (same order as the VariableLabels in Desc). If that combination of
label values is accessed for the first time, a new Counter is created.

It is possible to call this method without using the returned Counter to only
create the new Counter but leave it at its starting value 0. See also the
SummaryVec example.

Keeping the Counter for later use is possible (and should be considered if
performance is critical), but keep in mind that Reset, DeleteLabelValues and
Delete can be used to delete the Counter from the CounterVec. In that case,
the Counter will still exist, but it will not be exported anymore, even if a
Counter with the same label values is created later.

An error is returned if the number of label values is not the same as the
number of VariableLabels in Desc.

Note that for more than one label value, this method is prone to mistakes
caused by an incorrect order of arguments. Consider GetMetricWith(Labels) as
an alternative to avoid that type of mistake. For higher label numbers, the
latter has a much more readable (albeit more verbose) syntax, but it comes
with a performance overhead (for creating and processing the Labels map).
See also the GaugeVec example.

Desc is the descriptor used by every Prometheus Metric. It is essentially
the immutable meta-data of a Metric. The normal Metric implementations
included in this package manage their Desc under the hood. Users only have to
deal with Desc if they use advanced features like the ExpvarCollector or
custom Collectors and Metrics.

Descriptors registered with the same registry have to fulfill certain
consistency and uniqueness criteria if they share the same fully-qualified
name: They must have the same help string and the same label names (aka label
dimensions) in each, constLabels and variableLabels, but they must differ in
the values of the constLabels.

Descriptors that share the same fully-qualified names and the same label
values of their constLabels are considered equal.

NewDesc allocates and initializes a new Desc. Errors are recorded in the Desc
and will be reported on registration time. variableLabels and constLabels can
be nil if no such labels should be set. fqName and help must not be empty.

variableLabels only contain the label names. Their label values are variable
and therefore not part of the Desc. (They are managed within the Metric.)

For constLabels, the label values are constant. Therefore, they are fully
specified in the Desc. See the Opts documentation for the implications of
constant labels.

NewInvalidDesc returns an invalid descriptor, i.e. a descriptor with the
provided error set. If a collector returning such a descriptor is registered,
registration will fail with the provided error. NewInvalidDesc can be used by
a Collector to signal inability to describe itself.

type Gatherer interface {
// Gather calls the Collect method of the registered Collectors and then
// gathers the collected metrics into a lexicographically sorted slice
// of MetricFamily protobufs. Even if an error occurs, Gather attempts
// to gather as many metrics as possible. Hence, if a non-nil error is
// returned, the returned MetricFamily slice could be nil (in case of a
// fatal error that prevented any meaningful metric collection) or
// contain a number of MetricFamily protobufs, some of which might be
// incomplete, and some might be missing altogether. The returned error
// (which might be a MultiError) explains the details. In scenarios
// where complete collection is critical, the returned MetricFamily
// protobufs should be disregarded if the returned error is non-nil.Gather() ([]*dto.MetricFamily, error)
}

Gatherer is the interface for the part of a registry in charge of gathering
the collected metrics into a number of MetricFamilies. The Gatherer interface
comes with the same general implication as described for the Registerer
interface.

Gatherers is a slice of Gatherer instances that implements the Gatherer
interface itself. Its Gather method calls Gather on all Gatherers in the
slice in order and returns the merged results. Errors returned from the
Gather calles are all returned in a flattened MultiError. Duplicate and
inconsistent Metrics are skipped (first occurrence in slice order wins) and
reported in the returned error.

Gatherers can be used to merge the Gather results from multiple
Registries. It also provides a way to directly inject existing MetricFamily
protobufs into the gathering by creating a custom Gatherer with a Gather
method that simply returns the existing MetricFamily protobufs. Note that no
registration is involved (in contrast to Collector registration), so
obviously registration-time checks cannot happen. Any inconsistencies between
the gathered MetricFamilies are reported as errors by the Gather method, and
inconsistent Metrics are dropped. Invalid parts of the MetricFamilies
(e.g. syntactically invalid metric or label names) will go undetected.

type Gauge interface {
MetricCollector// Set sets the Gauge to an arbitrary value.Set(float64)
// Inc increments the Gauge by 1. Use Add to increment it by arbitrary
// values.Inc()
// Dec decrements the Gauge by 1. Use Sub to decrement it by arbitrary
// values.Dec()
// Add adds the given value to the Gauge. (The value can be negative,
// resulting in a decrease of the Gauge.)Add(float64)
// Sub subtracts the given value from the Gauge. (The value can be
// negative, resulting in an increase of the Gauge.)Sub(float64)
// SetToCurrentTime sets the Gauge to the current Unix time in seconds.SetToCurrentTime()
}

Gauge is a Metric that represents a single numerical value that can
arbitrarily go up and down.

A Gauge is typically used for measured values like temperatures or current
memory usage, but also "counts" that can go up and down, like the number of
running goroutines.

NewGaugeFunc creates a new GaugeFunc based on the provided GaugeOpts. The
value reported is determined by calling the given function from within the
Write method. Take into account that metric collection may happen
concurrently. If that results in concurrent calls to Write, like in the case
where a GaugeFunc is directly registered with Prometheus, the provided
function must be concurrency-safe.

GaugeVec is a Collector that bundles a set of Gauges that all share the same
Desc, but have different values for their variable labels. This is used if
you want to count the same thing partitioned by various dimensions
(e.g. number of operations queued, partitioned by user and operation
type). Create instances with NewGaugeVec.

Delete deletes the metric where the variable labels are the same as those
passed in as labels. It returns true if a metric was deleted.

It is not an error if the number and names of the Labels are inconsistent
with those of the VariableLabels in Desc. However, such inconsistent Labels
can never match an actual metric, so the method will always return false in
that case.

This method is used for the same purpose as DeleteLabelValues(...string). See
there for pros and cons of the two methods.

DeleteLabelValues removes the metric where the variable labels are the same
as those passed in as labels (same order as the VariableLabels in Desc). It
returns true if a metric was deleted.

It is not an error if the number of label values is not the same as the
number of VariableLabels in Desc. However, such inconsistent label count can
never match an actual metric, so the method will always return false in that
case.

Note that for more than one label value, this method is prone to mistakes
caused by an incorrect order of arguments. Consider Delete(Labels) as an
alternative to avoid that type of mistake. For higher label numbers, the
latter has a much more readable (albeit more verbose) syntax, but it comes
with a performance overhead (for creating and processing the Labels map).
See also the CounterVec example.

GetMetricWith returns the Gauge for the given Labels map (the label names
must match those of the VariableLabels in Desc). If that label map is
accessed for the first time, a new Gauge is created. Implications of
creating a Gauge without using it and keeping the Gauge for later use are
the same as for GetMetricWithLabelValues.

An error is returned if the number and names of the Labels are inconsistent
with those of the VariableLabels in Desc.

This method is used for the same purpose as
GetMetricWithLabelValues(...string). See there for pros and cons of the two
methods.

GetMetricWithLabelValues returns the Gauge for the given slice of label
values (same order as the VariableLabels in Desc). If that combination of
label values is accessed for the first time, a new Gauge is created.

It is possible to call this method without using the returned Gauge to only
create the new Gauge but leave it at its starting value 0. See also the
SummaryVec example.

Keeping the Gauge for later use is possible (and should be considered if
performance is critical), but keep in mind that Reset, DeleteLabelValues and
Delete can be used to delete the Gauge from the GaugeVec. In that case, the
Gauge will still exist, but it will not be exported anymore, even if a
Gauge with the same label values is created later. See also the CounterVec
example.

An error is returned if the number of label values is not the same as the
number of VariableLabels in Desc.

Note that for more than one label value, this method is prone to mistakes
caused by an incorrect order of arguments. Consider GetMetricWith(Labels) as
an alternative to avoid that type of mistake. For higher label numbers, the
latter has a much more readable (albeit more verbose) syntax, but it comes
with a performance overhead (for creating and processing the Labels map).

A Histogram counts individual observations from an event or sample stream in
configurable buckets. Similar to a summary, it also provides a sum of
observations and an observation count.

On the Prometheus server, quantiles can be calculated from a Histogram using
the histogram_quantile function in the query language.

Note that Histograms, in contrast to Summaries, can be aggregated with the
Prometheus query language (see the documentation for detailed
procedures). However, Histograms require the user to pre-define suitable
buckets, and they are in general less accurate. The Observe method of a
Histogram has a very low performance overhead in comparison with the Observe
method of a Summary.

type HistogramOpts struct {
// Namespace, Subsystem, and Name are components of the fully-qualified
// name of the Histogram (created by joining these components with
// "_"). Only Name is mandatory, the others merely help structuring the
// name. Note that the fully-qualified name of the Histogram must be a
// valid Prometheus metric name.NamespacestringSubsystemstringNamestring// Help provides information about this Histogram. Mandatory!
//
// Metrics with the same fully-qualified name must have the same Help
// string.Helpstring// ConstLabels are used to attach fixed labels to this
// Histogram. Histograms with the same fully-qualified name must have the
// same label names in their ConstLabels.
//
// Note that in most cases, labels have a value that varies during the
// lifetime of a process. Those labels are usually managed with a
// HistogramVec. ConstLabels serve only special purposes. One is for the
// special case where the value of a label does not change during the
// lifetime of a process, e.g. if the revision of the running binary is
// put into a label. Another, more advanced purpose is if more than one
// Collector needs to collect Histograms with the same fully-qualified
// name. In that case, those Summaries must differ in the values of
// their ConstLabels. See the Collector examples.
//
// If the value of a label never changes (not even between binaries),
// that label most likely should not be a label at all (but part of the
// metric name).ConstLabelsLabels// Buckets defines the buckets into which observations are counted. Each
// element in the slice is the upper inclusive bound of a bucket. The
// values must be sorted in strictly increasing order. There is no need
// to add a highest bucket with +Inf bound, it will be added
// implicitly. The default value is DefBuckets.Buckets []float64
}

HistogramOpts bundles the options for creating a Histogram metric. It is
mandatory to set Name and Help to a non-empty string. All other fields are
optional and can safely be left at their zero value.

HistogramVec is a Collector that bundles a set of Histograms that all share the
same Desc, but have different values for their variable labels. This is used
if you want to count the same thing partitioned by various dimensions
(e.g. HTTP request latencies, partitioned by status code and method). Create
instances with NewHistogramVec.

Delete deletes the metric where the variable labels are the same as those
passed in as labels. It returns true if a metric was deleted.

It is not an error if the number and names of the Labels are inconsistent
with those of the VariableLabels in Desc. However, such inconsistent Labels
can never match an actual metric, so the method will always return false in
that case.

This method is used for the same purpose as DeleteLabelValues(...string). See
there for pros and cons of the two methods.

DeleteLabelValues removes the metric where the variable labels are the same
as those passed in as labels (same order as the VariableLabels in Desc). It
returns true if a metric was deleted.

It is not an error if the number of label values is not the same as the
number of VariableLabels in Desc. However, such inconsistent label count can
never match an actual metric, so the method will always return false in that
case.

Note that for more than one label value, this method is prone to mistakes
caused by an incorrect order of arguments. Consider Delete(Labels) as an
alternative to avoid that type of mistake. For higher label numbers, the
latter has a much more readable (albeit more verbose) syntax, but it comes
with a performance overhead (for creating and processing the Labels map).
See also the CounterVec example.

GetMetricWith returns the Histogram for the given Labels map (the label names
must match those of the VariableLabels in Desc). If that label map is
accessed for the first time, a new Histogram is created. Implications of
creating a Histogram without using it and keeping the Histogram for later use
are the same as for GetMetricWithLabelValues.

An error is returned if the number and names of the Labels are inconsistent
with those of the VariableLabels in Desc.

This method is used for the same purpose as
GetMetricWithLabelValues(...string). See there for pros and cons of the two
methods.

GetMetricWithLabelValues returns the Histogram for the given slice of label
values (same order as the VariableLabels in Desc). If that combination of
label values is accessed for the first time, a new Histogram is created.

It is possible to call this method without using the returned Histogram to only
create the new Histogram but leave it at its starting value, a Histogram without
any observations.

Keeping the Histogram for later use is possible (and should be considered if
performance is critical), but keep in mind that Reset, DeleteLabelValues and
Delete can be used to delete the Histogram from the HistogramVec. In that case, the
Histogram will still exist, but it will not be exported anymore, even if a
Histogram with the same label values is created later. See also the CounterVec
example.

An error is returned if the number of label values is not the same as the
number of VariableLabels in Desc.

Note that for more than one label value, this method is prone to mistakes
caused by an incorrect order of arguments. Consider GetMetricWith(Labels) as
an alternative to avoid that type of mistake. For higher label numbers, the
latter has a much more readable (albeit more verbose) syntax, but it comes
with a performance overhead (for creating and processing the Labels map).
See also the GaugeVec example.

type Metric interface {
// Desc returns the descriptor for the Metric. This method idempotently
// returns the same descriptor throughout the lifetime of the
// Metric. The returned descriptor is immutable by contract. A Metric
// unable to describe itself must return an invalid descriptor (created
// with NewInvalidDesc).Desc() *Desc// Write encodes the Metric into a "Metric" Protocol Buffer data
// transmission object.
//
// Metric implementations must observe concurrency safety as reads of
// this metric may occur at any time, and any blocking occurs at the
// expense of total performance of rendering all registered
// metrics. Ideally, Metric implementations should support concurrent
// readers.
//
// While populating dto.Metric, it is the responsibility of the
// implementation to ensure validity of the Metric protobuf (like valid
// UTF-8 strings or syntactically valid metric and label names). It is
// recommended to sort labels lexicographically. (Implementers may find
// LabelPairSorter useful for that.) Callers of Write should still make
// sure of sorting if they depend on it.Write(*dto.Metric) error
}

A Metric models a single sample value with its meta data being exported to
Prometheus. Implementations of Metric in this package are Gauge, Counter,
Histogram, Summary, and Untyped.

NewConstHistogram returns a metric representing a Prometheus histogram with
fixed values for the count, sum, and bucket counts. As those parameters
cannot be changed, the returned value does not implement the Histogram
interface (but only the Metric interface). Users of this package will not
have much use for it in regular operations. However, when implementing custom
Collectors, it is useful as a throw-away metric that is generated on the fly
to send it to Prometheus in the Collect method.

buckets is a map of upper bounds to cumulative counts, excluding the +Inf
bucket.

NewConstHistogram returns an error if the length of labelValues is not
consistent with the variable labels in Desc.

NewConstMetric returns a metric with one fixed value that cannot be
changed. Users of this package will not have much use for it in regular
operations. However, when implementing custom Collectors, it is useful as a
throw-away metric that is generated on the fly to send it to Prometheus in
the Collect method. NewConstMetric returns an error if the length of
labelValues is not consistent with the variable labels in Desc.

NewConstSummary returns a metric representing a Prometheus summary with fixed
values for the count, sum, and quantiles. As those parameters cannot be
changed, the returned value does not implement the Summary interface (but
only the Metric interface). Users of this package will not have much use for
it in regular operations. However, when implementing custom Collectors, it is
useful as a throw-away metric that is generated on the fly to send it to
Prometheus in the Collect method.

quantiles maps ranks to quantile values. For example, a median latency of
0.23s and a 99th percentile latency of 0.56s would be expressed as:

map[float64]float64{0.5: 0.23, 0.99: 0.56}

NewConstSummary returns an error if the length of labelValues is not
consistent with the variable labels in Desc.

NewInvalidMetric returns a metric whose Write method always returns the
provided error. It is useful if a Collector finds itself unable to collect
a metric and wishes to report an error to the registry.

MaybeUnwrap returns nil if len(errs) is 0. It returns the first and only
contained error as error if len(errs is 1). In all other cases, it returns
the MultiError directly. This is helpful for returning a MultiError in a way
that only uses the MultiError if needed.

type Opts struct {
// Namespace, Subsystem, and Name are components of the fully-qualified
// name of the Metric (created by joining these components with
// "_"). Only Name is mandatory, the others merely help structuring the
// name. Note that the fully-qualified name of the metric must be a
// valid Prometheus metric name.NamespacestringSubsystemstringNamestring// Help provides information about this metric. Mandatory!
//
// Metrics with the same fully-qualified name must have the same Help
// string.Helpstring// ConstLabels are used to attach fixed labels to this metric. Metrics
// with the same fully-qualified name must have the same label names in
// their ConstLabels.
//
// Note that in most cases, labels have a value that varies during the
// lifetime of a process. Those labels are usually managed with a metric
// vector collector (like CounterVec, GaugeVec, UntypedVec). ConstLabels
// serve only special purposes. One is for the special case where the
// value of a label does not change during the lifetime of a process,
// e.g. if the revision of the running binary is put into a
// label. Another, more advanced purpose is if more than one Collector
// needs to collect Metrics with the same fully-qualified name. In that
// case, those Metrics must differ in the values of their
// ConstLabels. See the Collector examples.
//
// If the value of a label never changes (not even between binaries),
// that label most likely should not be a label at all (but part of the
// metric name).ConstLabelsLabels
}

Opts bundles the options for creating most Metric types. Each metric
implementation XXX has its own XXXOpts type, but in most cases, it is just be
an alias of this type (which might change when the requirement arises.)

It is mandatory to set Name and Help to a non-empty string. All other fields
are optional and can safely be left at their zero value.

type Registerer interface {
// Register registers a new Collector to be included in metrics
// collection. It returns an error if the descriptors provided by the
// Collector are invalid or if they — in combination with descriptors of
// already registered Collectors — do not fulfill the consistency and
// uniqueness criteria described in the documentation of metric.Desc.
//
// If the provided Collector is equal to a Collector already registered
// (which includes the case of re-registering the same Collector), the
// returned error is an instance of AlreadyRegisteredError, which
// contains the previously registered Collector.
//
// It is in general not safe to register the same Collector multiple
// times concurrently.Register(Collector) error// MustRegister works like Register but registers any number of
// Collectors and panics upon the first registration that causes an
// error.MustRegister(...Collector)
// Unregister unregisters the Collector that equals the Collector passed
// in as an argument. (Two Collectors are considered equal if their
// Describe method yields the same set of descriptors.) The function
// returns whether a Collector was unregistered.
//
// Note that even after unregistering, it will not be possible to
// register a new Collector that is inconsistent with the unregistered
// Collector, e.g. a Collector collecting metrics with the same name but
// a different help string. The rationale here is that the same registry
// instance must only collect consistent metrics throughout its
// lifetime.Unregister(Collector) bool
}

Registerer is the interface for the part of a registry in charge of
registering and unregistering. Users of custom registries should use
Registerer as type for registration purposes (rather than the Registry type
directly). In that way, they are free to use custom Registerer implementation
(e.g. for testing purposes).

Registry registers Prometheus collectors, collects their metrics, and gathers
them into MetricFamilies for exposition. It implements both Registerer and
Gatherer. The zero value is not usable. Create instances with NewRegistry or
NewPedanticRegistry.

NewPedanticRegistry returns a registry that checks during collection if each
collected Metric is consistent with its reported Desc, and if the Desc has
actually been registered with the registry.

Usually, a Registry will be happy as long as the union of all collected
Metrics is consistent and valid even if some metrics are not consistent with
their own Desc or a Desc provided by their registered Collector. Well-behaved
Collectors and Metrics will only provide consistent Descs. This Registry is
useful to test the implementation of Collectors and Metrics.

A Summary captures individual observations from an event or sample stream and
summarizes them in a manner similar to traditional summary statistics: 1. sum
of observations, 2. observation count, 3. rank estimations.

A typical use-case is the observation of request latencies. By default, a
Summary provides the median, the 90th and the 99th percentile of the latency
as rank estimations. However, the default behavior will change in the
upcoming v0.10 of the library. There will be no rank estiamtions at all by
default. For a sane transition, it is recommended to set the desired rank
estimations explicitly.

Note that the rank estimations cannot be aggregated in a meaningful way with
the Prometheus query language (i.e. you cannot average or add them). If you
need aggregatable quantiles (e.g. you want the 99th percentile latency of all
queries served across all instances of a service), consider the Histogram
metric type. See the Prometheus documentation for more details.

type SummaryOpts struct {
// Namespace, Subsystem, and Name are components of the fully-qualified
// name of the Summary (created by joining these components with
// "_"). Only Name is mandatory, the others merely help structuring the
// name. Note that the fully-qualified name of the Summary must be a
// valid Prometheus metric name.NamespacestringSubsystemstringNamestring// Help provides information about this Summary. Mandatory!
//
// Metrics with the same fully-qualified name must have the same Help
// string.Helpstring// ConstLabels are used to attach fixed labels to this
// Summary. Summaries with the same fully-qualified name must have the
// same label names in their ConstLabels.
//
// Note that in most cases, labels have a value that varies during the
// lifetime of a process. Those labels are usually managed with a
// SummaryVec. ConstLabels serve only special purposes. One is for the
// special case where the value of a label does not change during the
// lifetime of a process, e.g. if the revision of the running binary is
// put into a label. Another, more advanced purpose is if more than one
// Collector needs to collect Summaries with the same fully-qualified
// name. In that case, those Summaries must differ in the values of
// their ConstLabels. See the Collector examples.
//
// If the value of a label never changes (not even between binaries),
// that label most likely should not be a label at all (but part of the
// metric name).ConstLabelsLabels// Objectives defines the quantile rank estimates with their respective
// absolute error. If Objectives[q] = e, then the value reported for q
// will be the φ-quantile value for some φ between q-e and q+e. The
// default value is DefObjectives. It is used if Objectives is left at
// its zero value (i.e. nil). To create a Summary without Objectives,
// set it to an empty map (i.e. map[float64]float64{}).
//
// Deprecated: Note that the current value of DefObjectives is
// deprecated. It will be replaced by an empty map in v0.10 of the
// library. Please explicitly set Objectives to the desired value.Objectives map[float64]float64// MaxAge defines the duration for which an observation stays relevant
// for the summary. Must be positive. The default value is DefMaxAge.MaxAgetime.Duration// AgeBuckets is the number of buckets used to exclude observations that
// are older than MaxAge from the summary. A higher number has a
// resource penalty, so only increase it if the higher resolution is
// really required. For very high observation rates, you might want to
// reduce the number of age buckets. With only one age bucket, you will
// effectively see a complete reset of the summary each time MaxAge has
// passed. The default value is DefAgeBuckets.AgeBucketsuint32// BufCap defines the default sample stream buffer size. The default
// value of DefBufCap should suffice for most uses. If there is a need
// to increase the value, a multiple of 500 is recommended (because that
// is the internal buffer size of the underlying package
// "github.com/bmizerany/perks/quantile").BufCapuint32
}

SummaryOpts bundles the options for creating a Summary metric. It is
mandatory to set Name and Help to a non-empty string. While all other fields
are optional and can safely be left at their zero value, it is recommended to
explicitly set the Objectives field to the desired value as the default value
will change in the upcoming v0.10 of the library.

SummaryVec is a Collector that bundles a set of Summaries that all share the
same Desc, but have different values for their variable labels. This is used
if you want to count the same thing partitioned by various dimensions
(e.g. HTTP request latencies, partitioned by status code and method). Create
instances with NewSummaryVec.

Delete deletes the metric where the variable labels are the same as those
passed in as labels. It returns true if a metric was deleted.

It is not an error if the number and names of the Labels are inconsistent
with those of the VariableLabels in Desc. However, such inconsistent Labels
can never match an actual metric, so the method will always return false in
that case.

This method is used for the same purpose as DeleteLabelValues(...string). See
there for pros and cons of the two methods.

DeleteLabelValues removes the metric where the variable labels are the same
as those passed in as labels (same order as the VariableLabels in Desc). It
returns true if a metric was deleted.

It is not an error if the number of label values is not the same as the
number of VariableLabels in Desc. However, such inconsistent label count can
never match an actual metric, so the method will always return false in that
case.

Note that for more than one label value, this method is prone to mistakes
caused by an incorrect order of arguments. Consider Delete(Labels) as an
alternative to avoid that type of mistake. For higher label numbers, the
latter has a much more readable (albeit more verbose) syntax, but it comes
with a performance overhead (for creating and processing the Labels map).
See also the CounterVec example.

GetMetricWith returns the Summary for the given Labels map (the label names
must match those of the VariableLabels in Desc). If that label map is
accessed for the first time, a new Summary is created. Implications of
creating a Summary without using it and keeping the Summary for later use are
the same as for GetMetricWithLabelValues.

An error is returned if the number and names of the Labels are inconsistent
with those of the VariableLabels in Desc.

This method is used for the same purpose as
GetMetricWithLabelValues(...string). See there for pros and cons of the two
methods.

GetMetricWithLabelValues returns the Summary for the given slice of label
values (same order as the VariableLabels in Desc). If that combination of
label values is accessed for the first time, a new Summary is created.

It is possible to call this method without using the returned Summary to only
create the new Summary but leave it at its starting value, a Summary without
any observations.

Keeping the Summary for later use is possible (and should be considered if
performance is critical), but keep in mind that Reset, DeleteLabelValues and
Delete can be used to delete the Summary from the SummaryVec. In that case, the
Summary will still exist, but it will not be exported anymore, even if a
Summary with the same label values is created later. See also the CounterVec
example.

An error is returned if the number of label values is not the same as the
number of VariableLabels in Desc.

Note that for more than one label value, this method is prone to mistakes
caused by an incorrect order of arguments. Consider GetMetricWith(Labels) as
an alternative to avoid that type of mistake. For higher label numbers, the
latter has a much more readable (albeit more verbose) syntax, but it comes
with a performance overhead (for creating and processing the Labels map).
See also the GaugeVec example.

package main
import (
"os"
"github.com/prometheus/client_golang/prometheus"
)
var (
// If a function is called rarely (i.e. not more often than scrapes
// happen) or ideally only once (like in a batch job), it can make sense
// to use a Gauge for timing the function call. For timing a batch job
// and pushing the result to a Pushgateway, see also the comprehensive
// example in the push package.
funcDuration = prometheus.NewGauge(prometheus.GaugeOpts{
Name: "example_function_duration_seconds",
Help: "Duration of the last call of an example function.",
})
)
func run() error {
// The Set method of the Gauge is used to observe the duration.
timer := prometheus.NewTimer(prometheus.ObserverFunc(funcDuration.Set))
defer timer.ObserveDuration()
// Do something. Return errors as encountered. The use of 'defer' above
// makes sure the function is still timed properly.
return nil
}
func main() {
if err := run(); err != nil {
os.Exit(1)
}
}

ObserveDuration records the duration passed since the Timer was created with
NewTimer. It calls the Observe method of the Observer provided during
construction with the duration in seconds as an argument. ObserveDuration is
usually called with a defer statement.

Note that this method is only guaranteed to never observe negative durations
if used with Go1.9+.

NewUntypedFunc creates a new UntypedFunc based on the provided
UntypedOpts. The value reported is determined by calling the given function
from within the Write method. Take into account that metric collection may
happen concurrently. If that results in concurrent calls to Write, like in
the case where an UntypedFunc is directly registered with Prometheus, the
provided function must be concurrency-safe.