tailscale/prober/dns_example_test.go
Anton Tolchanov 5336362e64 prober: export probe class and metrics from bandwidth prober
- Wrap each prober function into a probe class that allows associating
  metric labels and custom metrics with a given probe;
- Make sure all existing probe classes set a `class` metric label;
- Move bandwidth probe size from being a metric label to a separate
  gauge metric; this will make it possible to use it to calculate
  average used bandwidth using a PromQL query;
- Also export transfer time for the bandwidth prober (more accurate than
  the total probe time, since it excludes connection establishment
  time).

Updates tailscale/corp#17912

Signed-off-by: Anton Tolchanov <anton@tailscale.com>
2024-04-08 12:02:58 +01:00

102 lines
2.3 KiB
Go

// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
package prober_test
import (
"context"
"flag"
"fmt"
"log"
"net"
"net/netip"
"os"
"os/signal"
"time"
"tailscale.com/prober"
"tailscale.com/types/logger"
)
const (
every30s = 30 * time.Second
)
var (
hostname = flag.String("hostname", "tailscale.com", "hostname to probe")
oneshot = flag.Bool("oneshot", true, "run probes once and exit")
verbose = flag.Bool("verbose", false, "enable verbose logging")
)
// This example demonstrates how to use ForEachAddr to create a TLS probe for
// each IP address in the DNS record of a given hostname.
func ExampleForEachAddr() {
flag.Parse()
p := prober.New().WithSpread(true)
if *oneshot {
p = p.WithOnce(true)
}
// This function is called every time we discover a new IP address to check.
makeTLSProbe := func(addr netip.Addr) []*prober.Probe {
pf := prober.TLSWithIP(*hostname, netip.AddrPortFrom(addr, 443))
if *verbose {
logger := logger.WithPrefix(log.Printf, fmt.Sprintf("[tls %s]: ", addr))
pf = probeLogWrapper(logger, pf)
}
probe := p.Run(fmt.Sprintf("website/%s/tls", addr), every30s, nil, pf)
return []*prober.Probe{probe}
}
// Determine whether to use IPv4 or IPv6 based on whether we can create
// an IPv6 listening socket on localhost.
sock, err := net.Listen("tcp", "[::1]:0")
supportsIPv6 := err == nil
if sock != nil {
sock.Close()
}
networks := []string{"ip4"}
if supportsIPv6 {
networks = append(networks, "ip6")
}
var vlogf logger.Logf = logger.Discard
if *verbose {
vlogf = log.Printf
}
// This is the outer probe that resolves the hostname and creates a new
// TLS probe for each IP.
p.Run("website/dns", every30s, nil, prober.ForEachAddr(*hostname, makeTLSProbe, prober.ForEachAddrOpts{
Logf: vlogf,
Networks: networks,
}))
defer log.Printf("done")
// Wait until all probes have run if we're running in oneshot mode.
if *oneshot {
p.Wait()
return
}
// Otherwise, wait until we get a signal.
sigCh := make(chan os.Signal, 1)
signal.Notify(sigCh, os.Interrupt)
<-sigCh
}
func probeLogWrapper(logf logger.Logf, pc prober.ProbeClass) prober.ProbeClass {
return prober.ProbeClass{
Probe: func(ctx context.Context) error {
logf("starting probe")
err := pc.Probe(ctx)
logf("probe finished with %v", err)
return err
},
}
}