Skip to content

Commit

Permalink
Route browser checks to the browser prober (#780)
Browse files Browse the repository at this point in the history
Make sure that validate works for all check types, and make sure all
check types have at least a trivial test.

Make sure the probe factory knows how to create checks for all defined
types.

Follow-up-to: 9730c0b
Follow-up-to: db349fd

Signed-off-by: Marcelo E. Magallon <[email protected]>
  • Loading branch information
mem authored Jul 8, 2024
1 parent 7b9b351 commit ed93cf8
Show file tree
Hide file tree
Showing 6 changed files with 237 additions and 150 deletions.
19 changes: 4 additions & 15 deletions internal/checks/checks.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"google.golang.org/grpc/status"

logproto "github.com/grafana/loki/pkg/push"
"github.com/grafana/synthetic-monitoring-agent/internal/error_types"
"github.com/grafana/synthetic-monitoring-agent/internal/feature"
"github.com/grafana/synthetic-monitoring-agent/internal/k6runner"
"github.com/grafana/synthetic-monitoring-agent/internal/limits"
Expand All @@ -34,23 +35,11 @@ import (
sm "github.com/grafana/synthetic-monitoring-agent/pkg/pb/synthetic_monitoring"
)

type Error string
type Error = error_types.BasicError

func (e Error) Error() string { return string(e) }
type TransientError = error_types.TransientError

// TransientError is an error that can be recovered.
type TransientError Error

func (e TransientError) Error() string { return string(e) }

var _ error = TransientError("")

// FatalError is an error that causes the program to terminate.
type FatalError Error

func (e FatalError) Error() string { return string(e) }

var _ error = FatalError("")
type FatalError = error_types.FatalError

const (
errCapabilityK6Missing = FatalError("k6 is required for scripted check support - configure k6 or edit probe capabilities in the SM app")
Expand Down
22 changes: 22 additions & 0 deletions internal/error_types/error_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package error_types

// BasicError is an error for which we have no additional information.
type BasicError string

func (e BasicError) Error() string { return string(e) }

var _ error = BasicError("")

// TransientError is an error that can be recovered.
type TransientError BasicError

func (e TransientError) Error() string { return string(e) }

var _ error = TransientError("")

// FatalError is an error that causes the program to terminate.
type FatalError BasicError

func (e FatalError) Error() string { return string(e) }

var _ error = FatalError("")
17 changes: 16 additions & 1 deletion internal/prober/prober.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ import (
"fmt"
"net/http"

"github.com/grafana/synthetic-monitoring-agent/internal/error_types"
"github.com/grafana/synthetic-monitoring-agent/internal/k6runner"
"github.com/grafana/synthetic-monitoring-agent/internal/model"
"github.com/grafana/synthetic-monitoring-agent/internal/prober/browser"
"github.com/grafana/synthetic-monitoring-agent/internal/prober/dns"
"github.com/grafana/synthetic-monitoring-agent/internal/prober/grpc"
httpProber "github.com/grafana/synthetic-monitoring-agent/internal/prober/http"
Expand All @@ -21,6 +23,8 @@ import (
"github.com/rs/zerolog"
)

const unsupportedCheckType = error_types.BasicError("unsupported check type")

type Prober interface {
Name() string
Probe(ctx context.Context, target string, registry *prometheus.Registry, logger logger.Logger) bool
Expand Down Expand Up @@ -83,6 +87,17 @@ func (f proberFactory) New(ctx context.Context, logger zerolog.Logger, check mod
err = fmt.Errorf("k6 checks are not enabled")
}

case sm.CheckTypeBrowser:
// TODO(mem): we possibly need to extend the validation so that
// we know that the runner is actually able to handle browser
// checks.
if f.runner != nil {
p, err = browser.NewProber(ctx, check.Check, logger, f.runner)
target = check.Target
} else {
err = fmt.Errorf("k6 checks are not enabled")
}

case sm.CheckTypeMultiHttp:
if f.runner != nil {
reservedHeaders := f.getReservedHeaders(&check)
Expand All @@ -97,7 +112,7 @@ func (f proberFactory) New(ctx context.Context, logger zerolog.Logger, check mod
target = check.Target

default:
return nil, "", fmt.Errorf("unsupported check type")
return nil, "", unsupportedCheckType
}

return p, target, err
Expand Down
27 changes: 27 additions & 0 deletions internal/prober/prober_test.go
Original file line number Diff line number Diff line change
@@ -1 +1,28 @@
package prober

import (
"context"
"testing"

"github.com/grafana/synthetic-monitoring-agent/internal/model"
sm "github.com/grafana/synthetic-monitoring-agent/pkg/pb/synthetic_monitoring"
"github.com/rs/zerolog"
"github.com/stretchr/testify/require"
)

func TestProberFactoryCoverage(t *testing.T) {
// This test will assert that the prober factory is handling all the
// known check types (as defined in the synthetic_monitoring package).

pf := NewProberFactory(nil, 0)
ctx := context.Background()
testLogger := zerolog.New(zerolog.NewTestWriter(t))

for _, checkType := range sm.CheckTypeValues() {
var check model.Check
require.NoError(t, check.FromSM(sm.GetCheckInstance(checkType)))

_, _, err := pf.New(ctx, testLogger, check)
require.NotErrorIs(t, err, unsupportedCheckType)
}
}
136 changes: 136 additions & 0 deletions pkg/pb/synthetic_monitoring/checks_extra.go
Original file line number Diff line number Diff line change
Expand Up @@ -1440,3 +1440,139 @@ func validateTimeout(checkType CheckType, timeout, frequency int64) error {
func inClosedRange[T constraints.Ordered](v, lower, upper T) bool {
return v >= lower && v <= upper
}

func GetCheckInstance(checkType CheckType) Check {
var validCheckCases = map[CheckType]Check{
CheckTypeDns: {
Id: 1,
TenantId: 1,
Target: "www.example.org",
Job: "job",
Frequency: 1000,
Timeout: 1000,
Probes: []int64{1},
Settings: CheckSettings{
Dns: &DnsSettings{
Server: "127.0.0.1",
},
},
},
CheckTypeHttp: {
Id: 1,
TenantId: 1,
Target: "http://www.example.org",
Job: "job",
Frequency: 1000,
Timeout: 1000,
Probes: []int64{1},
Settings: CheckSettings{
Http: &HttpSettings{},
},
},
CheckTypePing: {
Id: 1,
TenantId: 1,
Target: "127.0.0.1",
Job: "job",
Frequency: 1000,
Timeout: 1000,
Probes: []int64{1},
Settings: CheckSettings{
Ping: &PingSettings{},
},
},
CheckTypeTcp: {
Id: 1,
TenantId: 1,
Target: "127.0.0.1:9000",
Job: "job",
Frequency: 1000,
Timeout: 1000,
Probes: []int64{1},
Settings: CheckSettings{
Tcp: &TcpSettings{},
},
},
CheckTypeTraceroute: {
Id: 1,
TenantId: 1,
Target: "127.0.0.1",
Job: "job",
Frequency: 120000,
Timeout: 30000,
Probes: []int64{1},
Settings: CheckSettings{
Traceroute: &TracerouteSettings{},
},
},
CheckTypeScripted: {
Id: 1,
TenantId: 1,
Target: "http://www.example.org",
Job: "job",
Frequency: 60000,
Timeout: 10000,
Probes: []int64{1},
Settings: CheckSettings{
Scripted: &ScriptedSettings{
Script: []byte("// test"),
},
},
},
CheckTypeMultiHttp: {
Id: 1,
TenantId: 1,
Target: "http://www.example.org",
Job: "job",
Frequency: 60000,
Timeout: 10000,
Probes: []int64{1},
Settings: CheckSettings{
Multihttp: &MultiHttpSettings{
Entries: []*MultiHttpEntry{
{
Request: &MultiHttpEntryRequest{
Method: HttpMethod_GET,
Url: "http://www.example.org/",
},
},
},
},
},
},
CheckTypeGrpc: {
Id: 1,
TenantId: 1,
Target: "127.0.0.1:9000",
Job: "job",
Frequency: 60000,
Timeout: 10000,
Probes: []int64{1},
Settings: CheckSettings{
Grpc: &GrpcSettings{},
},
},
CheckTypeBrowser: {
Id: 1,
TenantId: 1,
Target: "http://www.example.org",
Job: "job",
Frequency: 60000,
Timeout: 10000,
Probes: []int64{1},
Settings: CheckSettings{
Browser: &BrowserSettings{
Script: []byte("// test"),
},
},
},
}

instance, known := validCheckCases[checkType]

if !known {
panic("unknown check type")
}

return instance
}
Loading

0 comments on commit ed93cf8

Please sign in to comment.