Skip to content

Commit

Permalink
feat: simulate latency in extension endpoints
Browse files Browse the repository at this point in the history
  • Loading branch information
ReuDa committed Dec 4, 2023
1 parent 6e56561 commit 16752d9
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 18 deletions.
99 changes: 81 additions & 18 deletions extloadtest/action_log.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/steadybit/extension-kit/extbuild"
"github.com/steadybit/extension-kit/extconversion"
"github.com/steadybit/extension-kit/extutil"
"time"
)

type logAction struct {
Expand All @@ -29,16 +30,20 @@ var (
)

type LogActionState struct {
FormattedMessage string
Error string
ErrorTargetFilter string
TargetName string
FormattedMessage string
ErrorEndpoint string
LatencyEndpoint string
LatencyDuration time.Duration
TargetFilter string
TargetName string
}

type LogActionConfig struct {
Message string
Error string
ErrorTargetFilter string
Message string
ErrorEndpoint string
LatencyEndpoint string
LatencyDuration int64
TargetFilter string
}

func NewLogAction(targetId string, selectionTemplate action_kit_api.TargetSelectionTemplate) action_kit_sdk.Action[LogActionState] {
Expand Down Expand Up @@ -86,7 +91,7 @@ func (l *logAction) Describe() action_kit_api.ActionDescription {
Order: extutil.Ptr(1),
},
{
Name: "error",
Name: "errorEndpoint",
Label: "Error in endpoint",
Description: extutil.Ptr("Should we throw an error in the selected endpoint?"),
Type: action_kit_api.String,
Expand Down Expand Up @@ -117,13 +122,53 @@ func (l *logAction) Describe() action_kit_api.ActionDescription {
}),
},
{
Name: "errorTargetFilter",
Label: "Error Target Filter",
Description: extutil.Ptr("For which target should we throw an error? '*' throws for all targets."),
DefaultValue: extutil.Ptr("*"),
Name: "latencyEndpoint",
Label: "Latency in endpoint",
Description: extutil.Ptr("Should we add latency in the selected endpoint?"),
Type: action_kit_api.String,
Order: extutil.Ptr(3),
Advanced: extutil.Ptr(true),
DefaultValue: extutil.Ptr("none"),
Options: extutil.Ptr([]action_kit_api.ParameterOption{
action_kit_api.ExplicitParameterOption{
Label: "no latency",
Value: "none",
},
action_kit_api.ExplicitParameterOption{
Label: "prepare",
Value: "prepare",
},
action_kit_api.ExplicitParameterOption{
Label: "start",
Value: "start",
},
action_kit_api.ExplicitParameterOption{
Label: "status",
Value: "status",
},
action_kit_api.ExplicitParameterOption{
Label: "stop",
Value: "stop",
},
}),
},
{
Name: "latencyDuration",
Label: "Latency",
Type: action_kit_api.Duration,
DefaultValue: extutil.Ptr("5s"),
Required: extutil.Ptr(false),
Order: extutil.Ptr(4),
Advanced: extutil.Ptr(true),
},
{
Name: "targetFilter",
Label: "Target Filter for error / latency",
Description: extutil.Ptr("For which target should we throw an error / add latency? '*' throws for all targets."),
DefaultValue: extutil.Ptr("*"),
Type: action_kit_api.String,
Order: extutil.Ptr(5),
Advanced: extutil.Ptr(true),
},
},
Status: extutil.Ptr(action_kit_api.MutatingEndpointReferenceWithCallInterval{
Expand All @@ -139,15 +184,21 @@ func (l *logAction) Prepare(_ context.Context, state *LogActionState, request ac
return nil, extension_kit.ToError("Failed to unmarshal the config.", err)
}
state.FormattedMessage = fmt.Sprintf(config.Message, request.Target.Name)
state.Error = config.Error
state.ErrorTargetFilter = config.ErrorTargetFilter
state.ErrorEndpoint = config.ErrorEndpoint
state.LatencyEndpoint = config.LatencyEndpoint
state.LatencyDuration = time.Duration(config.LatencyDuration * int64(time.Millisecond))
state.TargetFilter = config.TargetFilter
state.TargetName = request.Target.Name

log.Info().Str("message", state.FormattedMessage).Msg("Logging in log action **prepare**")

if state.Error == "prepare" && (state.ErrorTargetFilter == "*" || state.ErrorTargetFilter == state.TargetName) {
if state.ErrorEndpoint == "prepare" && (state.TargetFilter == "*" || state.TargetFilter == state.TargetName) {
return nil, extension_kit.ToError("Simulated error thrown in prepare endpoint", nil)
}
if state.LatencyEndpoint == "prepare" && (state.TargetFilter == "*" || state.TargetFilter == state.TargetName) {
log.Info().Int64("latency", state.LatencyDuration.Milliseconds()).Msg("Adding latency in log action **prepare**")
time.Sleep(state.LatencyDuration)
}

return &action_kit_api.PrepareResult{
Messages: extutil.Ptr([]action_kit_api.Message{
Expand All @@ -161,9 +212,13 @@ func (l *logAction) Prepare(_ context.Context, state *LogActionState, request ac
func (l *logAction) Start(_ context.Context, state *LogActionState) (*action_kit_api.StartResult, error) {
log.Info().Str("message", state.FormattedMessage).Msg("Logging in log action **start**")

if state.Error == "start" && (state.ErrorTargetFilter == "*" || state.ErrorTargetFilter == state.TargetName) {
if state.ErrorEndpoint == "start" && (state.TargetFilter == "*" || state.TargetFilter == state.TargetName) {
return nil, extension_kit.ToError("Simulated error thrown in start endpoint", nil)
}
if state.LatencyEndpoint == "start" && (state.TargetFilter == "*" || state.TargetFilter == state.TargetName) {
log.Info().Int64("latency", state.LatencyDuration.Milliseconds()).Msg("Adding latency in log action **start**")
time.Sleep(state.LatencyDuration)
}

return &action_kit_api.StartResult{
Messages: extutil.Ptr([]action_kit_api.Message{
Expand All @@ -177,9 +232,13 @@ func (l *logAction) Start(_ context.Context, state *LogActionState) (*action_kit
func (l *logAction) Status(_ context.Context, state *LogActionState) (*action_kit_api.StatusResult, error) {
log.Info().Str("message", state.FormattedMessage).Msg("Logging in log action **status**")

if state.Error == "status" && (state.ErrorTargetFilter == "*" || state.ErrorTargetFilter == state.TargetName) {
if state.ErrorEndpoint == "status" && (state.TargetFilter == "*" || state.TargetFilter == state.TargetName) {
return nil, extension_kit.ToError("Simulated error thrown in status endpoint", nil)
}
if state.LatencyEndpoint == "status" && (state.TargetFilter == "*" || state.TargetFilter == state.TargetName) {
log.Info().Int64("latency", state.LatencyDuration.Milliseconds()).Msg("Adding latency in log action **status**")
time.Sleep(state.LatencyDuration)
}

return &action_kit_api.StatusResult{
//indicate that the action is still running
Expand All @@ -196,9 +255,13 @@ func (l *logAction) Status(_ context.Context, state *LogActionState) (*action_ki
func (l *logAction) Stop(_ context.Context, state *LogActionState) (*action_kit_api.StopResult, error) {
log.Info().Str("message", state.FormattedMessage).Msg("Logging in log action **stop**")

if state.Error == "stop" && (state.ErrorTargetFilter == "*" || state.ErrorTargetFilter == state.TargetName) {
if state.ErrorEndpoint == "stop" && (state.TargetFilter == "*" || state.TargetFilter == state.TargetName) {
return nil, extension_kit.ToError("Simulated error thrown in stop endpoint", nil)
}
if state.LatencyEndpoint == "stop" && (state.TargetFilter == "*" || state.TargetFilter == state.TargetName) {
log.Info().Int64("latency", state.LatencyDuration.Milliseconds()).Msg("Adding latency in log action **stop**")
time.Sleep(state.LatencyDuration)
}

return &action_kit_api.StopResult{
//These messages will show up in agent log
Expand Down
43 changes: 43 additions & 0 deletions extloadtest/action_log_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package extloadtest

import (
"context"
"github.com/steadybit/action-kit/go/action_kit_api/v2"
"github.com/steadybit/extension-kit/extutil"
"github.com/stretchr/testify/require"
"testing"
"time"
)

func TestPrepare(t *testing.T) {
// Given
request := extutil.JsonMangle(action_kit_api.PrepareActionRequestBody{
Config: map[string]interface{}{
"duration": 1000 * 60,
"message": "lorem ipsum %s",
"errorEndpoint": "stop",
"latencyEndpoint": "start",
"latencyDuration": 1000 * 60,
"targetFilter": "*",
"targetName": "loadtest",
},
Target: &action_kit_api.Target{
Name: "example-target",
},
ExecutionContext: extutil.Ptr(action_kit_api.ExecutionContext{}),
})
action := NewLogAction("com.example.target", action_kit_api.TargetSelectionTemplate{})
state := action.NewEmptyState()

// When
_, err := action.Prepare(context.TODO(), &state, request)

// Then
require.Nil(t, err)
require.Equal(t, "lorem ipsum example-target", state.FormattedMessage)
require.Equal(t, "example-target", state.TargetName)
require.Equal(t, "stop", state.ErrorEndpoint)
require.Equal(t, "start", state.LatencyEndpoint)
require.Equal(t, 60*time.Second, state.LatencyDuration)
require.Equal(t, "*", state.TargetFilter)
}
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ require (
github.com/steadybit/discovery-kit/go/discovery_kit_sdk v1.0.0
github.com/steadybit/event-kit/go/event_kit_api v1.3.1
github.com/steadybit/extension-kit v1.8.11
github.com/stretchr/testify v1.8.4
)

require (
Expand All @@ -27,6 +28,7 @@ require (
github.com/bytedance/sonic v1.10.2 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect
github.com/chenzhuoyu/iasm v0.9.1 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/deepmap/oapi-codegen v1.16.2 // indirect
github.com/fatih/structs v1.1.0 // indirect
github.com/flosch/pongo2/v4 v4.0.2 // indirect
Expand Down Expand Up @@ -70,6 +72,7 @@ require (
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
github.com/perimeterx/marshmallow v1.1.5 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rs/xid v1.5.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/schollz/closestmatch v2.1.0+incompatible // indirect
Expand Down

0 comments on commit 16752d9

Please sign in to comment.