mirror of
https://github.com/nabbar/golib.git
synced 2025-10-17 05:11:30 +08:00
Add package prometheus
This commit is contained in:
99
prometheus/bloom.go
Normal file
99
prometheus/bloom.go
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 Nicolas JUHEL
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package prometheus
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/bits-and-blooms/bitset"
|
||||||
|
)
|
||||||
|
|
||||||
|
const defaultSize = 2 << 24
|
||||||
|
|
||||||
|
var seeds = []uint{7, 11, 13, 31, 37, 61}
|
||||||
|
|
||||||
|
type bloomFilter struct {
|
||||||
|
m sync.Mutex
|
||||||
|
Set *bitset.BitSet
|
||||||
|
Funcs [6]simpleHash
|
||||||
|
}
|
||||||
|
|
||||||
|
type BloomFilter interface {
|
||||||
|
Add(value string)
|
||||||
|
Contains(value string) bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewBloomFilter() BloomFilter {
|
||||||
|
bf := new(bloomFilter)
|
||||||
|
|
||||||
|
for i := 0; i < len(bf.Funcs); i++ {
|
||||||
|
bf.Funcs[i] = simpleHash{defaultSize, seeds[i]}
|
||||||
|
}
|
||||||
|
|
||||||
|
bf.Set = bitset.New(defaultSize)
|
||||||
|
|
||||||
|
return bf
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bf *bloomFilter) Add(value string) {
|
||||||
|
bf.m.Lock()
|
||||||
|
defer bf.m.Unlock()
|
||||||
|
|
||||||
|
for _, f := range bf.Funcs {
|
||||||
|
bf.Set.Set(f.hash(value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bf *bloomFilter) Contains(value string) bool {
|
||||||
|
if value == "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
ret := true
|
||||||
|
|
||||||
|
bf.m.Lock()
|
||||||
|
defer bf.m.Unlock()
|
||||||
|
|
||||||
|
for _, f := range bf.Funcs {
|
||||||
|
ret = ret && bf.Set.Test(f.hash(value))
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
type simpleHash struct {
|
||||||
|
Cap uint
|
||||||
|
Seed uint
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *simpleHash) hash(value string) uint {
|
||||||
|
var result uint = 0
|
||||||
|
for i := 0; i < len(value); i++ {
|
||||||
|
result = result*s.Seed + uint(value[i])
|
||||||
|
}
|
||||||
|
return (s.Cap - 1) & result
|
||||||
|
}
|
67
prometheus/interface.go
Normal file
67
prometheus/interface.go
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 Nicolas JUHEL
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package prometheus
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync/atomic"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
DefaultSlowTime = int32(5)
|
||||||
|
)
|
||||||
|
|
||||||
|
type Prometheus interface {
|
||||||
|
Expose(c *gin.Context)
|
||||||
|
MiddleWare(c *gin.Context)
|
||||||
|
CollectMetrics(c *gin.Context, start time.Time)
|
||||||
|
|
||||||
|
ExcludePath(startWith ...string)
|
||||||
|
|
||||||
|
GetMetric(name string) *metrics
|
||||||
|
SetMetric(metric Metrics) error
|
||||||
|
AddMetric(metric Metrics) error
|
||||||
|
ListMetric() []string
|
||||||
|
|
||||||
|
SetSlowTime(slowTime int32)
|
||||||
|
GetSlowTime() int32
|
||||||
|
|
||||||
|
SetDuration(duration []float64)
|
||||||
|
GetDuration() []float64
|
||||||
|
}
|
||||||
|
|
||||||
|
// New will return a new object that implement interface GinPrometheus.
|
||||||
|
func New() Prometheus {
|
||||||
|
return &monitor{
|
||||||
|
slowTime: DefaultSlowTime,
|
||||||
|
reqDuration: []float64{0.1, 0.3, 1.2, 5, 10},
|
||||||
|
metrics: make(map[string]*atomic.Value),
|
||||||
|
exclude: make([]string, 0),
|
||||||
|
}
|
||||||
|
}
|
239
prometheus/metrics.go
Normal file
239
prometheus/metrics.go
Normal file
@@ -0,0 +1,239 @@
|
|||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 Nicolas JUHEL
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package prometheus
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Metrics interface {
|
||||||
|
SetGaugeValue(labelValues []string, value float64) error
|
||||||
|
Inc(labelValues []string) error
|
||||||
|
Add(labelValues []string, value float64) error
|
||||||
|
Observe(labelValues []string, value float64) error
|
||||||
|
|
||||||
|
Collect(c *gin.Context, start time.Time)
|
||||||
|
|
||||||
|
GetName() string
|
||||||
|
GetType() MetricType
|
||||||
|
SetDesc(desc string)
|
||||||
|
|
||||||
|
AddLabel(label ...string)
|
||||||
|
AddBuckets(bucket ...float64)
|
||||||
|
AddObjective(key, value float64)
|
||||||
|
SetCollect(fct FuncCollect)
|
||||||
|
}
|
||||||
|
|
||||||
|
type FuncCollect func(m Metrics, c *gin.Context, start time.Time)
|
||||||
|
|
||||||
|
func NewMetrics(name string, metricType MetricType) Metrics {
|
||||||
|
return &metrics{
|
||||||
|
t: metricType,
|
||||||
|
n: name,
|
||||||
|
d: "",
|
||||||
|
l: make([]string, 0),
|
||||||
|
b: make([]float64, 0),
|
||||||
|
o: make(map[float64]float64, 0),
|
||||||
|
f: nil,
|
||||||
|
v: nil,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// metrics defines a metric object. Users can use it to save
|
||||||
|
// metric data. Every metric should be globally unique by name.
|
||||||
|
type metrics struct {
|
||||||
|
m sync.Mutex
|
||||||
|
t MetricType
|
||||||
|
n string
|
||||||
|
d string
|
||||||
|
l []string
|
||||||
|
b []float64
|
||||||
|
o map[float64]float64
|
||||||
|
f FuncCollect
|
||||||
|
v prometheus.Collector
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetGaugeValue set data for Gauge type metrics.
|
||||||
|
func (m *metrics) SetGaugeValue(labelValues []string, value float64) error {
|
||||||
|
m.m.Lock()
|
||||||
|
defer m.m.Unlock()
|
||||||
|
|
||||||
|
if m.t == None {
|
||||||
|
return errors.Errorf("metric '%s' not existed.", m.n)
|
||||||
|
}
|
||||||
|
|
||||||
|
if m.t != Gauge {
|
||||||
|
return errors.Errorf("metric '%s' not Gauge type", m.n)
|
||||||
|
}
|
||||||
|
|
||||||
|
m.v.(*prometheus.GaugeVec).WithLabelValues(labelValues...).Set(value)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inc increases value for Counter/Gauge type metric, increments
|
||||||
|
// the counter by 1
|
||||||
|
func (m *metrics) Inc(labelValues []string) error {
|
||||||
|
m.m.Lock()
|
||||||
|
defer m.m.Unlock()
|
||||||
|
|
||||||
|
if m.t == None {
|
||||||
|
return errors.Errorf("metric '%s' not existed.", m.n)
|
||||||
|
}
|
||||||
|
|
||||||
|
if m.t != Gauge && m.t != Counter {
|
||||||
|
return errors.Errorf("metric '%s' not Gauge or Counter type", m.n)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch m.t {
|
||||||
|
case Counter:
|
||||||
|
m.v.(*prometheus.CounterVec).WithLabelValues(labelValues...).Inc()
|
||||||
|
break
|
||||||
|
case Gauge:
|
||||||
|
m.v.(*prometheus.GaugeVec).WithLabelValues(labelValues...).Inc()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add adds the given value to the metrics object. Only
|
||||||
|
// for Counter/Gauge type metric.
|
||||||
|
func (m *metrics) Add(labelValues []string, value float64) error {
|
||||||
|
m.m.Lock()
|
||||||
|
defer m.m.Unlock()
|
||||||
|
|
||||||
|
if m.t == None {
|
||||||
|
return errors.Errorf("metric '%s' not existed.", m.n)
|
||||||
|
}
|
||||||
|
|
||||||
|
if m.t != Gauge && m.t != Counter {
|
||||||
|
return errors.Errorf("metric '%s' not Gauge or Counter type", m.n)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch m.t {
|
||||||
|
case Counter:
|
||||||
|
m.v.(*prometheus.CounterVec).WithLabelValues(labelValues...).Add(value)
|
||||||
|
break
|
||||||
|
case Gauge:
|
||||||
|
m.v.(*prometheus.GaugeVec).WithLabelValues(labelValues...).Add(value)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Observe is used by Histogram and Summary type metric to
|
||||||
|
// add observations.
|
||||||
|
func (m *metrics) Observe(labelValues []string, value float64) error {
|
||||||
|
m.m.Lock()
|
||||||
|
defer m.m.Unlock()
|
||||||
|
|
||||||
|
if m.t == 0 {
|
||||||
|
return errors.Errorf("metric '%s' not existed.", m.n)
|
||||||
|
}
|
||||||
|
|
||||||
|
if m.t != Histogram && m.t != Summary {
|
||||||
|
return errors.Errorf("metric '%s' not Histogram or Summary type", m.n)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch m.t {
|
||||||
|
case Histogram:
|
||||||
|
m.v.(*prometheus.HistogramVec).WithLabelValues(labelValues...).Observe(value)
|
||||||
|
break
|
||||||
|
case Summary:
|
||||||
|
m.v.(*prometheus.SummaryVec).WithLabelValues(labelValues...).Observe(value)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *metrics) Collect(c *gin.Context, start time.Time) {
|
||||||
|
if m.f != nil {
|
||||||
|
m.f(m, c, start)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *metrics) GetName() string {
|
||||||
|
return m.n
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *metrics) GetType() MetricType {
|
||||||
|
return m.t
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *metrics) SetDesc(desc string) {
|
||||||
|
m.m.Lock()
|
||||||
|
defer m.m.Unlock()
|
||||||
|
|
||||||
|
m.d = desc
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *metrics) AddLabel(label ...string) {
|
||||||
|
m.m.Lock()
|
||||||
|
defer m.m.Unlock()
|
||||||
|
|
||||||
|
if len(m.l) < 1 {
|
||||||
|
m.l = make([]string, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
m.l = append(m.l, label...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *metrics) AddBuckets(bucket ...float64) {
|
||||||
|
m.m.Lock()
|
||||||
|
defer m.m.Unlock()
|
||||||
|
|
||||||
|
if len(m.b) < 1 {
|
||||||
|
m.b = make([]float64, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
m.b = append(m.b, bucket...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *metrics) AddObjective(key, value float64) {
|
||||||
|
m.m.Lock()
|
||||||
|
defer m.m.Unlock()
|
||||||
|
|
||||||
|
if len(m.o) < 1 {
|
||||||
|
m.o = make(map[float64]float64, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
m.o[key] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *metrics) SetCollect(fct FuncCollect) {
|
||||||
|
m.m.Lock()
|
||||||
|
defer m.m.Unlock()
|
||||||
|
|
||||||
|
m.f = fct
|
||||||
|
}
|
209
prometheus/monitor.go
Normal file
209
prometheus/monitor.go
Normal file
@@ -0,0 +1,209 @@
|
|||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 Nicolas JUHEL
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package prometheus
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
|
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GinPrometheus is an object that uses to set gin server monitor.
|
||||||
|
type monitor struct {
|
||||||
|
m sync.Mutex
|
||||||
|
|
||||||
|
exclude []string
|
||||||
|
slowTime int32
|
||||||
|
reqDuration []float64
|
||||||
|
|
||||||
|
metrics map[string]*atomic.Value
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expose adds metric path to a given router.
|
||||||
|
// The router can be different with the one passed to UseWithoutExposingEndpoint.
|
||||||
|
// This allows to expose metrics on different port.
|
||||||
|
func (m *monitor) Expose(c *gin.Context) {
|
||||||
|
promhttp.Handler().ServeHTTP(c.Writer, c.Request)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MiddleWare as gin monitor middleware.
|
||||||
|
func (m *monitor) MiddleWare(c *gin.Context) {
|
||||||
|
startTime := time.Now()
|
||||||
|
|
||||||
|
if len(m.exclude) > 0 {
|
||||||
|
r := c.Request.URL.Path
|
||||||
|
if !strings.HasPrefix(r, "/") {
|
||||||
|
r = "/" + r
|
||||||
|
}
|
||||||
|
for _, p := range m.exclude {
|
||||||
|
if p != "" && strings.HasPrefix(r, p) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// execute normal process.
|
||||||
|
c.Next()
|
||||||
|
|
||||||
|
// after request
|
||||||
|
m.CollectMetrics(c, startTime)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *monitor) CollectMetrics(c *gin.Context, start time.Time) {
|
||||||
|
for _, k := range m.ListMetric() {
|
||||||
|
metric := m.GetMetric(k)
|
||||||
|
metric.Collect(c, start)
|
||||||
|
_ = m.SetMetric(metric)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *monitor) ExcludePath(startWith ...string) {
|
||||||
|
m.m.Lock()
|
||||||
|
defer m.m.Unlock()
|
||||||
|
|
||||||
|
for _, p := range startWith {
|
||||||
|
if p != "" {
|
||||||
|
m.exclude = append(m.exclude, p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetSlowTime set slowTime property. slowTime is used to determine whether
|
||||||
|
// the request is slow. For "gin_slow_request_total" metric.
|
||||||
|
func (m *monitor) SetSlowTime(slowTime int32) {
|
||||||
|
m.m.Lock()
|
||||||
|
defer m.m.Unlock()
|
||||||
|
|
||||||
|
m.slowTime = slowTime
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSlowTime retrieve the slowTime property. slowTime is used to determine whether
|
||||||
|
// the request is slow. For "gin_slow_request_total" metric.
|
||||||
|
func (m *monitor) GetSlowTime() int32 {
|
||||||
|
m.m.Lock()
|
||||||
|
defer m.m.Unlock()
|
||||||
|
|
||||||
|
return m.slowTime
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetDuration set duration property. duration is used to ginRequestDuration
|
||||||
|
// metric buckets.
|
||||||
|
func (m *monitor) SetDuration(duration []float64) {
|
||||||
|
m.m.Lock()
|
||||||
|
defer m.m.Unlock()
|
||||||
|
|
||||||
|
m.reqDuration = duration
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetDuration retrieve the duration property. duration is used to ginRequestDuration
|
||||||
|
// metric buckets.
|
||||||
|
func (m *monitor) GetDuration() []float64 {
|
||||||
|
m.m.Lock()
|
||||||
|
defer m.m.Unlock()
|
||||||
|
|
||||||
|
return m.reqDuration
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMetric used to get metric object by metric_name.
|
||||||
|
func (m *monitor) GetMetric(name string) *metrics {
|
||||||
|
m.m.Lock()
|
||||||
|
defer m.m.Unlock()
|
||||||
|
|
||||||
|
if a, ok := m.metrics[name]; !ok || a == nil {
|
||||||
|
return &metrics{}
|
||||||
|
} else if i := a.Load(); i == nil {
|
||||||
|
return &metrics{}
|
||||||
|
} else if o, ok := i.(*metrics); !ok || o == nil {
|
||||||
|
return &metrics{}
|
||||||
|
} else {
|
||||||
|
return o
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetMetric used to store an atomic value of the metric object by metric_name.
|
||||||
|
func (m *monitor) SetMetric(metric Metrics) error {
|
||||||
|
m.m.Lock()
|
||||||
|
defer m.m.Unlock()
|
||||||
|
|
||||||
|
var (
|
||||||
|
ok bool
|
||||||
|
o *metrics
|
||||||
|
)
|
||||||
|
|
||||||
|
if o, ok = metric.(*metrics); !ok {
|
||||||
|
return errors.Errorf("metric is not a valid metric instance")
|
||||||
|
}
|
||||||
|
|
||||||
|
if o.n == "" {
|
||||||
|
return errors.Errorf("metric name cannot be empty.")
|
||||||
|
}
|
||||||
|
|
||||||
|
if o.f == nil {
|
||||||
|
return errors.Errorf("metric collect func cannot be empty.")
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok = m.metrics[o.n]; !ok {
|
||||||
|
if err := o.t.Register(o); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
prometheus.MustRegister(o.v)
|
||||||
|
}
|
||||||
|
|
||||||
|
if m.metrics[o.n] == nil {
|
||||||
|
m.metrics[o.n] = new(atomic.Value)
|
||||||
|
}
|
||||||
|
|
||||||
|
m.metrics[o.n].Store(metric)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddMetric add custom monitor metric.
|
||||||
|
func (m *monitor) AddMetric(metric Metrics) error {
|
||||||
|
return m.SetMetric(metric)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListMetric retrieve a slice of metrics' name registered
|
||||||
|
func (m *monitor) ListMetric() []string {
|
||||||
|
var res = make([]string, 0)
|
||||||
|
|
||||||
|
m.m.Lock()
|
||||||
|
defer m.m.Unlock()
|
||||||
|
|
||||||
|
for k := range m.metrics {
|
||||||
|
res = append(res, k)
|
||||||
|
}
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
95
prometheus/types.go
Normal file
95
prometheus/types.go
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 Nicolas JUHEL
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package prometheus
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MetricType int
|
||||||
|
|
||||||
|
const (
|
||||||
|
None MetricType = iota
|
||||||
|
Counter
|
||||||
|
Gauge
|
||||||
|
Histogram
|
||||||
|
Summary
|
||||||
|
)
|
||||||
|
|
||||||
|
func (m MetricType) Register(metric *metrics) error {
|
||||||
|
switch metric.t {
|
||||||
|
case Counter:
|
||||||
|
return m.counterHandler(metric)
|
||||||
|
case Gauge:
|
||||||
|
return m.gaugeHandler(metric)
|
||||||
|
case Histogram:
|
||||||
|
return m.histogramHandler(metric)
|
||||||
|
case Summary:
|
||||||
|
return m.summaryHandler(metric)
|
||||||
|
}
|
||||||
|
|
||||||
|
return errors.Errorf("metric type is not compatible.")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m MetricType) counterHandler(metric *metrics) error {
|
||||||
|
metric.v = prometheus.NewCounterVec(
|
||||||
|
prometheus.CounterOpts{Name: metric.n, Help: metric.d},
|
||||||
|
metric.l,
|
||||||
|
)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m MetricType) gaugeHandler(metric *metrics) error {
|
||||||
|
metric.v = prometheus.NewGaugeVec(
|
||||||
|
prometheus.GaugeOpts{Name: metric.n, Help: metric.d},
|
||||||
|
metric.l,
|
||||||
|
)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m MetricType) histogramHandler(metric *metrics) error {
|
||||||
|
if len(metric.b) == 0 {
|
||||||
|
return errors.Errorf("metric '%s' is histogram type, cannot lose bucket param.", metric.n)
|
||||||
|
}
|
||||||
|
metric.v = prometheus.NewHistogramVec(
|
||||||
|
prometheus.HistogramOpts{Name: metric.n, Help: metric.d, Buckets: metric.b},
|
||||||
|
metric.l,
|
||||||
|
)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m MetricType) summaryHandler(metric *metrics) error {
|
||||||
|
if len(metric.o) == 0 {
|
||||||
|
return errors.Errorf("metric '%s' is summary type, cannot lose objectives param.", metric.n)
|
||||||
|
}
|
||||||
|
prometheus.NewSummaryVec(
|
||||||
|
prometheus.SummaryOpts{Name: metric.n, Help: metric.d, Objectives: metric.o},
|
||||||
|
metric.l,
|
||||||
|
)
|
||||||
|
return nil
|
||||||
|
}
|
Reference in New Issue
Block a user