-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathmetrics.go
77 lines (64 loc) · 2.27 KB
/
metrics.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
package sqlds
import (
"fmt"
"strings"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
)
type Metrics struct {
DSName string
DSType string
Endpoint Endpoint
}
type Status string
type Endpoint string
type Source string
const (
StatusOK Status = "ok"
StatusError Status = "error"
EndpointHealth Endpoint = "health"
EndpointQuery Endpoint = "query"
SourceDownstream Source = "downstream"
SourcePlugin Source = "plugin"
)
var durationMetric = promauto.NewHistogramVec(prometheus.HistogramOpts{
Namespace: "plugins",
Name: "plugin_request_duration_seconds",
Help: "Duration of plugin execution",
}, []string{"datasource_name", "datasource_type", "source", "endpoint", "status"})
func NewMetrics(dsName, dsType string, endpoint Endpoint) Metrics {
dsName, ok := sanitizeLabelName(dsName)
if !ok {
backend.Logger.Warn("Failed to sanitize datasource name for prometheus label", dsName)
}
return Metrics{DSName: dsName, DSType: dsType, Endpoint: endpoint}
}
func (m *Metrics) WithEndpoint(endpoint Endpoint) Metrics {
return Metrics{DSName: m.DSName, DSType: m.DSType, Endpoint: endpoint}
}
func (m *Metrics) CollectDuration(source Source, status Status, duration float64) {
durationMetric.WithLabelValues(m.DSName, m.DSType, string(source), string(m.Endpoint), string(status)).Observe(duration)
}
// sanitizeLabelName removes all invalid chars from the label name.
// If the label name is empty or contains only invalid chars, it will return false indicating it was not sanitized.
// copied from https://github.com/grafana/grafana/blob/main/pkg/infra/metrics/metricutil/utils.go#L14
func sanitizeLabelName(name string) (string, bool) {
if len(name) == 0 {
backend.Logger.Warn(fmt.Sprintf("label name cannot be empty: %s", name))
return "", false
}
out := strings.Builder{}
for i, b := range name {
if (b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || b == '_' || (b >= '0' && b <= '9' && i > 0) {
out.WriteRune(b)
} else if b == ' ' {
out.WriteRune('_')
}
}
if out.Len() == 0 {
backend.Logger.Warn(fmt.Sprintf("label name only contains invalid chars: %q", name))
return "", false
}
return out.String(), true
}