Skip to content

Commit

Permalink
feat: add check base struct to latency check
Browse files Browse the repository at this point in the history
  • Loading branch information
lvlcn-t committed Jan 8, 2024
1 parent 03c2fdb commit 3f1e7c4
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 36 deletions.
75 changes: 44 additions & 31 deletions pkg/checks/latency.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,33 +38,38 @@ import (

var _ Check = (*Latency)(nil)

// Latency is a check that measures the latency to an endpoint
type Latency struct {
CheckBase
config LatencyConfig
metrics latencyMetrics
}

// NewLatencyCheck creates a new instance of the latency check
func NewLatencyCheck() Check {
return &Latency{
mu: sync.Mutex{},
cfg: LatencyConfig{},
c: nil,
done: make(chan bool, 1),
client: &http.Client{},
CheckBase: CheckBase{
mu: sync.Mutex{},
cResult: nil,
done: make(chan bool, 1),
client: &http.Client{},
},
config: LatencyConfig{
Retry: DefaultRetry,
},
metrics: newLatencyMetrics(),
}
}

type Latency struct {
cfg LatencyConfig
mu sync.Mutex
c chan<- Result
done chan bool
client *http.Client
metrics latencyMetrics
}

// LatencyConfig defines the configuration parameters for a latency check
type LatencyConfig struct {
Targets []string
Interval time.Duration
Timeout time.Duration
Retry helper.RetryConfig
}

// LatencyResult represents the result of a single latency check for a specific target
type LatencyResult struct {
Code int `json:"code"`
Error *string `json:"error"`
Expand All @@ -78,11 +83,12 @@ type latencyMetrics struct {
latencyHistogram *prometheus.HistogramVec
}

// Run starts the latency check
func (l *Latency) Run(ctx context.Context) error {
ctx, cancel := logger.NewContextWithLogger(ctx, "latency")
defer cancel()
log := logger.FromContext(ctx)
log.Info(fmt.Sprintf("Using latency check interval of %s", l.cfg.Interval.String()))
log.Info(fmt.Sprintf("Using latency check interval of %s", l.config.Interval.String()))

for {
select {
Expand All @@ -91,16 +97,17 @@ func (l *Latency) Run(ctx context.Context) error {
return ctx.Err()
case <-l.done:
return nil
case <-time.After(l.cfg.Interval):
results := l.check(ctx)
case <-time.After(l.config.Interval):
res := l.check(ctx)
errval := ""
checkResult := Result{
Data: results,
r := Result{
Data: res,
Err: errval,
Timestamp: time.Now(),
}

l.c <- checkResult
l.cResult <- r
log.Debug("Successfully finished latency check run")
}
}
}
Expand All @@ -109,7 +116,7 @@ func (l *Latency) Startup(ctx context.Context, cResult chan<- Result) error {
log := logger.FromContext(ctx).WithGroup("latency")
log.Debug("Starting latency check")

l.c = cResult
l.cResult = cResult
return nil
}

Expand All @@ -122,15 +129,14 @@ func (l *Latency) Shutdown(_ context.Context) error {

func (l *Latency) SetConfig(_ context.Context, config any) error {
var c LatencyConfig
err := mapstructure.Decode(config, &c)
if err != nil {
if err := mapstructure.Decode(config, &c); err != nil {
return ErrInvalidConfig
}
c.Interval = time.Second * c.Interval
c.Retry.Delay = time.Second * c.Retry.Delay
c.Interval *= time.Second
c.Retry.Delay *= time.Second
l.mu.Lock()
defer l.mu.Unlock()
l.cfg = c
l.config = c

return nil
}
Expand All @@ -142,18 +148,23 @@ func (l *Latency) SetClient(c *http.Client) {
l.client = c
}

// Schema provides the schema of the data that will be provided
// by the latency check
func (l *Latency) Schema() (*openapi3.SchemaRef, error) {
return OpenapiFromPerfData(make(map[string]LatencyResult))
}

// RegisterHandler registers a server handler
func (l *Latency) RegisterHandler(_ context.Context, router *api.RoutingTree) {
router.Add(http.MethodGet, "v1alpha1/latency", l.Handler)
}

// DeregisterHandler deletes the server handler
func (l *Latency) DeregisterHandler(_ context.Context, router *api.RoutingTree) {
router.Remove(http.MethodGet, "v1alpha1/latency")
}

// Handler defines the server handler for the latency check
func (l *Latency) Handler(w http.ResponseWriter, _ *http.Request) {
w.WriteHeader(http.StatusOK)
}
Expand Down Expand Up @@ -201,23 +212,25 @@ func (h *Latency) GetMetricCollectors() []prometheus.Collector {
}
}

// check performs a latency check using a retry function
// to get the latency to all targets
func (l *Latency) check(ctx context.Context) map[string]LatencyResult {
log := logger.FromContext(ctx).WithGroup("check")
log.Debug("Checking latency")
if len(l.cfg.Targets) == 0 {
if len(l.config.Targets) == 0 {
log.Debug("No targets defined")
return map[string]LatencyResult{}
}
log.Debug("Getting latency status for each target in separate routine", "amount", len(l.cfg.Targets))
log.Debug("Getting latency status for each target in separate routine", "amount", len(l.config.Targets))

var mu sync.Mutex
var wg sync.WaitGroup
results := map[string]LatencyResult{}

l.mu.Lock()
l.client.Timeout = l.cfg.Timeout * time.Second
l.client.Timeout = l.config.Timeout * time.Second
l.mu.Unlock()
for _, t := range l.cfg.Targets {
for _, t := range l.config.Targets {
target := t
wg.Add(1)
lo := log.With("target", target)
Expand All @@ -229,7 +242,7 @@ func (l *Latency) check(ctx context.Context) map[string]LatencyResult {
results[target] = res

return nil
}, l.cfg.Retry)
}, l.config.Retry)

go func() {
defer wg.Done()
Expand Down
14 changes: 9 additions & 5 deletions pkg/checks/latency_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -291,8 +291,10 @@ func TestLatency_check(t *testing.T) {
}

l := &Latency{
cfg: LatencyConfig{Targets: tt.targets, Interval: time.Second * 120, Timeout: time.Second * 1},
client: &http.Client{Transport: httpmock.DefaultTransport},
CheckBase: CheckBase{
client: &http.Client{},
},
config: LatencyConfig{Targets: tt.targets, Interval: time.Second * 120, Timeout: time.Second * 1},
metrics: newLatencyMetrics(),
}

Expand Down Expand Up @@ -333,7 +335,9 @@ func TestLatency_Startup(t *testing.T) {
func TestLatency_Shutdown(t *testing.T) {
cDone := make(chan bool, 1)
c := Latency{
done: cDone,
CheckBase: CheckBase{
done: cDone,
},
}
err := c.Shutdown(context.Background())
if err != nil {
Expand All @@ -355,8 +359,8 @@ func TestLatency_SetConfig(t *testing.T) {
if err != nil {
t.Errorf("SetConfig() error = %v", err)
}
if !reflect.DeepEqual(c.cfg, wantCfg) {
t.Errorf("SetConfig() = %v, want %v", c.cfg, wantCfg)
if !reflect.DeepEqual(c.config, wantCfg) {
t.Errorf("SetConfig() = %v, want %v", c.config, wantCfg)
}
}

Expand Down

0 comments on commit 3f1e7c4

Please sign in to comment.