123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181 |
- package metrics
- import (
- "fmt"
- "sync"
- "github.com/prometheus/client_golang/prometheus"
- )
- type Labels map[string]string
- // NewNamespace returns a namespaces that is responsible for managing a collection of
- // metrics for a particual namespace and subsystem
- //
- // labels allows const labels to be added to all metrics created in this namespace
- // and are commonly used for data like application version and git commit
- func NewNamespace(name, subsystem string, labels Labels) *Namespace {
- if labels == nil {
- labels = make(map[string]string)
- }
- return &Namespace{
- name: name,
- subsystem: subsystem,
- labels: labels,
- }
- }
- // Namespace describes a set of metrics that share a namespace and subsystem.
- type Namespace struct {
- name string
- subsystem string
- labels Labels
- mu sync.Mutex
- metrics []prometheus.Collector
- }
- // WithConstLabels returns a namespace with the provided set of labels merged
- // with the existing constant labels on the namespace.
- //
- // Only metrics created with the returned namespace will get the new constant
- // labels. The returned namespace must be registered separately.
- func (n *Namespace) WithConstLabels(labels Labels) *Namespace {
- n.mu.Lock()
- ns := &Namespace{
- name: n.name,
- subsystem: n.subsystem,
- labels: mergeLabels(n.labels, labels),
- }
- n.mu.Unlock()
- return ns
- }
- func (n *Namespace) NewCounter(name, help string) Counter {
- c := &counter{pc: prometheus.NewCounter(n.newCounterOpts(name, help))}
- n.Add(c)
- return c
- }
- func (n *Namespace) NewLabeledCounter(name, help string, labels ...string) LabeledCounter {
- c := &labeledCounter{pc: prometheus.NewCounterVec(n.newCounterOpts(name, help), labels)}
- n.Add(c)
- return c
- }
- func (n *Namespace) newCounterOpts(name, help string) prometheus.CounterOpts {
- return prometheus.CounterOpts{
- Namespace: n.name,
- Subsystem: n.subsystem,
- Name: makeName(name, Total),
- Help: help,
- ConstLabels: prometheus.Labels(n.labels),
- }
- }
- func (n *Namespace) NewTimer(name, help string) Timer {
- t := &timer{
- m: prometheus.NewHistogram(n.newTimerOpts(name, help)),
- }
- n.Add(t)
- return t
- }
- func (n *Namespace) NewLabeledTimer(name, help string, labels ...string) LabeledTimer {
- t := &labeledTimer{
- m: prometheus.NewHistogramVec(n.newTimerOpts(name, help), labels),
- }
- n.Add(t)
- return t
- }
- func (n *Namespace) newTimerOpts(name, help string) prometheus.HistogramOpts {
- return prometheus.HistogramOpts{
- Namespace: n.name,
- Subsystem: n.subsystem,
- Name: makeName(name, Seconds),
- Help: help,
- ConstLabels: prometheus.Labels(n.labels),
- }
- }
- func (n *Namespace) NewGauge(name, help string, unit Unit) Gauge {
- g := &gauge{
- pg: prometheus.NewGauge(n.newGaugeOpts(name, help, unit)),
- }
- n.Add(g)
- return g
- }
- func (n *Namespace) NewLabeledGauge(name, help string, unit Unit, labels ...string) LabeledGauge {
- g := &labeledGauge{
- pg: prometheus.NewGaugeVec(n.newGaugeOpts(name, help, unit), labels),
- }
- n.Add(g)
- return g
- }
- func (n *Namespace) newGaugeOpts(name, help string, unit Unit) prometheus.GaugeOpts {
- return prometheus.GaugeOpts{
- Namespace: n.name,
- Subsystem: n.subsystem,
- Name: makeName(name, unit),
- Help: help,
- ConstLabels: prometheus.Labels(n.labels),
- }
- }
- func (n *Namespace) Describe(ch chan<- *prometheus.Desc) {
- n.mu.Lock()
- defer n.mu.Unlock()
- for _, metric := range n.metrics {
- metric.Describe(ch)
- }
- }
- func (n *Namespace) Collect(ch chan<- prometheus.Metric) {
- n.mu.Lock()
- defer n.mu.Unlock()
- for _, metric := range n.metrics {
- metric.Collect(ch)
- }
- }
- func (n *Namespace) Add(collector prometheus.Collector) {
- n.mu.Lock()
- n.metrics = append(n.metrics, collector)
- n.mu.Unlock()
- }
- func (n *Namespace) NewDesc(name, help string, unit Unit, labels ...string) *prometheus.Desc {
- name = makeName(name, unit)
- namespace := n.name
- if n.subsystem != "" {
- namespace = fmt.Sprintf("%s_%s", namespace, n.subsystem)
- }
- name = fmt.Sprintf("%s_%s", namespace, name)
- return prometheus.NewDesc(name, help, labels, prometheus.Labels(n.labels))
- }
- // mergeLabels merges two or more labels objects into a single map, favoring
- // the later labels.
- func mergeLabels(lbs ...Labels) Labels {
- merged := make(Labels)
- for _, target := range lbs {
- for k, v := range target {
- merged[k] = v
- }
- }
- return merged
- }
- func makeName(name string, unit Unit) string {
- if unit == "" {
- return name
- }
- return fmt.Sprintf("%s_%s", name, unit)
- }
|