-
Notifications
You must be signed in to change notification settings - Fork 485
/
collector_integration.go
105 lines (90 loc) · 3.17 KB
/
collector_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
package integrations
import (
"context"
"fmt"
"net/http"
"github.com/grafana/agent/pkg/build"
"github.com/grafana/agent/pkg/integrations/config"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
// CollectorIntegration is an integration exposing metrics from one or more Prometheus collectors.
type CollectorIntegration struct {
name string
cs []prometheus.Collector
includeExporterMetrics bool
runner func(context.Context) error
}
// NewCollectorIntegration creates a basic integration that exposes metrics from multiple prometheus.Collector.
func NewCollectorIntegration(name string, configs ...CollectorIntegrationConfig) *CollectorIntegration {
i := &CollectorIntegration{
name: name,
runner: func(ctx context.Context) error {
// We don't need to do anything by default, so we can just wait for the context to finish.
<-ctx.Done()
return ctx.Err()
},
}
for _, configure := range configs {
configure(i)
}
return i
}
// CollectorIntegrationConfig defines constructor configuration for NewCollectorIntegration
type CollectorIntegrationConfig func(integration *CollectorIntegration)
// WithCollectors adds more collectors to the CollectorIntegration being created.
func WithCollectors(cs ...prometheus.Collector) CollectorIntegrationConfig {
return func(i *CollectorIntegration) {
i.cs = append(i.cs, cs...)
}
}
// WithRunner replaces the runner of the CollectorIntegration.
// The runner function should run while the context provided is not done.
func WithRunner(runner func(context.Context) error) CollectorIntegrationConfig {
return func(i *CollectorIntegration) {
i.runner = runner
}
}
// WithExporterMetricsIncluded can enable the exporter metrics if the flag provided is enabled.
func WithExporterMetricsIncluded(included bool) CollectorIntegrationConfig {
return func(i *CollectorIntegration) {
i.includeExporterMetrics = included
}
}
// MetricsHandler returns the HTTP handler for the integration.
func (i *CollectorIntegration) MetricsHandler() (http.Handler, error) {
r := prometheus.NewRegistry()
for _, c := range i.cs {
if err := r.Register(c); err != nil {
return nil, fmt.Errorf("couldn't register %s: %w", i.name, err)
}
}
// Register <integration name>_build_info metrics, generally useful for
// dashboards that depend on them for discovering targets.
if err := r.Register(build.NewCollector(i.name)); err != nil {
return nil, fmt.Errorf("couldn't register %s: %w", i.name, err)
}
handler := promhttp.HandlerFor(
r,
promhttp.HandlerOpts{
ErrorHandling: promhttp.ContinueOnError,
},
)
if i.includeExporterMetrics {
// Note that we have to use reg here to use the same promhttp metrics for
// all expositions.
handler = promhttp.InstrumentMetricHandler(r, handler)
}
return handler, nil
}
// ScrapeConfigs satisfies Integration.ScrapeConfigs.
func (i *CollectorIntegration) ScrapeConfigs() []config.ScrapeConfig {
return []config.ScrapeConfig{{
JobName: i.name,
MetricsPath: "/metrics",
}}
}
// Run satisfies Integration.Run.
func (i *CollectorIntegration) Run(ctx context.Context) error {
return i.runner(ctx)
}