Skip to content

Commit

Permalink
Add multihttp check type
Browse files Browse the repository at this point in the history
This supports the multihttp check type. It's not yet connected to the
API (i.e. it might receive a multihttp check from the API but it won't
run it).

Signed-off-by: Marcelo E. Magallon <marcelo.magallon@grafana.com>
  • Loading branch information
mem committed May 18, 2023
1 parent 4c25c8e commit 0f17bab
Show file tree
Hide file tree
Showing 11 changed files with 1,233 additions and 0 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ require (
github.com/go-ping/ping v1.1.0
github.com/gogo/status v1.1.1
github.com/jpillora/backoff v1.0.0
github.com/mccutchen/go-httpbin/v2 v2.8.0
github.com/quasilyte/go-ruleguard/dsl v0.3.22
kernel.org/pub/linux/libs/security/libcap/cap v1.2.68
)
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp9
github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
github.com/mccutchen/go-httpbin/v2 v2.8.0 h1:5Ld/mII532zWV6Dn9UpOUZebfD8chkYmx3UIW3VZET8=
github.com/mccutchen/go-httpbin/v2 v2.8.0/go.mod h1:+DBHcmg6EOeoizuiOI8iL12VIHXx+9YQNlz+gjB9uxk=
github.com/miekg/dns v1.1.54 h1:5jon9mWcb0sFJGpnI99tOMhCPyJ+RPVz5b63MQG0VWI=
github.com/miekg/dns v1.1.54/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY=
github.com/mmcloughlin/geohash v0.10.0 h1:9w1HchfDfdeLc+jFEf/04D27KP7E2QmpDu52wPbJWRE=
Expand Down
8 changes: 8 additions & 0 deletions internal/checks/checks.go
Original file line number Diff line number Diff line change
Expand Up @@ -794,6 +794,14 @@ func (c *Updater) addAndStartScraperWithLock(ctx context.Context, check sm.Check
return nil
}

case sm.CheckTypeMultiHttp:
// This is correct, MultiHttp is a K6 check. We probably want
// to abstrct this by adding a function to the settings that
// returns whether the check requires k6 or not.
if !c.features.IsSet(feature.K6) {
return nil
}

default:
}

Expand Down
74 changes: 74 additions & 0 deletions internal/prober/multihttp/multihttp.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package multihttp

import (
"context"
"errors"
"time"

"github.com/grafana/synthetic-monitoring-agent/internal/prober/logger"
sm "github.com/grafana/synthetic-monitoring-agent/pkg/pb/synthetic_monitoring"
"github.com/prometheus/client_golang/prometheus"
"github.com/rs/zerolog"
)

const proberName = "multi_http"

var errUnsupportedCheck = errors.New("unsupported check")

type Module struct {
Prober string
Timeout time.Duration
}

type Prober struct {
logger zerolog.Logger
config Module
runner *runner
}

func NewProber(ctx context.Context, check sm.Check, logger zerolog.Logger) (Prober, error) {
var p Prober

if check.Settings.Multihttp == nil {
return p, errUnsupportedCheck
}

if err := check.Settings.Multihttp.Validate(); err != nil {
return p, err
}

p.config = settingsToModule(check.Settings.Multihttp)
p.config.Timeout = time.Duration(check.Timeout) * time.Millisecond

r, err := newRunner(check.Settings.Multihttp)
if err != nil {
return p, err
}

p.runner = r
p.logger = logger

return p, nil
}

func (p Prober) Name() string {
return proberName
}

func (p Prober) Probe(ctx context.Context, target string, registry *prometheus.Registry, logger logger.Logger) bool {
err := p.runner.Run(ctx, registry, logger, p.logger)
if err != nil {
p.logger.Warn().Err(err).Msg("running probe")
return false
}

return true
}

func settingsToModule(settings *sm.MultiHttpSettings) Module {
var m Module

m.Prober = sm.CheckTypeMultiHttp.String()

return m
}
100 changes: 100 additions & 0 deletions internal/prober/multihttp/multihttp_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package multihttp

import (
"context"
"testing"
"time"

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

func TestNewProber(t *testing.T) {
ctx, cancel := testContext(t)
t.Cleanup(cancel)

logger := zerolog.New(zerolog.NewTestWriter(t))

testcases := map[string]struct {
check synthetic_monitoring.Check
expectFailure bool
}{
"valid": {
expectFailure: false,
check: synthetic_monitoring.Check{
Target: "http://www.example.org",
Job: "test",
Frequency: 10 * 1000,
Timeout: 10 * 1000,
Probes: []int64{1},
Settings: synthetic_monitoring.CheckSettings{
Multihttp: &synthetic_monitoring.MultiHttpSettings{
Entries: []*synthetic_monitoring.MultiHttpEntry{
{
Request: &synthetic_monitoring.MultiHttpEntryRequest{
Url: "http://www.example.org",
},
},
},
},
},
},
},
"settings must be valid": {
expectFailure: true,
check: synthetic_monitoring.Check{
Target: "http://www.example.org",
Job: "test",
Frequency: 10 * 1000,
Timeout: 10 * 1000,
Probes: []int64{1},
Settings: synthetic_monitoring.CheckSettings{
Multihttp: &synthetic_monitoring.MultiHttpSettings{
Entries: []*synthetic_monitoring.MultiHttpEntry{
// This is invalid because the requsest does not have a URL
{},
},
},
},
},
},
"must contain multihttp settings": {
expectFailure: true,
check: synthetic_monitoring.Check{
Target: "http://www.example.org",
Job: "test",
Frequency: 10 * 1000,
Timeout: 10 * 1000,
Probes: []int64{1},
Settings: synthetic_monitoring.CheckSettings{
// The settings are valid for ping, but not for multihttp
Ping: &synthetic_monitoring.PingSettings{},
},
},
},
}

for name, tc := range testcases {
t.Run(name, func(t *testing.T) {
p, err := NewProber(ctx, tc.check, logger)
if tc.expectFailure {
require.Error(t, err)
return
}

require.NoError(t, err)
require.Equal(t, proberName, p.config.Prober)
require.Equal(t, 10*time.Second, p.config.Timeout)
// TODO: check script
})
}
}

func testContext(t *testing.T) (context.Context, func()) {
if deadline, ok := t.Deadline(); ok {
return context.WithDeadline(context.Background(), deadline)
}

return context.WithTimeout(context.Background(), 10*time.Second)
}

0 comments on commit 0f17bab

Please sign in to comment.