...
1 package ginmetrics
2
3 import (
4 "github.com/pkg/errors"
5 "github.com/prometheus/client_golang/prometheus"
6 )
7
8 type MetricType int
9
10 const (
11 None MetricType = iota
12 Counter
13 Gauge
14 Histogram
15 Summary
16
17 defaultMetricPath = "/debug/metrics"
18 defaultSlowTime = int32(5)
19 )
20
21 var (
22 defaultDuration = []float64{0.1, 0.3, 1.2, 5, 10}
23 monitor *Monitor
24
25 promTypeHandler = map[MetricType]func(metric *Metric) error{
26 Counter: counterHandler,
27 Gauge: gaugeHandler,
28 Histogram: histogramHandler,
29 Summary: summaryHandler,
30 }
31 )
32
33
34 type Monitor struct {
35 slowTime int32
36 metricPath string
37 reqDuration []float64
38 metrics map[string]*Metric
39 }
40
41
42
43 func GetMonitor() *Monitor {
44 if monitor == nil {
45 monitor = &Monitor{
46 metricPath: defaultMetricPath,
47 slowTime: defaultSlowTime,
48 reqDuration: defaultDuration,
49 metrics: make(map[string]*Metric),
50 }
51 }
52 return monitor
53 }
54
55
56 func (m *Monitor) GetMetric(name string) *Metric {
57 if metric, ok := m.metrics[name]; ok {
58 return metric
59 }
60 return &Metric{}
61 }
62
63
64
65 func (m *Monitor) SetMetricPath(path string) {
66 m.metricPath = path
67 }
68
69
70
71 func (m *Monitor) SetSlowTime(slowTime int32) {
72 m.slowTime = slowTime
73 }
74
75
76
77 func (m *Monitor) SetDuration(duration []float64) {
78 m.reqDuration = duration
79 }
80
81 func (m *Monitor) SetMetricPrefix(prefix string) {
82 metricRequestTotal = prefix + metricRequestTotal
83 metricRequestUVTotal = prefix + metricRequestUVTotal
84 metricURIRequestTotal = prefix + metricURIRequestTotal
85 metricRequestBody = prefix + metricRequestBody
86 metricResponseBody = prefix + metricResponseBody
87 metricRequestDuration = prefix + metricRequestDuration
88 metricSlowRequest = prefix + metricSlowRequest
89 }
90
91 func (m *Monitor) SetMetricSuffix(suffix string) {
92 metricRequestTotal += suffix
93 metricRequestUVTotal += suffix
94 metricURIRequestTotal += suffix
95 metricRequestBody += suffix
96 metricResponseBody += suffix
97 metricRequestDuration += suffix
98 metricSlowRequest += suffix
99 }
100
101
102 func (m *Monitor) AddMetric(metric *Metric) error {
103 if _, ok := m.metrics[metric.Name]; ok {
104 return errors.Errorf("metric '%s' is existed", metric.Name)
105 }
106
107 if metric.Name == "" {
108 return errors.Errorf("metric name cannot be empty.")
109 }
110 if f, ok := promTypeHandler[metric.Type]; ok {
111 if err := f(metric); err == nil {
112 prometheus.MustRegister(metric.vec)
113 m.metrics[metric.Name] = metric
114 return nil
115 }
116 }
117 return errors.Errorf("metric type '%d' not existed.", metric.Type)
118 }
119
120 func counterHandler(metric *Metric) error {
121 metric.vec = prometheus.NewCounterVec(
122 prometheus.CounterOpts{Name: metric.Name, Help: metric.Description},
123 metric.Labels,
124 )
125 return nil
126 }
127
128 func gaugeHandler(metric *Metric) error {
129 metric.vec = prometheus.NewGaugeVec(
130 prometheus.GaugeOpts{Name: metric.Name, Help: metric.Description},
131 metric.Labels,
132 )
133 return nil
134 }
135
136 func histogramHandler(metric *Metric) error {
137 if len(metric.Buckets) == 0 {
138 return errors.Errorf("metric '%s' is histogram type, cannot lose bucket param.", metric.Name)
139 }
140 metric.vec = prometheus.NewHistogramVec(
141 prometheus.HistogramOpts{Name: metric.Name, Help: metric.Description, Buckets: metric.Buckets},
142 metric.Labels,
143 )
144 return nil
145 }
146
147 func summaryHandler(metric *Metric) error {
148 if len(metric.Objectives) == 0 {
149 return errors.Errorf("metric '%s' is summary type, cannot lose objectives param.", metric.Name)
150 }
151 prometheus.NewSummaryVec(
152 prometheus.SummaryOpts{Name: metric.Name, Help: metric.Description, Objectives: metric.Objectives},
153 metric.Labels,
154 )
155 return nil
156 }
157
View as plain text