github.com/grafana/synthetic-monitoring-agent@v0.64.2/internal/prober/icmp/icmp.go (about)

     1  package icmp
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"sync"
     7  	"time"
     8  
     9  	"github.com/go-kit/log"
    10  	"github.com/grafana/synthetic-monitoring-agent/internal/model"
    11  	"github.com/grafana/synthetic-monitoring-agent/internal/prober/logger"
    12  	sm "github.com/grafana/synthetic-monitoring-agent/pkg/pb/synthetic_monitoring"
    13  	"github.com/prometheus/blackbox_exporter/config"
    14  	"github.com/prometheus/client_golang/prometheus"
    15  )
    16  
    17  var errUnsupportedCheck = errors.New("unsupported check")
    18  
    19  type Module struct {
    20  	Prober            string
    21  	Timeout           time.Duration
    22  	PacketCount       int64
    23  	ReqSuccessCount   int64
    24  	MaxResolveRetries int64
    25  	ICMP              config.ICMPProbe
    26  	Privileged        bool
    27  }
    28  
    29  type Prober struct {
    30  	config Module
    31  }
    32  
    33  func NewProber(check model.Check) (Prober, error) {
    34  	var p Prober
    35  
    36  	if check.Settings.Ping == nil {
    37  		return p, errUnsupportedCheck
    38  	}
    39  
    40  	p.config = settingsToModule(check.Settings.Ping)
    41  	p.config.Timeout = time.Duration(check.Timeout) * time.Millisecond
    42  	p.config.Privileged = isPrivilegedRequired()
    43  
    44  	return p, nil
    45  }
    46  
    47  func (p Prober) Name() string {
    48  	return "ping"
    49  }
    50  
    51  func (p Prober) Probe(ctx context.Context, target string, registry *prometheus.Registry, l logger.Logger, _ string) (bool, float64) {
    52  	return probeICMP(ctx, target, p.config, registry, l)
    53  }
    54  
    55  func settingsToModule(settings *sm.PingSettings) Module {
    56  	var m Module
    57  
    58  	m.Prober = sm.CheckTypePing.String()
    59  
    60  	m.ICMP.IPProtocol, m.ICMP.IPProtocolFallback = settings.IpVersion.ToIpProtocol()
    61  
    62  	m.ICMP.SourceIPAddress = settings.SourceIpAddress
    63  
    64  	m.ICMP.PayloadSize = int(settings.PayloadSize)
    65  
    66  	m.ICMP.DontFragment = settings.DontFragment
    67  
    68  	if settings.PacketCount == 0 {
    69  		m.PacketCount = 3
    70  		m.ReqSuccessCount = 1
    71  	} else {
    72  		m.PacketCount = settings.PacketCount
    73  		m.ReqSuccessCount = settings.PacketCount // TODO(mem): expose this setting
    74  	}
    75  
    76  	// TODO(mem): add a setting for this
    77  	m.MaxResolveRetries = 3
    78  
    79  	return m
    80  }
    81  
    82  var (
    83  	privilegedRequired   bool
    84  	privilegedCheckDone  bool
    85  	privilegedCheckMutex sync.Mutex
    86  )
    87  
    88  func isPrivilegedRequired() bool {
    89  	privilegedCheckMutex.Lock()
    90  	defer privilegedCheckMutex.Unlock()
    91  
    92  	if privilegedCheckDone {
    93  		return privilegedRequired
    94  	}
    95  
    96  	var (
    97  		ctx      = context.Background()
    98  		target   = "127.0.0.1"
    99  		registry = prometheus.NewRegistry()
   100  		logger   = log.NewNopLogger()
   101  		config   = Module{
   102  			Prober:      "test-unprivileged",
   103  			Timeout:     1 * time.Second,
   104  			PacketCount: 1,
   105  			Privileged:  false,
   106  			ICMP: config.ICMPProbe{
   107  				IPProtocol: "ip4",
   108  			},
   109  		}
   110  	)
   111  
   112  	success, _ := probeICMP(ctx, target, config, registry, logger)
   113  
   114  	privilegedRequired = !success
   115  	privilegedCheckDone = true
   116  
   117  	return privilegedRequired
   118  }