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

     1  package prober
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"net/http"
     7  
     8  	"github.com/grafana/synthetic-monitoring-agent/internal/secrets"
     9  
    10  	"github.com/grafana/synthetic-monitoring-agent/internal/error_types"
    11  	"github.com/grafana/synthetic-monitoring-agent/internal/feature"
    12  	"github.com/grafana/synthetic-monitoring-agent/internal/k6runner"
    13  	"github.com/grafana/synthetic-monitoring-agent/internal/model"
    14  	"github.com/grafana/synthetic-monitoring-agent/internal/prober/browser"
    15  	"github.com/grafana/synthetic-monitoring-agent/internal/prober/dns"
    16  	"github.com/grafana/synthetic-monitoring-agent/internal/prober/grpc"
    17  	httpProber "github.com/grafana/synthetic-monitoring-agent/internal/prober/http"
    18  	"github.com/grafana/synthetic-monitoring-agent/internal/prober/icmp"
    19  	"github.com/grafana/synthetic-monitoring-agent/internal/prober/logger"
    20  	"github.com/grafana/synthetic-monitoring-agent/internal/prober/multihttp"
    21  	"github.com/grafana/synthetic-monitoring-agent/internal/prober/scripted"
    22  	"github.com/grafana/synthetic-monitoring-agent/internal/prober/tcp"
    23  	"github.com/grafana/synthetic-monitoring-agent/internal/prober/traceroute"
    24  	sm "github.com/grafana/synthetic-monitoring-agent/pkg/pb/synthetic_monitoring"
    25  	"github.com/prometheus/client_golang/prometheus"
    26  	"github.com/rs/zerolog"
    27  )
    28  
    29  const errUnsupportedCheckType = error_types.BasicError("unsupported check type")
    30  
    31  type Prober interface {
    32  	Name() string
    33  	Probe(ctx context.Context, target string, registry *prometheus.Registry, logger logger.Logger, executionID string) (bool, float64)
    34  }
    35  
    36  func Run(ctx context.Context, p Prober, target string, registry *prometheus.Registry, logger logger.Logger, executionID string) (bool, float64) {
    37  	return p.Probe(ctx, target, registry, logger, executionID)
    38  }
    39  
    40  type ProberFactory interface {
    41  	New(ctx context.Context, logger zerolog.Logger, check model.Check) (Prober, string, error)
    42  }
    43  
    44  type proberFactory struct {
    45  	runner      k6runner.Runner
    46  	probeId     int64
    47  	features    feature.Collection
    48  	secretStore secrets.SecretProvider
    49  }
    50  
    51  func NewProberFactory(runner k6runner.Runner, probeId int64, features feature.Collection, secretStore secrets.SecretProvider) ProberFactory {
    52  	return proberFactory{
    53  		runner:      runner,
    54  		probeId:     probeId,
    55  		features:    features,
    56  		secretStore: secretStore,
    57  	}
    58  }
    59  
    60  func (f proberFactory) New(ctx context.Context, logger zerolog.Logger, check model.Check) (Prober, string, error) {
    61  	var (
    62  		p      Prober
    63  		target string
    64  		err    error
    65  	)
    66  
    67  	switch checkType := check.Type(); checkType {
    68  	case sm.CheckTypePing:
    69  		p, err = icmp.NewProber(check)
    70  		target = check.Target
    71  
    72  	case sm.CheckTypeHttp:
    73  		reservedHeaders := f.getReservedHeaders(&check)
    74  		p, err = httpProber.NewProber(ctx, check, logger, reservedHeaders, f.secretStore)
    75  		target = check.Target
    76  
    77  	case sm.CheckTypeDns:
    78  		if f.features.IsSet(feature.ExperimentalDnsProber) {
    79  			p, err = dns.NewExperimentalProber(check)
    80  		} else {
    81  			p, err = dns.NewProber(check)
    82  		}
    83  
    84  		target = check.Settings.Dns.Server
    85  
    86  	case sm.CheckTypeTcp:
    87  		p, err = tcp.NewProber(ctx, check, logger)
    88  		target = check.Target
    89  
    90  	case sm.CheckTypeTraceroute:
    91  		p, err = traceroute.NewProber(check, logger)
    92  		target = check.Target
    93  
    94  	case sm.CheckTypeScripted:
    95  		if f.runner != nil {
    96  			p, err = scripted.NewProber(ctx, check, logger, f.runner, f.secretStore)
    97  			target = check.Target
    98  		} else {
    99  			err = fmt.Errorf("k6 checks are not enabled")
   100  		}
   101  
   102  	case sm.CheckTypeBrowser:
   103  		// TODO(mem): we possibly need to extend the validation so that
   104  		// we know that the runner is actually able to handle browser
   105  		// checks.
   106  		if f.runner != nil {
   107  			p, err = browser.NewProber(ctx, check, logger, f.runner, f.secretStore)
   108  			target = check.Target
   109  		} else {
   110  			err = fmt.Errorf("k6 checks are not enabled")
   111  		}
   112  
   113  	case sm.CheckTypeMultiHttp:
   114  		if f.runner != nil {
   115  			reservedHeaders := f.getReservedHeaders(&check)
   116  			p, err = multihttp.NewProber(ctx, check, logger, f.runner, reservedHeaders, f.secretStore)
   117  			target = check.Target
   118  		} else {
   119  			err = fmt.Errorf("k6 checks are not enabled")
   120  		}
   121  
   122  	case sm.CheckTypeGrpc:
   123  		p, err = grpc.NewProber(ctx, check, logger)
   124  		target = check.Target
   125  
   126  	default:
   127  		return nil, "", errUnsupportedCheckType
   128  	}
   129  
   130  	return p, target, err
   131  }
   132  
   133  // Build reserved HTTP request headers for applicable checks.
   134  func (f proberFactory) getReservedHeaders(check *model.Check) http.Header {
   135  	reservedHeaders := http.Header{}
   136  
   137  	if f.probeId != 0 {
   138  		checkProbeIdentifier := fmt.Sprintf("%d-%d", check.GlobalID(), f.probeId)
   139  		reservedHeaders.Add("x-sm-id", checkProbeIdentifier)
   140  	}
   141  
   142  	return reservedHeaders
   143  }