Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
aos
GitHub Repository: aos/grafana-agent
Path: blob/main/pkg/integrations/blackbox_exporter/blackbox_exporter.go
5398 views
1
package blackbox_exporter
2
3
import (
4
"context"
5
"fmt"
6
"net/http"
7
"net/url"
8
9
"github.com/go-kit/log"
10
"github.com/grafana/agent/pkg/integrations"
11
"github.com/grafana/agent/pkg/integrations/config"
12
blackbox_config "github.com/prometheus/blackbox_exporter/config"
13
"github.com/prometheus/blackbox_exporter/prober"
14
)
15
16
// DefaultConfig holds the default settings for the blackbox_exporter integration.
17
var DefaultConfig = Config{
18
// Default value taken from https://github.com/prometheus/blackbox_exporter/blob/master/main.go#L61
19
ProbeTimeoutOffset: 0.5,
20
}
21
22
func loadFile(filename string, log log.Logger) (*blackbox_config.Config, error) {
23
sc := &blackbox_config.SafeConfig{
24
C: &blackbox_config.Config{},
25
}
26
err := sc.ReloadConfig(filename, log)
27
if err != nil {
28
return nil, err
29
}
30
return sc.C, nil
31
}
32
33
// BlackboxTarget defines a target device to be used by the integration.
34
type BlackboxTarget struct {
35
Name string `yaml:"name"`
36
Target string `yaml:"address"`
37
Module string `yaml:"module"`
38
}
39
40
// Config configures the Blackbox integration.
41
type Config struct {
42
BlackboxConfigFile string `yaml:"config_file,omitempty"`
43
BlackboxTargets []BlackboxTarget `yaml:"blackbox_targets"`
44
BlackboxConfig blackbox_config.Config `yaml:"blackbox_config,omitempty"`
45
ProbeTimeoutOffset float64 `yaml:"probe_timeout_offset,omitempty"`
46
}
47
48
// UnmarshalYAML implements yaml.Unmarshaler for Config.
49
func (c *Config) UnmarshalYAML(unmarshal func(interface{}) error) error {
50
*c = DefaultConfig
51
52
type plain Config
53
return unmarshal((*plain)(c))
54
}
55
56
// Name returns the name of the integration.
57
func (c *Config) Name() string {
58
return "blackbox"
59
}
60
61
// InstanceKey returns the hostname:port of the agent.
62
func (c *Config) InstanceKey(agentKey string) (string, error) {
63
return agentKey, nil
64
}
65
66
// NewIntegration creates a new blackbox integration.
67
func (c *Config) NewIntegration(l log.Logger) (integrations.Integration, error) {
68
return New(l, c)
69
}
70
71
func init() {
72
integrations.RegisterIntegration(&Config{})
73
}
74
75
// LoadBlackboxConfig loads the blackbox config from the given file or from embedded yaml block
76
// it also validates that targets are properly defined
77
func LoadBlackboxConfig(log log.Logger, configFile string, targets []BlackboxTarget, modules *blackbox_config.Config) (*blackbox_config.Config, error) {
78
var err error
79
80
if configFile != "" {
81
modules, err = loadFile(configFile, log)
82
if err != nil {
83
return nil, fmt.Errorf("failed to load blackbox config from file %v: %w", configFile, err)
84
}
85
}
86
87
// The `name` and `address` fields are mandatory for the Blackbox targets are mandatory.
88
// Enforce this check and fail the creation of the integration if they're missing.
89
for _, target := range targets {
90
if target.Name == "" || target.Target == "" {
91
return nil, fmt.Errorf("failed to load blackbox_targets; the `name` and `address` fields are mandatory")
92
}
93
}
94
return modules, nil
95
}
96
97
// New creates a new blackbox_exporter integration
98
func New(log log.Logger, c *Config) (integrations.Integration, error) {
99
modules, err := LoadBlackboxConfig(log, c.BlackboxConfigFile, c.BlackboxTargets, &c.BlackboxConfig)
100
if err != nil {
101
return nil, err
102
}
103
104
integration := &Integration{
105
cfg: c,
106
modules: modules,
107
log: log,
108
}
109
return integration, nil
110
}
111
112
// Integration is the blackbox integration. The integration scrapes metrics
113
// probing of endpoints over HTTP, HTTPS, DNS, TCP, ICMP and gRPC.
114
type Integration struct {
115
cfg *Config
116
modules *blackbox_config.Config
117
log log.Logger
118
}
119
120
// MetricsHandler implements Integration.
121
func (i *Integration) MetricsHandler() (http.Handler, error) {
122
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
123
prober.Handler(w, r, i.modules, i.log, &prober.ResultHistory{}, i.cfg.ProbeTimeoutOffset, nil)
124
}), nil
125
}
126
127
// Run satisfies Integration.Run.
128
func (i *Integration) Run(ctx context.Context) error {
129
// We don't need to do anything here, so we can just wait for the context to
130
// finish.
131
<-ctx.Done()
132
return ctx.Err()
133
}
134
135
// ScrapeConfigs satisfies Integration.ScrapeConfigs.
136
func (i *Integration) ScrapeConfigs() []config.ScrapeConfig {
137
var res []config.ScrapeConfig
138
for _, target := range i.cfg.BlackboxTargets {
139
queryParams := url.Values{}
140
queryParams.Add("target", target.Target)
141
if target.Module != "" {
142
queryParams.Add("module", target.Module)
143
}
144
res = append(res, config.ScrapeConfig{
145
JobName: i.cfg.Name() + "/" + target.Name,
146
MetricsPath: "/metrics",
147
QueryParams: queryParams,
148
})
149
}
150
return res
151
}
152
153