-
Notifications
You must be signed in to change notification settings - Fork 91
/
metricshandler_integration.go
152 lines (128 loc) · 4.42 KB
/
metricshandler_integration.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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
package metricsutils
import (
"context"
"fmt"
"net/http"
"path"
"github.com/go-kit/log"
"github.com/gorilla/mux"
"github.com/grafana/alloy/internal/static/integrations/v2"
"github.com/grafana/alloy/internal/static/integrations/v2/autoscrape"
"github.com/grafana/alloy/internal/static/integrations/v2/common"
"github.com/prometheus/common/model"
"github.com/prometheus/prometheus/config"
"github.com/prometheus/prometheus/discovery"
"github.com/prometheus/prometheus/discovery/targetgroup"
)
// NewMetricsHandlerIntegration returns a integrations.MetricsIntegration which
// will expose a /metrics endpoint for h.
func NewMetricsHandlerIntegration(
_ log.Logger,
c integrations.Config,
mc common.MetricsConfig,
globals integrations.Globals,
h http.Handler,
) (integrations.MetricsIntegration, error) {
id, err := c.Identifier(globals)
if err != nil {
return nil, err
}
return &metricsHandlerIntegration{
integrationName: c.Name(),
instanceID: id,
common: mc,
globals: globals,
handler: h,
targets: []handlerTarget{{MetricsPath: "metrics"}},
}, nil
}
type metricsHandlerIntegration struct {
integrationName, instanceID string
common common.MetricsConfig
globals integrations.Globals
handler http.Handler
targets []handlerTarget
runFunc func(ctx context.Context) error
}
type handlerTarget struct {
// Path relative to Handler prefix where metrics are available.
MetricsPath string
// Extra labels to inject into the target. Labels here that take precedence
// over labels with the same name from the generated target group.
Labels model.LabelSet
}
// Static typecheck tests
var (
_ integrations.Integration = (*metricsHandlerIntegration)(nil)
_ integrations.HTTPIntegration = (*metricsHandlerIntegration)(nil)
_ integrations.MetricsIntegration = (*metricsHandlerIntegration)(nil)
)
// RunIntegration implements Integration.
func (i *metricsHandlerIntegration) RunIntegration(ctx context.Context) error {
// Call our runFunc if defined (used from integrationShim), otherwise
// fallback to no-op.
if i.runFunc != nil {
return i.runFunc(ctx)
}
<-ctx.Done()
return nil
}
// Handler implements HTTPIntegration.
func (i *metricsHandlerIntegration) Handler(prefix string) (http.Handler, error) {
r := mux.NewRouter()
r.Handle(path.Join(prefix, "metrics"), i.handler)
return r, nil
}
// Targets implements MetricsIntegration.
func (i *metricsHandlerIntegration) Targets(ep integrations.Endpoint) []*targetgroup.Group {
integrationNameValue := model.LabelValue("integrations/" + i.integrationName)
group := &targetgroup.Group{
Labels: model.LabelSet{
model.InstanceLabel: model.LabelValue(i.instanceID),
model.JobLabel: integrationNameValue,
"agent_hostname": model.LabelValue(i.globals.AgentIdentifier),
// Meta labels that can be used during SD.
"__meta_agent_integration_name": model.LabelValue(i.integrationName),
"__meta_agent_integration_instance": model.LabelValue(i.instanceID),
"__meta_agent_integration_autoscrape": model.LabelValue(BoolToString(*i.common.Autoscrape.Enable)),
},
Source: fmt.Sprintf("%s/%s", i.integrationName, i.instanceID),
}
for _, lbl := range i.common.ExtraLabels {
group.Labels[model.LabelName(lbl.Name)] = model.LabelValue(lbl.Value)
}
for _, t := range i.targets {
group.Targets = append(group.Targets, model.LabelSet{
model.AddressLabel: model.LabelValue(ep.Host),
model.MetricsPathLabel: model.LabelValue(path.Join(ep.Prefix, t.MetricsPath)),
}.Merge(t.Labels))
}
return []*targetgroup.Group{group}
}
// BoolToString is a helper for converting boolean values to a Prometheus labels-compatible string.
func BoolToString(b bool) string {
switch b {
case true:
return "1"
default:
return "0"
}
}
// ScrapeConfigs implements MetricsIntegration.
func (i *metricsHandlerIntegration) ScrapeConfigs(sd discovery.Configs) []*autoscrape.ScrapeConfig {
if !*i.common.Autoscrape.Enable {
return nil
}
cfg := config.DefaultScrapeConfig
cfg.JobName = fmt.Sprintf("%s/%s", i.integrationName, i.instanceID)
cfg.Scheme = i.globals.AgentBaseURL.Scheme
cfg.ServiceDiscoveryConfigs = sd
cfg.ScrapeInterval = i.common.Autoscrape.ScrapeInterval
cfg.ScrapeTimeout = i.common.Autoscrape.ScrapeTimeout
cfg.RelabelConfigs = i.common.Autoscrape.RelabelConfigs
cfg.MetricRelabelConfigs = i.common.Autoscrape.MetricRelabelConfigs
return []*autoscrape.ScrapeConfig{{
Instance: i.common.Autoscrape.MetricsInstance,
Config: cfg,
}}
}