XinYeYouKu/app/utils/metric/reporter.go

178 lines
4.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package metric
// prometheus metricunique identifier: name and optional key-value pairs called labels
// 1. name regexp: [a-zA-Z_:][a-zA-Z0-9_:]*
// 2. label name regexp: [a-zA-Z_][a-zA-Z0-9_]*
// 3. Label names beginning with __ are reserved for internal use.
// 4. Label values may contain any Unicode characters.
// 5. notation: <metric name>{<label name>=<label value>, ...}
// for example: api_http_requests_total{method="POST", handler="/messages"}
// A label with an empty label value is considered equivalent to a label that does not exist.
// each sample consists of :
// - a float64 value
// - a millisecond-precision timestamp
// metric type:
// - Counter
// A cumulative metric that represents a single monotonically increasing counter whose value can only increase or be reset to zero on restart.
// - Gauge
// A gauge is a metric that represents a single numerical value that can arbitrarily go up and down.
// - Histogram
// A histogram samples observations (usually things like request durations or response sizes) and counts them in configurable buckets. It also provides a sum of all observed values.
// - Summary
// Similar to a histogram, a summary samples observations (usually things like request durations and response sizes). While it also provides a total count of observations and a sum of all observed values, it calculates configurable quantiles over a sliding time window.
// metric:
// Counter:
// - req_total_count
// - req_failed_count
// Gauge:
// - heap_inuse_size
// - heap_total_size
// - heap_object_num
// - goroutine_num
// Histogram:
// - req_cost_time
// Summary:
// - req_cost_time
import (
"net/http"
"sync"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
const (
//ENV = "env"
APP = "snow"
VER = "ver"
)
var (
collectors = []prometheus.Collector{}
)
func RegisterCollector(c ...prometheus.Collector) {
collectors = append(collectors, c...)
}
type Options struct {
labels map[string]string
processEnable bool
runtimeEnable bool
}
type Option func(opt *Options)
// 添加App和Ver label
func AppVer(app, ver string) Option {
return func(opt *Options) {
if app != "" {
opt.labels[APP] = app
}
if ver != "" {
opt.labels[VER] = ver
}
}
}
// 添加额外label
func WithLabel(key, val string) Option {
return func(opt *Options) {
if key != "" && val != "" {
opt.labels[key] = val
}
}
}
// 收集进程信息
func EnableProcess() Option {
return func(opt *Options) {
opt.processEnable = true
}
}
func EnableRuntime() Option {
return func(opt *Options) {
opt.runtimeEnable = true
}
}
type Reporter struct {
opts Options
collectors []prometheus.Collector
// registerer
registerer prometheus.Registerer
gatherer prometheus.Gatherer
}
var (
once sync.Once
reporter Reporter
)
func Init(opts ...Option) {
_opts := Options{
labels: map[string]string{},
}
for _, opt := range opts {
opt(&_opts)
}
once.Do(func() {
cs := collectors
if _opts.processEnable {
cs = append(cs, prometheus.NewProcessCollector(prometheus.ProcessCollectorOpts{}))
}
if _opts.runtimeEnable {
cs = append(cs, prometheus.NewGoCollector())
}
reporter = Reporter{
opts: _opts,
collectors: cs,
}
registry := prometheus.NewRegistry()
reporter.registerer = prometheus.WrapRegistererWith(reporter.opts.labels, registry)
reporter.gatherer = registry
reporter.registerer.MustRegister(reporter.collectors...)
})
}
func (p *Reporter) newCounterVec(metric string, labels []string) *prometheus.CounterVec {
counterVec := prometheus.NewCounterVec(prometheus.CounterOpts{
Name: metric,
}, labels)
return counterVec
}
func (p *Reporter) newGaugeVec(metric string, labels []string) *prometheus.GaugeVec {
gaugeVec := prometheus.NewGaugeVec(prometheus.GaugeOpts{
Name: metric,
}, labels)
return gaugeVec
}
func (p *Reporter) newHistogramVec(metric string, labels []string, buckets []float64) *prometheus.HistogramVec {
histogramVec := prometheus.NewHistogramVec(prometheus.HistogramOpts{
Name: metric,
Buckets: buckets,
}, labels)
return histogramVec
}
func Handler() http.Handler {
return promhttp.InstrumentMetricHandler(
reporter.registerer, promhttp.HandlerFor(reporter.gatherer, promhttp.HandlerOpts{}),
)
}