178 lines
4.3 KiB
Go
178 lines
4.3 KiB
Go
package metric
|
||
|
||
// prometheus metric:unique 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{}),
|
||
)
|
||
}
|