From 0b7a01bc892396781ec7630f857c9dd29f23d8c3 Mon Sep 17 00:00:00 2001 From: Brian Brazil Date: Mon, 4 Sep 2017 14:22:47 +0100 Subject: [PATCH] Switch to go-kit for logging --- main.go | 39 +++++++++++++++++++++++---------------- main_test.go | 4 +++- prober/dns.go | 43 ++++++++++++++++++++++--------------------- prober/dns_test.go | 19 ++++++++++--------- prober/http.go | 23 ++++++++++++----------- prober/http_test.go | 41 +++++++++++++++++++++-------------------- prober/icmp.go | 24 ++++++++++++------------ prober/prober.go | 3 ++- prober/tcp.go | 33 +++++++++++++++++---------------- prober/tcp_test.go | 25 +++++++++++++------------ 10 files changed, 135 insertions(+), 119 deletions(-) diff --git a/main.go b/main.go index bb79c03..044d976 100644 --- a/main.go +++ b/main.go @@ -23,12 +23,15 @@ import ( "syscall" "time" + "github.com/go-kit/kit/log" + "github.com/go-kit/kit/log/level" "gopkg.in/alecthomas/kingpin.v2" "gopkg.in/yaml.v2" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" - "github.com/prometheus/common/log" + "github.com/prometheus/common/promlog" + "github.com/prometheus/common/promlog/flag" "github.com/prometheus/common/version" "github.com/prometheus/blackbox_exporter/config" @@ -52,7 +55,7 @@ var ( } ) -func probeHandler(w http.ResponseWriter, r *http.Request, c *config.Config) { +func probeHandler(w http.ResponseWriter, r *http.Request, c *config.Config, logger log.Logger) { moduleName := r.URL.Query().Get("module") if moduleName == "" { moduleName = "http_2xx" @@ -109,7 +112,7 @@ func probeHandler(w http.ResponseWriter, r *http.Request, c *config.Config) { registry := prometheus.NewRegistry() registry.MustRegister(probeSuccessGauge) registry.MustRegister(probeDurationGauge) - success := prober(ctx, target, module, registry) + success := prober(ctx, target, module, registry, logger) probeDurationGauge.Set(time.Since(start).Seconds()) if success { probeSuccessGauge.Set(1) @@ -123,18 +126,21 @@ func init() { } func main() { - log.AddFlags(kingpin.CommandLine) + allowedLevel := promlog.AllowedLevel{} + flag.AddFlags(kingpin.CommandLine, &allowedLevel) kingpin.Version(version.Print("blackbox_exporter")) kingpin.HelpFlag.Short('h') kingpin.Parse() + logger := promlog.New(allowedLevel) - log.Infoln("Starting blackbox_exporter", version.Info()) - log.Infoln("Build context", version.BuildContext()) + level.Info(logger).Log("msg", "Starting blackbox_exporter", "version", version.Info()) + level.Info(logger).Log("msg", "Build context", version.BuildContext()) if err := sc.ReloadConfig(*configFile); err != nil { - log.Fatalf("Error loading config: %s", err) + level.Error(logger).Log("msg", "Error loading config", "err", err) + os.Exit(1) } - log.Infoln("Loaded config file") + level.Info(logger).Log("msg", "Loaded config file") hup := make(chan os.Signal) reloadCh := make(chan chan error) @@ -144,16 +150,16 @@ func main() { select { case <-hup: if err := sc.ReloadConfig(*configFile); err != nil { - log.Errorf("Error reloading config: %s", err) + level.Error(logger).Log("msg", "Error reloading config", "err", err) continue } - log.Infoln("Loaded config file") + level.Info(logger).Log("msg", "Reloaded config file") case rc := <-reloadCh: if err := sc.ReloadConfig(*configFile); err != nil { - log.Errorf("Error reloading config: %s", err) + level.Error(logger).Log("msg", "Error reloading config", "err", err) rc <- err } else { - log.Infoln("Loaded config file") + level.Info(logger).Log("msg", "Reloaded config file") rc <- nil } } @@ -179,7 +185,7 @@ func main() { sc.Lock() conf := sc.C sc.Unlock() - probeHandler(w, r, conf) + probeHandler(w, r, conf, logger) }) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte(` @@ -198,15 +204,16 @@ func main() { c, err := yaml.Marshal(sc.C) sc.RUnlock() if err != nil { - log.Warnf("Error marshalling configuration: %v", err) + level.Warn(logger).Log("msg", "Error marshalling configuration", "err", err) http.Error(w, err.Error(), 500) return } w.Write(c) }) - log.Infoln("Listening on", *listenAddress) + level.Info(logger).Log("msg", "Listening on address", "address", *listenAddress) if err := http.ListenAndServe(*listenAddress, nil); err != nil { - log.Fatalf("Error starting HTTP server: %s", err) + level.Error(logger).Log("msg", "Error starting HTTP server", "err", err) + os.Exit(1) } } diff --git a/main_test.go b/main_test.go index 4665ef5..e76da63 100644 --- a/main_test.go +++ b/main_test.go @@ -6,6 +6,8 @@ import ( "testing" "time" + "github.com/go-kit/kit/log" + "github.com/prometheus/blackbox_exporter/config" ) @@ -33,7 +35,7 @@ func TestPrometheusTimeoutHTTP(t *testing.T) { rr := httptest.NewRecorder() handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - probeHandler(w, r, c) + probeHandler(w, r, c, log.NewNopLogger()) }) handler.ServeHTTP(rr, req) diff --git a/prober/dns.go b/prober/dns.go index 2a7f0d9..2418a6a 100644 --- a/prober/dns.go +++ b/prober/dns.go @@ -19,26 +19,27 @@ import ( "regexp" "time" + "github.com/go-kit/kit/log" + "github.com/go-kit/kit/log/level" "github.com/miekg/dns" "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/common/log" "github.com/prometheus/blackbox_exporter/config" ) // validRRs checks a slice of RRs received from the server against a DNSRRValidator. -func validRRs(rrs *[]dns.RR, v *config.DNSRRValidator) bool { +func validRRs(rrs *[]dns.RR, v *config.DNSRRValidator, logger log.Logger) bool { // Fail the probe if there are no RRs of a given type, but a regexp match is required // (i.e. FailIfNotMatchesRegexp is set). if len(*rrs) == 0 && len(v.FailIfNotMatchesRegexp) > 0 { return false } for _, rr := range *rrs { - log.Debugf("Validating RR: %q", rr) + level.Debug(logger).Log("msg", "Validating RR: %q", rr) for _, re := range v.FailIfMatchesRegexp { match, err := regexp.MatchString(re, rr.String()) if err != nil { - log.Errorf("Error matching regexp %q: %s", re, err) + level.Error(logger).Log("msg", "Error matching regexp %q: %s", re, err) return false } if match { @@ -48,7 +49,7 @@ func validRRs(rrs *[]dns.RR, v *config.DNSRRValidator) bool { for _, re := range v.FailIfNotMatchesRegexp { match, err := regexp.MatchString(re, rr.String()) if err != nil { - log.Errorf("Error matching regexp %q: %s", re, err) + level.Error(logger).Log("msg", "Error matching regexp %q: %s", re, err) return false } if !match { @@ -60,7 +61,7 @@ func validRRs(rrs *[]dns.RR, v *config.DNSRRValidator) bool { } // validRcode checks rcode in the response against a list of valid rcodes. -func validRcode(rcode int, valid []string) bool { +func validRcode(rcode int, valid []string, logger log.Logger) bool { var validRcodes []int // If no list of valid rcodes is specified, only NOERROR is considered valid. if valid == nil { @@ -69,7 +70,7 @@ func validRcode(rcode int, valid []string) bool { for _, rcode := range valid { rc, ok := dns.StringToRcode[rcode] if !ok { - log.Errorf("Invalid rcode %v. Existing rcodes: %v", rcode, dns.RcodeToString) + level.Error(logger).Log("msg", "Invalid rcode", "rcode", rcode, "known_rcode", dns.RcodeToString) return false } validRcodes = append(validRcodes, rc) @@ -80,11 +81,11 @@ func validRcode(rcode int, valid []string) bool { return true } } - log.Debugf("%s (%d) is not one of the valid rcodes (%v)", dns.RcodeToString[rcode], rcode, validRcodes) + level.Error(logger).Log("msg", "Rcode is not one of the valid rcodes", "string_rcode", dns.RcodeToString[rcode], "rcode", rcode, "valid_rcodes", validRcodes) return false } -func ProbeDNS(ctx context.Context, target string, module config.Module, registry *prometheus.Registry) bool { +func ProbeDNS(ctx context.Context, target string, module config.Module, registry *prometheus.Registry, logger log.Logger) bool { var numAnswer, numAuthority, numAdditional int var dialProtocol string probeDNSAnswerRRSGauge := prometheus.NewGauge(prometheus.GaugeOpts{ @@ -124,12 +125,12 @@ func ProbeDNS(ctx context.Context, target string, module config.Module, registry } ip, err = chooseProtocol(module.DNS.PreferredIPProtocol, targetAddr, registry) if err != nil { - log.Error(err) + level.Error(logger).Log("msg", "Error resolving address", "err", err) return false } target = net.JoinHostPort(ip.String(), port) } else { - log.Errorf("Configuration error: Expected transport protocol udp or tcp, got %s", module.DNS.TransportProtocol) + level.Error(logger).Log("msg", "Configuration error: Expected transport protocol udp or tcp", "protocol", module.DNS.TransportProtocol) return false } @@ -146,7 +147,7 @@ func ProbeDNS(ctx context.Context, target string, module config.Module, registry var ok bool qt, ok = dns.StringToType[module.DNS.QueryType] if !ok { - log.Errorf("Invalid type %v. Existing types: %v", module.DNS.QueryType, dns.TypeToString) + level.Error(logger).Log("msg", "Invalid query type", "Type seen", module.DNS.QueryType, "Existing types", dns.TypeToString) return false } } @@ -157,26 +158,26 @@ func ProbeDNS(ctx context.Context, target string, module config.Module, registry client.Timeout = timeoutDeadline.Sub(time.Now()) response, _, err := client.Exchange(msg, target) if err != nil { - log.Warnf("Error while sending a DNS query: %s", err) + level.Warn(logger).Log("msg", "Error while sending a DNS query", "err", err) return false } - log.Debugf("Got response: %#v", response) + level.Debug(logger).Log("msg", "Got response: %#v", response) numAnswer, numAuthority, numAdditional = len(response.Answer), len(response.Ns), len(response.Extra) - if !validRcode(response.Rcode, module.DNS.ValidRcodes) { + if !validRcode(response.Rcode, module.DNS.ValidRcodes, logger) { return false } - if !validRRs(&response.Answer, &module.DNS.ValidateAnswer) { - log.Debugf("Answer RRs validation failed") + if !validRRs(&response.Answer, &module.DNS.ValidateAnswer, logger) { + level.Debug(logger).Log("msg", "Answer RRs validation failed") return false } - if !validRRs(&response.Ns, &module.DNS.ValidateAuthority) { - log.Debugf("Authority RRs validation failed") + if !validRRs(&response.Ns, &module.DNS.ValidateAuthority, logger) { + level.Debug(logger).Log("msg", "Authority RRs validation failed") return false } - if !validRRs(&response.Extra, &module.DNS.ValidateAdditional) { - log.Debugf("Additional RRs validation failed") + if !validRRs(&response.Extra, &module.DNS.ValidateAdditional, logger) { + level.Debug(logger).Log("msg", "Additional RRs validation failed") return false } return true diff --git a/prober/dns_test.go b/prober/dns_test.go index 6425185..3f6c023 100644 --- a/prober/dns_test.go +++ b/prober/dns_test.go @@ -20,6 +20,7 @@ import ( "testing" "time" + "github.com/go-kit/kit/log" "github.com/miekg/dns" "github.com/prometheus/client_golang/prometheus" @@ -124,7 +125,7 @@ func TestRecursiveDNSResponse(t *testing.T) { testCTX, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() - result := ProbeDNS(testCTX, addr.String(), config.Module{Timeout: time.Second, DNS: test.Probe}, registry) + result := ProbeDNS(testCTX, addr.String(), config.Module{Timeout: time.Second, DNS: test.Probe}, registry, log.NewNopLogger()) if result != test.ShouldSucceed { t.Fatalf("Test %d had unexpected result: %v", i, result) } @@ -251,7 +252,7 @@ func TestAuthoritativeDNSResponse(t *testing.T) { registry := prometheus.NewRegistry() testCTX, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() - result := ProbeDNS(testCTX, addr.String(), config.Module{Timeout: time.Second, DNS: test.Probe}, registry) + result := ProbeDNS(testCTX, addr.String(), config.Module{Timeout: time.Second, DNS: test.Probe}, registry, log.NewNopLogger()) if result != test.ShouldSucceed { t.Fatalf("Test %d had unexpected result: %v", i, result) } @@ -309,7 +310,7 @@ func TestServfailDNSResponse(t *testing.T) { registry := prometheus.NewRegistry() testCTX, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() - result := ProbeDNS(testCTX, addr.String(), config.Module{Timeout: time.Second, DNS: test.Probe}, registry) + result := ProbeDNS(testCTX, addr.String(), config.Module{Timeout: time.Second, DNS: test.Probe}, registry, log.NewNopLogger()) if result != test.ShouldSucceed { t.Fatalf("Test %d had unexpected result: %v", i, result) } @@ -357,7 +358,7 @@ func TestDNSProtocol(t *testing.T) { registry := prometheus.NewRegistry() testCTX, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() - result := ProbeDNS(testCTX, net.JoinHostPort("localhost", port), module, registry) + result := ProbeDNS(testCTX, net.JoinHostPort("localhost", port), module, registry, log.NewNopLogger()) if !result { t.Fatalf("DNS protocol: \"%v4\" connection test failed, expected success.", protocol) } @@ -383,7 +384,7 @@ func TestDNSProtocol(t *testing.T) { registry = prometheus.NewRegistry() testCTX, cancel = context.WithTimeout(context.Background(), 10*time.Second) defer cancel() - result = ProbeDNS(testCTX, net.JoinHostPort("localhost", port), module, registry) + result = ProbeDNS(testCTX, net.JoinHostPort("localhost", port), module, registry, log.NewNopLogger()) if !result { t.Fatalf("DNS protocol: \"%v6\" connection test failed, expected success.", protocol) } @@ -408,7 +409,7 @@ func TestDNSProtocol(t *testing.T) { registry = prometheus.NewRegistry() testCTX, cancel = context.WithTimeout(context.Background(), 10*time.Second) defer cancel() - result = ProbeDNS(testCTX, net.JoinHostPort("localhost", port), module, registry) + result = ProbeDNS(testCTX, net.JoinHostPort("localhost", port), module, registry, log.NewNopLogger()) if !result { t.Fatalf("DNS protocol: \"%v\", preferred \"ip6\" connection test failed, expected success.", protocol) } @@ -433,7 +434,7 @@ func TestDNSProtocol(t *testing.T) { registry = prometheus.NewRegistry() testCTX, cancel = context.WithTimeout(context.Background(), 10*time.Second) defer cancel() - result = ProbeDNS(testCTX, net.JoinHostPort("localhost", port), module, registry) + result = ProbeDNS(testCTX, net.JoinHostPort("localhost", port), module, registry, log.NewNopLogger()) if !result { t.Fatalf("DNS protocol: \"%v\", preferred \"ip4\" connection test failed, expected success.", protocol) } @@ -458,7 +459,7 @@ func TestDNSProtocol(t *testing.T) { registry = prometheus.NewRegistry() testCTX, cancel = context.WithTimeout(context.Background(), 10*time.Second) defer cancel() - result = ProbeDNS(testCTX, net.JoinHostPort("localhost", port), module, registry) + result = ProbeDNS(testCTX, net.JoinHostPort("localhost", port), module, registry, log.NewNopLogger()) if !result { t.Fatalf("DNS protocol: \"%v\" connection test failed, expected success.", protocol) } @@ -482,7 +483,7 @@ func TestDNSProtocol(t *testing.T) { registry = prometheus.NewRegistry() testCTX, cancel = context.WithTimeout(context.Background(), 10*time.Second) defer cancel() - result = ProbeDNS(testCTX, net.JoinHostPort("localhost", port), module, registry) + result = ProbeDNS(testCTX, net.JoinHostPort("localhost", port), module, registry, log.NewNopLogger()) if protocol == "udp" { if !result { t.Fatalf("DNS test connection with protocol %s failed, expected success.", protocol) diff --git a/prober/http.go b/prober/http.go index 39dbfa0..7bc284b 100644 --- a/prober/http.go +++ b/prober/http.go @@ -25,23 +25,24 @@ import ( "strconv" "strings" + "github.com/go-kit/kit/log" + "github.com/go-kit/kit/log/level" "github.com/prometheus/client_golang/prometheus" pconfig "github.com/prometheus/common/config" - "github.com/prometheus/common/log" "github.com/prometheus/blackbox_exporter/config" ) -func matchRegularExpressions(reader io.Reader, httpConfig config.HTTPProbe) bool { +func matchRegularExpressions(reader io.Reader, httpConfig config.HTTPProbe, logger log.Logger) bool { body, err := ioutil.ReadAll(reader) if err != nil { - log.Errorf("Error reading HTTP body: %s", err) + level.Error(logger).Log("msg", "Error reading HTTP body", "err", err) return false } for _, expression := range httpConfig.FailIfMatchesRegexp { re, err := regexp.Compile(expression) if err != nil { - log.Errorf("Could not compile expression %q as regular expression: %s", expression, err) + level.Error(logger).Log("msg", "Could not compile regular expression", "regexp", expression, "err", err) return false } if re.Match(body) { @@ -51,7 +52,7 @@ func matchRegularExpressions(reader io.Reader, httpConfig config.HTTPProbe) bool for _, expression := range httpConfig.FailIfNotMatchesRegexp { re, err := regexp.Compile(expression) if err != nil { - log.Errorf("Could not compile expression %q as regular expression: %s", expression, err) + level.Error(logger).Log("msg", "Could not compile regular expression", "regexp", expression, "err", err) return false } if !re.Match(body) { @@ -61,7 +62,7 @@ func matchRegularExpressions(reader io.Reader, httpConfig config.HTTPProbe) bool return true } -func ProbeHTTP(ctx context.Context, target string, module config.Module, registry *prometheus.Registry) (success bool) { +func ProbeHTTP(ctx context.Context, target string, module config.Module, registry *prometheus.Registry, logger log.Logger) (success bool) { var redirects int var ( contentLengthGauge = prometheus.NewGauge(prometheus.GaugeOpts{ @@ -132,7 +133,7 @@ func ProbeHTTP(ctx context.Context, target string, module config.Module, registr client, err := pconfig.NewHTTPClientFromConfig(httpClientConfig) if err != nil { - log.Errorf("Error generating HTTP client: %v", err) + level.Error(logger).Log("msg", "Error generating HTTP client", "err", err) return false } @@ -158,7 +159,7 @@ func ProbeHTTP(ctx context.Context, target string, module config.Module, registr } if err != nil { - log.Errorf("Error creating request for target %s: %s", target, err) + level.Error(logger).Log("msg", "Error creating request", "err", err) return } @@ -177,7 +178,7 @@ func ProbeHTTP(ctx context.Context, target string, module config.Module, registr resp, err := client.Do(request) // Err won't be nil if redirects were turned off. See https://github.com/golang/go/issues/3795 if err != nil && resp == nil { - log.Errorf("Error for HTTP request to %s: %s", target, err) + level.Error(logger).Log("msg", "Error for HTTP request", "err", err) success = false } else { defer resp.Body.Close() @@ -193,7 +194,7 @@ func ProbeHTTP(ctx context.Context, target string, module config.Module, registr } if success && (len(httpConfig.FailIfMatchesRegexp) > 0 || len(httpConfig.FailIfNotMatchesRegexp) > 0) { - success = matchRegularExpressions(resp.Body, httpConfig) + success = matchRegularExpressions(resp.Body, httpConfig, logger) if success { probeFailedDueToRegex.Set(0) } else { @@ -204,7 +205,7 @@ func ProbeHTTP(ctx context.Context, target string, module config.Module, registr var httpVersionNumber float64 httpVersionNumber, err = strconv.ParseFloat(strings.TrimPrefix(resp.Proto, "HTTP/"), 64) if err != nil { - log.Errorf("Error parsing version number from HTTP version: %v", err) + level.Error(logger).Log("msg", "Error parsing version number from HTTP version", "err", err) } probeHTTPVersionGauge.Set(httpVersionNumber) diff --git a/prober/http_test.go b/prober/http_test.go index 43b9e31..ad86f18 100644 --- a/prober/http_test.go +++ b/prober/http_test.go @@ -22,6 +22,7 @@ import ( "testing" "time" + "github.com/go-kit/kit/log" "github.com/prometheus/client_golang/prometheus" pconfig "github.com/prometheus/common/config" @@ -55,7 +56,7 @@ func TestHTTPStatusCodes(t *testing.T) { testCTX, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() result := ProbeHTTP(testCTX, ts.URL, - config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{ValidStatusCodes: test.ValidStatusCodes}}, registry) + config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{ValidStatusCodes: test.ValidStatusCodes}}, registry, log.NewNopLogger()) body := recorder.Body.String() if result != test.ShouldSucceed { t.Fatalf("Test %d had unexpected result: %s", i, body) @@ -82,7 +83,7 @@ func TestValidHTTPVersion(t *testing.T) { result := ProbeHTTP(context.Background(), ts.URL, config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{ ValidHTTPVersions: test.ValidHTTPVersions, - }}, registry) + }}, registry, log.NewNopLogger()) body := recorder.Body.String() if result != test.ShouldSucceed { t.Fatalf("Test %v had unexpected result: %s", i, body) @@ -103,7 +104,7 @@ func TestRedirectFollowed(t *testing.T) { registry := prometheus.NewRegistry() testCTX, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() - result := ProbeHTTP(testCTX, ts.URL, config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{}}, registry) + result := ProbeHTTP(testCTX, ts.URL, config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{}}, registry, log.NewNopLogger()) body := recorder.Body.String() if !result { t.Fatalf("Redirect test failed unexpectedly, got %s", body) @@ -131,7 +132,7 @@ func TestRedirectNotFollowed(t *testing.T) { testCTX, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() result := ProbeHTTP(testCTX, ts.URL, - config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{NoFollowRedirects: true, ValidStatusCodes: []int{302}}}, registry) + config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{NoFollowRedirects: true, ValidStatusCodes: []int{302}}}, registry, log.NewNopLogger()) body := recorder.Body.String() if !result { t.Fatalf("Redirect test failed unexpectedly, got %s", body) @@ -152,7 +153,7 @@ func TestPost(t *testing.T) { testCTX, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() result := ProbeHTTP(testCTX, ts.URL, - config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{Method: "POST"}}, registry) + config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{Method: "POST"}}, registry, log.NewNopLogger()) body := recorder.Body.String() if !result { t.Fatalf("Post test failed unexpectedly, got %s", body) @@ -174,7 +175,7 @@ func TestBasicAuth(t *testing.T) { TLSConfig: pconfig.TLSConfig{InsecureSkipVerify: false}, BasicAuth: &pconfig.BasicAuth{Username: "username", Password: "password"}, }, - }}, registry) + }}, registry, log.NewNopLogger()) body := recorder.Body.String() if !result { t.Fatalf("HTTP probe failed, got %s", body) @@ -195,7 +196,7 @@ func TestBearerToken(t *testing.T) { HTTPClientConfig: pconfig.HTTPClientConfig{ BearerToken: pconfig.Secret("mysecret"), }, - }}, registry) + }}, registry, log.NewNopLogger()) body := recorder.Body.String() if !result { t.Fatalf("HTTP probe failed, got %s", body) @@ -212,7 +213,7 @@ func TestFailIfNotSSL(t *testing.T) { testCTX, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() result := ProbeHTTP(testCTX, ts.URL, - config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{FailIfNotSSL: true}}, registry) + config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{FailIfNotSSL: true}}, registry, log.NewNopLogger()) body := recorder.Body.String() if result { t.Fatalf("Fail if not SSL test suceeded unexpectedly, got %s", body) @@ -238,7 +239,7 @@ func TestFailIfMatchesRegexp(t *testing.T) { testCTX, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() result := ProbeHTTP(testCTX, ts.URL, - config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{FailIfMatchesRegexp: []string{"could not connect to database"}}}, registry) + config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{FailIfMatchesRegexp: []string{"could not connect to database"}}}, registry, log.NewNopLogger()) body := recorder.Body.String() if result { t.Fatalf("Regexp test succeeded unexpectedly, got %s", body) @@ -260,7 +261,7 @@ func TestFailIfMatchesRegexp(t *testing.T) { recorder = httptest.NewRecorder() registry = prometheus.NewRegistry() result = ProbeHTTP(testCTX, ts.URL, - config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{FailIfMatchesRegexp: []string{"could not connect to database"}}}, registry) + config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{FailIfMatchesRegexp: []string{"could not connect to database"}}}, registry, log.NewNopLogger()) body = recorder.Body.String() if !result { t.Fatalf("Regexp test failed unexpectedly, got %s", body) @@ -284,7 +285,7 @@ func TestFailIfMatchesRegexp(t *testing.T) { recorder = httptest.NewRecorder() registry = prometheus.NewRegistry() result = ProbeHTTP(testCTX, ts.URL, - config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{FailIfMatchesRegexp: []string{"could not connect to database", "internal error"}}}, registry) + config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{FailIfMatchesRegexp: []string{"could not connect to database", "internal error"}}}, registry, log.NewNopLogger()) body = recorder.Body.String() if result { t.Fatalf("Regexp test succeeded unexpectedly, got %s", body) @@ -298,7 +299,7 @@ func TestFailIfMatchesRegexp(t *testing.T) { recorder = httptest.NewRecorder() registry = prometheus.NewRegistry() result = ProbeHTTP(testCTX, ts.URL, - config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{FailIfMatchesRegexp: []string{"could not connect to database", "internal error"}}}, registry) + config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{FailIfMatchesRegexp: []string{"could not connect to database", "internal error"}}}, registry, log.NewNopLogger()) body = recorder.Body.String() if !result { t.Fatalf("Regexp test failed unexpectedly, got %s", body) @@ -316,7 +317,7 @@ func TestFailIfNotMatchesRegexp(t *testing.T) { testCTX, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() result := ProbeHTTP(testCTX, ts.URL, - config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{FailIfNotMatchesRegexp: []string{"Download the latest version here"}}}, registry) + config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{FailIfNotMatchesRegexp: []string{"Download the latest version here"}}}, registry, log.NewNopLogger()) body := recorder.Body.String() if result { t.Fatalf("Regexp test succeeded unexpectedly, got %s", body) @@ -330,7 +331,7 @@ func TestFailIfNotMatchesRegexp(t *testing.T) { recorder = httptest.NewRecorder() registry = prometheus.NewRegistry() result = ProbeHTTP(testCTX, ts.URL, - config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{FailIfNotMatchesRegexp: []string{"Download the latest version here"}}}, registry) + config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{FailIfNotMatchesRegexp: []string{"Download the latest version here"}}}, registry, log.NewNopLogger()) body = recorder.Body.String() if !result { t.Fatalf("Regexp test failed unexpectedly, got %s", body) @@ -346,7 +347,7 @@ func TestFailIfNotMatchesRegexp(t *testing.T) { recorder = httptest.NewRecorder() registry = prometheus.NewRegistry() result = ProbeHTTP(testCTX, ts.URL, - config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{FailIfNotMatchesRegexp: []string{"Download the latest version here", "Copyright 2015"}}}, registry) + config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{FailIfNotMatchesRegexp: []string{"Download the latest version here", "Copyright 2015"}}}, registry, log.NewNopLogger()) body = recorder.Body.String() if result { t.Fatalf("Regexp test succeeded unexpectedly, got %s", body) @@ -360,7 +361,7 @@ func TestFailIfNotMatchesRegexp(t *testing.T) { recorder = httptest.NewRecorder() registry = prometheus.NewRegistry() result = ProbeHTTP(testCTX, ts.URL, - config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{FailIfNotMatchesRegexp: []string{"Download the latest version here", "Copyright 2015"}}}, registry) + config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{FailIfNotMatchesRegexp: []string{"Download the latest version here", "Copyright 2015"}}}, registry, log.NewNopLogger()) body = recorder.Body.String() if !result { t.Fatalf("Regexp test failed unexpectedly, got %s", body) @@ -393,7 +394,7 @@ func TestHTTPHeaders(t *testing.T) { defer cancel() result := ProbeHTTP(testCTX, ts.URL, config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{ Headers: headers, - }}, registry) + }}, registry, log.NewNopLogger()) if !result { t.Fatalf("Probe failed unexpectedly.") } @@ -413,7 +414,7 @@ func TestFailIfSelfSignedCA(t *testing.T) { HTTPClientConfig: pconfig.HTTPClientConfig{ TLSConfig: pconfig.TLSConfig{InsecureSkipVerify: false}, }, - }}, registry) + }}, registry, log.NewNopLogger()) body := recorder.Body.String() if result { t.Fatalf("Fail if selfsigned CA test suceeded unexpectedly, got %s", body) @@ -442,7 +443,7 @@ func TestSucceedIfSelfSignedCA(t *testing.T) { HTTPClientConfig: pconfig.HTTPClientConfig{ TLSConfig: pconfig.TLSConfig{InsecureSkipVerify: true}, }, - }}, registry) + }}, registry, log.NewNopLogger()) body := recorder.Body.String() if !result { t.Fatalf("Fail if (not strict) selfsigned CA test fails unexpectedly, got %s", body) @@ -471,7 +472,7 @@ func TestTLSConfigIsIgnoredForPlainHTTP(t *testing.T) { HTTPClientConfig: pconfig.HTTPClientConfig{ TLSConfig: pconfig.TLSConfig{InsecureSkipVerify: false}, }, - }}, registry) + }}, registry, log.NewNopLogger()) body := recorder.Body.String() if !result { t.Fatalf("Fail if InsecureSkipVerify affects simple http fails unexpectedly, got %s", body) diff --git a/prober/icmp.go b/prober/icmp.go index 9c1a5d6..d62c20e 100644 --- a/prober/icmp.go +++ b/prober/icmp.go @@ -21,13 +21,13 @@ import ( "sync" "time" + "github.com/go-kit/kit/log" + "github.com/go-kit/kit/log/level" + "github.com/prometheus/client_golang/prometheus" "golang.org/x/net/icmp" "golang.org/x/net/ipv4" "golang.org/x/net/ipv6" - "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/common/log" - "github.com/prometheus/blackbox_exporter/config" ) @@ -43,7 +43,7 @@ func getICMPSequence() uint16 { return icmpSequence } -func ProbeICMP(ctx context.Context, target string, module config.Module, registry *prometheus.Registry) (success bool) { +func ProbeICMP(ctx context.Context, target string, module config.Module, registry *prometheus.Registry, logger log.Logger) (success bool) { var ( socket *icmp.PacketConn requestType icmp.Type @@ -54,7 +54,7 @@ func ProbeICMP(ctx context.Context, target string, module config.Module, registr ip, err := chooseProtocol(module.ICMP.PreferredIPProtocol, target, registry) if err != nil { - log.Warnf("Error resolving address %s: %s", target, err) + level.Warn(logger).Log("msg", "Error resolving address", "err", err) return false } @@ -69,7 +69,7 @@ func ProbeICMP(ctx context.Context, target string, module config.Module, registr } if err != nil { - log.Errorf("Error listening to socket for %s: %s", target, err) + level.Error(logger).Log("msg", "Error listening to socket", "err", err) return } defer socket.Close() @@ -86,11 +86,11 @@ func ProbeICMP(ctx context.Context, target string, module config.Module, registr wb, err := wm.Marshal(nil) if err != nil { - log.Errorf("Error marshalling packet for %s: %s", target, err) + level.Error(logger).Log("msg", "Error marshalling packet", "err", err) return } if _, err = socket.WriteTo(wb, ip); err != nil { - log.Warnf("Error writing to socket for %s: %s", target, err) + level.Warn(logger).Log("msg", "Error writing to socket", "err", err) return } @@ -98,23 +98,23 @@ func ProbeICMP(ctx context.Context, target string, module config.Module, registr wm.Type = replyType wb, err = wm.Marshal(nil) if err != nil { - log.Errorf("Error marshalling packet for %s: %s", target, err) + level.Error(logger).Log("msg", "Error marshalling packet", "err", err) return } rb := make([]byte, 1500) if err := socket.SetReadDeadline(deadline); err != nil { - log.Errorf("Error setting socket deadline for %s: %s", target, err) + level.Error(logger).Log("msg", "Error setting socket deadline", "err", err) return } for { n, peer, err := socket.ReadFrom(rb) if err != nil { if nerr, ok := err.(net.Error); ok && nerr.Timeout() { - log.Warnf("Timeout reading from socket for %s: %s", target, err) + level.Warn(logger).Log("msg", "Timeout reading from socket for", "err", err) return } - log.Errorf("Error reading from socket for %s: %s", target, err) + level.Error(logger).Log("msg", "Error reading from socket", "err", err) continue } if peer.String() != ip.String() { diff --git a/prober/prober.go b/prober/prober.go index c3a5fe8..8b18a09 100644 --- a/prober/prober.go +++ b/prober/prober.go @@ -3,9 +3,10 @@ package prober import ( "context" + "github.com/go-kit/kit/log" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/blackbox_exporter/config" ) -type ProbeFn func(ctx context.Context, target string, config config.Module, registry *prometheus.Registry) bool +type ProbeFn func(ctx context.Context, target string, config config.Module, registry *prometheus.Registry, logger log.Logger) bool diff --git a/prober/tcp.go b/prober/tcp.go index 74c9356..e5bf716 100644 --- a/prober/tcp.go +++ b/prober/tcp.go @@ -21,25 +21,26 @@ import ( "net" "regexp" + "github.com/go-kit/kit/log" + "github.com/go-kit/kit/log/level" "github.com/prometheus/client_golang/prometheus" pconfig "github.com/prometheus/common/config" - "github.com/prometheus/common/log" "github.com/prometheus/blackbox_exporter/config" ) -func dialTCP(ctx context.Context, target string, module config.Module, registry *prometheus.Registry) (net.Conn, error) { +func dialTCP(ctx context.Context, target string, module config.Module, registry *prometheus.Registry, logger log.Logger) (net.Conn, error) { var dialProtocol, dialTarget string dialer := &net.Dialer{} targetAddress, port, err := net.SplitHostPort(target) if err != nil { - log.Errorf("Error splitting target address and port: %v", err) + level.Error(logger).Log("msg", "Error splitting target address and port", "err", err) return nil, err } ip, err := chooseProtocol(module.TCP.PreferredIPProtocol, targetAddress, registry) if err != nil { - log.Errorf("Error choosing protocol: %v", err) + level.Error(logger).Log("msg", "Error resolving address", "err", err) return nil, err } @@ -55,7 +56,7 @@ func dialTCP(ctx context.Context, target string, module config.Module, registry } tlsConfig, err := pconfig.NewTLSConfig(&module.TCP.TLSConfig) if err != nil { - log.Errorf("Error creating TLS configuration: %v", err) + level.Error(logger).Log("msg", "Error creating TLS configuration", "err", err) return nil, err } timeoutDeadline, _ := ctx.Deadline() @@ -64,7 +65,7 @@ func dialTCP(ctx context.Context, target string, module config.Module, registry return tls.DialWithDialer(dialer, dialProtocol, dialTarget, tlsConfig) } -func ProbeTCP(ctx context.Context, target string, module config.Module, registry *prometheus.Registry) bool { +func ProbeTCP(ctx context.Context, target string, module config.Module, registry *prometheus.Registry, logger log.Logger) bool { probeSSLEarliestCertExpiry := prometheus.NewGauge(prometheus.GaugeOpts{ Name: "probe_ssl_earliest_cert_expiry", Help: "Returns earliest SSL cert expiry date", @@ -75,9 +76,9 @@ func ProbeTCP(ctx context.Context, target string, module config.Module, registry }) registry.MustRegister(probeFailedDueToRegex) deadline, _ := ctx.Deadline() - conn, err := dialTCP(ctx, target, module, registry) + conn, err := dialTCP(ctx, target, module, registry, logger) if err != nil { - log.Errorf("Error dialing TCP: %v", err) + level.Error(logger).Log("msg", "Error dialing TCP", "err", err) return false } defer conn.Close() @@ -86,7 +87,7 @@ func ProbeTCP(ctx context.Context, target string, module config.Module, registry // If a deadline cannot be set, better fail the probe by returning an error // now rather than blocking forever. if err := conn.SetDeadline(deadline); err != nil { - log.Errorf("Error setting deadline: %v", err) + level.Error(logger).Log("msg", "Error setting deadline", "err", err) return false } if module.TCP.TLS { @@ -95,27 +96,27 @@ func ProbeTCP(ctx context.Context, target string, module config.Module, registry probeSSLEarliestCertExpiry.Set(float64(getEarliestCertExpiry(&state).UnixNano()) / 1e9) } scanner := bufio.NewScanner(conn) - for _, qr := range module.TCP.QueryResponse { - log.Debugf("Processing query response entry %+v", qr) + for i, qr := range module.TCP.QueryResponse { + level.Debug(logger).Log("msg", "Processing query response entry", "entry_number", i) send := qr.Send if qr.Expect != "" { re, err := regexp.Compile(qr.Expect) if err != nil { - log.Errorf("Could not compile %q into regular expression: %v", qr.Expect, err) + level.Error(logger).Log("msg", "Could not compile into regular expression", "regexp", qr.Expect, "err", err) return false } var match []int // Read lines until one of them matches the configured regexp. for scanner.Scan() { - log.Debugf("read %q\n", scanner.Text()) + level.Debug(logger).Log("msg", "Read line", "line", scanner.Text()) match = re.FindSubmatchIndex(scanner.Bytes()) if match != nil { - log.Debugf("regexp %q matched %q", re, scanner.Text()) + level.Debug(logger).Log("msg", "Regexp matched", "regexp", re, "line", scanner.Text()) break } } if scanner.Err() != nil { - log.Errorf("Error reading from connection: %v", scanner.Err().Error()) + level.Error(logger).Log("msg", "Error reading from connection", "err", scanner.Err().Error()) return false } if match == nil { @@ -126,7 +127,7 @@ func ProbeTCP(ctx context.Context, target string, module config.Module, registry send = string(re.Expand(nil, []byte(send), scanner.Bytes(), match)) } if send != "" { - log.Debugf("Sending %q", send) + level.Debug(logger).Log("msg", "Sending %q", send) if _, err := fmt.Fprintf(conn, "%s\n", send); err != nil { return false } diff --git a/prober/tcp_test.go b/prober/tcp_test.go index 4e72099..aa63d2e 100644 --- a/prober/tcp_test.go +++ b/prober/tcp_test.go @@ -21,6 +21,7 @@ import ( "testing" "time" + "github.com/go-kit/kit/log" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/blackbox_exporter/config" @@ -45,7 +46,7 @@ func TestTCPConnection(t *testing.T) { testCTX, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() registry := prometheus.NewRegistry() - if !ProbeTCP(testCTX, ln.Addr().String(), config.Module{}, registry) { + if !ProbeTCP(testCTX, ln.Addr().String(), config.Module{}, registry, log.NewNopLogger()) { t.Fatalf("TCP module failed, expected success.") } <-ch @@ -56,7 +57,7 @@ func TestTCPConnectionFails(t *testing.T) { registry := prometheus.NewRegistry() testCTX, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() - if ProbeTCP(testCTX, ":0", config.Module{}, registry) { + if ProbeTCP(testCTX, ":0", config.Module{}, registry, log.NewNopLogger()) { t.Fatalf("TCP module suceeded, expected failure.") } } @@ -96,7 +97,7 @@ func TestTCPConnectionQueryResponseIRC(t *testing.T) { ch <- struct{}{} }() registry := prometheus.NewRegistry() - if !ProbeTCP(testCTX, ln.Addr().String(), module, registry) { + if !ProbeTCP(testCTX, ln.Addr().String(), module, registry, log.NewNopLogger()) { t.Fatalf("TCP module failed, expected success.") } <-ch @@ -115,7 +116,7 @@ func TestTCPConnectionQueryResponseIRC(t *testing.T) { ch <- struct{}{} }() registry = prometheus.NewRegistry() - if ProbeTCP(testCTX, ln.Addr().String(), module, registry) { + if ProbeTCP(testCTX, ln.Addr().String(), module, registry, log.NewNopLogger()) { t.Fatalf("TCP module succeeded, expected failure.") } mfs, err := registry.Gather() @@ -164,7 +165,7 @@ func TestTCPConnectionQueryResponseMatching(t *testing.T) { ch <- version }() registry := prometheus.NewRegistry() - if !ProbeTCP(testCTX, ln.Addr().String(), module, registry) { + if !ProbeTCP(testCTX, ln.Addr().String(), module, registry, log.NewNopLogger()) { t.Fatalf("TCP module failed, expected success.") } if got, want := <-ch, "OpenSSH_6.9p1"; got != want { @@ -212,7 +213,7 @@ func TestTCPConnectionProtocol(t *testing.T) { } registry := prometheus.NewRegistry() - result := ProbeTCP(testCTX, net.JoinHostPort("localhost", port), module, registry) + result := ProbeTCP(testCTX, net.JoinHostPort("localhost", port), module, registry, log.NewNopLogger()) if !result { t.Fatalf("TCP protocol: \"tcp4\" connection test failed, expected success.") } @@ -231,7 +232,7 @@ func TestTCPConnectionProtocol(t *testing.T) { } registry = prometheus.NewRegistry() - result = ProbeTCP(testCTX, net.JoinHostPort("localhost", port), module, registry) + result = ProbeTCP(testCTX, net.JoinHostPort("localhost", port), module, registry, log.NewNopLogger()) if !result { t.Fatalf("TCP protocol: \"tcp6\" connection test failed, expected success.") } @@ -252,7 +253,7 @@ func TestTCPConnectionProtocol(t *testing.T) { } registry = prometheus.NewRegistry() - result = ProbeTCP(testCTX, net.JoinHostPort("localhost", port), module, registry) + result = ProbeTCP(testCTX, net.JoinHostPort("localhost", port), module, registry, log.NewNopLogger()) if !result { t.Fatalf("TCP protocol: \"tcp\", prefer: \"ip4\" connection test failed, expected success.") } @@ -273,7 +274,7 @@ func TestTCPConnectionProtocol(t *testing.T) { } registry = prometheus.NewRegistry() - result = ProbeTCP(testCTX, net.JoinHostPort("localhost", port), module, registry) + result = ProbeTCP(testCTX, net.JoinHostPort("localhost", port), module, registry, log.NewNopLogger()) if !result { t.Fatalf("TCP protocol: \"tcp\", prefer: \"ip6\" connection test failed, expected success.") } @@ -292,7 +293,7 @@ func TestTCPConnectionProtocol(t *testing.T) { } registry = prometheus.NewRegistry() - result = ProbeTCP(testCTX, net.JoinHostPort("localhost", port), module, registry) + result = ProbeTCP(testCTX, net.JoinHostPort("localhost", port), module, registry, log.NewNopLogger()) if !result { t.Fatalf("TCP protocol: \"tcp\" connection test failed, expected success.") } @@ -311,7 +312,7 @@ func TestTCPConnectionProtocol(t *testing.T) { } registry = prometheus.NewRegistry() - result = ProbeTCP(testCTX, net.JoinHostPort("localhost", port), module, registry) + result = ProbeTCP(testCTX, net.JoinHostPort("localhost", port), module, registry, log.NewNopLogger()) if !result { t.Fatalf("TCP connection test with protocol unspecified failed, expected success.") } @@ -350,7 +351,7 @@ func TestPrometheusTimeoutTCP(t *testing.T) { Expect: "SSH-2.0-(OpenSSH_6.9p1) Debian-2", }, }, - }}, registry) { + }}, registry, log.NewNopLogger()) { t.Fatalf("TCP module succeeded, expected timeout failure.") } <-ch -- 2.25.1