mirror of
https://github.com/mentos1386/zdravko.git
synced 2024-11-21 23:33:34 +00:00
feat(healthchecks): store history and nice code editor for scripts
This commit is contained in:
parent
33e8d2091d
commit
3a8badb61b
56 changed files with 39003 additions and 109 deletions
|
@ -5,6 +5,7 @@
|
|||
"watchexec@latest",
|
||||
"tailwindcss@latest",
|
||||
"flyctl@latest",
|
||||
"just@latest"
|
||||
"just@latest",
|
||||
"nodePackages.npm@latest"
|
||||
]
|
||||
}
|
||||
|
|
14
devbox.lock
14
devbox.lock
|
@ -61,6 +61,20 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"nodePackages.npm@latest": {
|
||||
"last_modified": "2024-02-15T12:53:33Z",
|
||||
"resolved": "github:NixOS/nixpkgs/085589047343aad800c4d305cf7b98e8a3d51ae2#nodePackages.npm",
|
||||
"source": "devbox-search",
|
||||
"version": "10.4.0",
|
||||
"systems": {
|
||||
"aarch64-linux": {
|
||||
"store_path": "/nix/store/06ywqfygg4xc4rwvp40ksrrvsspnpxyl-npm-10.4.0"
|
||||
},
|
||||
"x86_64-linux": {
|
||||
"store_path": "/nix/store/p5hi9rp2qhhfw2ih4wgb1waplmwrkjqc-npm-10.4.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"tailwindcss@latest": {
|
||||
"last_modified": "2024-01-27T14:55:31Z",
|
||||
"resolved": "github:NixOS/nixpkgs/160b762eda6d139ac10ae081f8f78d640dd523eb#tailwindcss",
|
||||
|
|
11
internal/activities/activities.go
Normal file
11
internal/activities/activities.go
Normal file
|
@ -0,0 +1,11 @@
|
|||
package activities
|
||||
|
||||
import "code.tjo.space/mentos1386/zdravko/internal/config"
|
||||
|
||||
type Activities struct {
|
||||
config *config.WorkerConfig
|
||||
}
|
||||
|
||||
func NewActivities(config *config.WorkerConfig) *Activities {
|
||||
return &Activities{config: config}
|
||||
}
|
|
@ -1,10 +1,14 @@
|
|||
package activities
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
|
||||
"code.tjo.space/mentos1386/zdravko/pkg/api"
|
||||
"code.tjo.space/mentos1386/zdravko/pkg/k6"
|
||||
)
|
||||
|
||||
|
@ -13,33 +17,57 @@ type HealtcheckParam struct {
|
|||
}
|
||||
|
||||
type HealthcheckResult struct {
|
||||
StatusCode int
|
||||
Success bool
|
||||
Note string
|
||||
}
|
||||
|
||||
func Healthcheck(ctx context.Context, param HealtcheckParam) (*HealthcheckResult, error) {
|
||||
|
||||
statusCode := http.StatusOK // FIXME
|
||||
|
||||
func (a *Activities) Healthcheck(ctx context.Context, param HealtcheckParam) (*HealthcheckResult, error) {
|
||||
execution := k6.NewExecution(slog.Default(), param.Script)
|
||||
|
||||
err := execution.Run(ctx)
|
||||
result, err := execution.Run(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &HealthcheckResult{StatusCode: statusCode}, nil
|
||||
return &HealthcheckResult{Success: result.Success, Note: result.Note}, nil
|
||||
}
|
||||
|
||||
type HealtcheckAddToHistoryParam struct {
|
||||
Id string
|
||||
Success bool
|
||||
StatusCode int
|
||||
Slug string
|
||||
Status string
|
||||
Note string
|
||||
}
|
||||
|
||||
type HealthcheckAddToHistoryResult struct {
|
||||
}
|
||||
|
||||
func HealthcheckAddToHistory(ctx context.Context, param HealtcheckAddToHistoryParam) (*HealthcheckAddToHistoryResult, error) {
|
||||
func (a *Activities) HealthcheckAddToHistory(ctx context.Context, param HealtcheckAddToHistoryParam) (*HealthcheckAddToHistoryResult, error) {
|
||||
url := fmt.Sprintf("%s/api/v1/healthchecks/%s/history", a.config.ApiUrl, param.Slug)
|
||||
|
||||
body := api.ApiV1HealthchecksHistoryPOSTBody{
|
||||
Status: param.Status,
|
||||
Note: param.Note,
|
||||
}
|
||||
|
||||
jsonBody, err := json.Marshal(body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req, err := api.NewRequest(http.MethodPost, url, a.config.Token, bytes.NewReader(jsonBody))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
response, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer response.Body.Close()
|
||||
|
||||
if response.StatusCode != http.StatusCreated {
|
||||
return nil, fmt.Errorf("unexpected status code: %d", response.StatusCode)
|
||||
}
|
||||
|
||||
return &HealthcheckAddToHistoryResult{}, nil
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
|
||||
"code.tjo.space/mentos1386/zdravko/internal/models"
|
||||
"code.tjo.space/mentos1386/zdravko/internal/services"
|
||||
"code.tjo.space/mentos1386/zdravko/pkg/api"
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
|
@ -35,6 +36,12 @@ func (h *BaseHandler) ApiV1HealthchecksHistoryPOST(c echo.Context) error {
|
|||
|
||||
slug := c.Param("slug")
|
||||
|
||||
var body api.ApiV1HealthchecksHistoryPOSTBody
|
||||
err := (&echo.DefaultBinder{}).BindBody(c, &body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
healthcheck, err := services.GetHealthcheck(ctx, h.query, slug)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -42,7 +49,8 @@ func (h *BaseHandler) ApiV1HealthchecksHistoryPOST(c echo.Context) error {
|
|||
|
||||
err = h.query.Healthcheck.History.Model(healthcheck).Append(
|
||||
&models.HealthcheckHistory{
|
||||
Status: "UP",
|
||||
Status: body.Status,
|
||||
Note: body.Note,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -44,7 +44,8 @@ type Cronjob struct {
|
|||
type HealthcheckHistory struct {
|
||||
gorm.Model
|
||||
Healthcheck Healthcheck `gorm:"foreignkey:ID"`
|
||||
Status string
|
||||
Status string // SUCCESS, FAIL, ERROR
|
||||
Note string
|
||||
}
|
||||
|
||||
type CronjobHistory struct {
|
||||
|
|
|
@ -27,10 +27,12 @@ func StartHealthcheck(ctx context.Context, t client.Client, healthcheck *models.
|
|||
log.Println("Starting Healthcheck Workflow")
|
||||
|
||||
args := make([]interface{}, 0)
|
||||
args = append(args, workflows.HealthcheckWorkflowParam{Script: healthcheck.Script})
|
||||
args = append(args, workflows.HealthcheckWorkflowParam{Script: healthcheck.Script, Slug: healthcheck.Slug})
|
||||
|
||||
id := "healthcheck-" + healthcheck.Slug
|
||||
|
||||
fakeWorkflows := workflows.NewWorkflows(nil)
|
||||
|
||||
for _, group := range healthcheck.WorkerGroups {
|
||||
_, err := t.ScheduleClient().Create(ctx, client.ScheduleOptions{
|
||||
ID: id + "-" + group,
|
||||
|
@ -39,7 +41,7 @@ func StartHealthcheck(ctx context.Context, t client.Client, healthcheck *models.
|
|||
},
|
||||
Action: &client.ScheduleWorkflowAction{
|
||||
ID: id + "-" + group,
|
||||
Workflow: workflows.HealthcheckWorkflowDefinition,
|
||||
Workflow: fakeWorkflows.HealthcheckWorkflowDefinition,
|
||||
Args: args,
|
||||
TaskQueue: group,
|
||||
RetryPolicy: &temporal.RetryPolicy{
|
||||
|
|
|
@ -31,7 +31,7 @@ func ConnectServerToTemporal(cfg *config.ServerConfig) (client.Client, error) {
|
|||
provider := &AuthHeadersProvider{token}
|
||||
|
||||
// Try to connect to the Temporal Server
|
||||
return retry.Retry(5, 6*time.Second, func() (client.Client, error) {
|
||||
return retry.Retry(10, 3*time.Second, func() (client.Client, error) {
|
||||
return client.Dial(client.Options{
|
||||
HostPort: cfg.Temporal.ServerHost,
|
||||
HeadersProvider: provider,
|
||||
|
|
|
@ -9,20 +9,38 @@ import (
|
|||
|
||||
type HealthcheckWorkflowParam struct {
|
||||
Script string
|
||||
Slug string
|
||||
}
|
||||
|
||||
func HealthcheckWorkflowDefinition(ctx workflow.Context, param HealthcheckWorkflowParam) error {
|
||||
func (w *Workflows) HealthcheckWorkflowDefinition(ctx workflow.Context, param HealthcheckWorkflowParam) error {
|
||||
options := workflow.ActivityOptions{
|
||||
StartToCloseTimeout: 10 * time.Second,
|
||||
}
|
||||
ctx = workflow.WithActivityOptions(ctx, options)
|
||||
|
||||
activityParam := activities.HealtcheckParam{
|
||||
heatlcheckParam := activities.HealtcheckParam{
|
||||
Script: param.Script,
|
||||
}
|
||||
|
||||
var result *activities.HealthcheckResult
|
||||
err := workflow.ExecuteActivity(ctx, activities.Healthcheck, activityParam).Get(ctx, &result)
|
||||
var healthcheckResult *activities.HealthcheckResult
|
||||
err := workflow.ExecuteActivity(ctx, w.activities.Healthcheck, heatlcheckParam).Get(ctx, &healthcheckResult)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
status := "failure"
|
||||
if healthcheckResult.Success {
|
||||
status = "success"
|
||||
}
|
||||
|
||||
historyParam := activities.HealtcheckAddToHistoryParam{
|
||||
Slug: param.Slug,
|
||||
Status: status,
|
||||
Note: healthcheckResult.Note,
|
||||
}
|
||||
|
||||
var historyResult *activities.HealthcheckAddToHistoryResult
|
||||
err = workflow.ExecuteActivity(ctx, w.activities.HealthcheckAddToHistory, historyParam).Get(ctx, &historyResult)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
13
internal/workflows/workflows.go
Normal file
13
internal/workflows/workflows.go
Normal file
|
@ -0,0 +1,13 @@
|
|||
package workflows
|
||||
|
||||
import (
|
||||
"code.tjo.space/mentos1386/zdravko/internal/activities"
|
||||
)
|
||||
|
||||
type Workflows struct {
|
||||
activities *activities.Activities
|
||||
}
|
||||
|
||||
func NewWorkflows(a *activities.Activities) *Workflows {
|
||||
return &Workflows{activities: a}
|
||||
}
|
16
justfile
16
justfile
|
@ -35,7 +35,7 @@ run-temporal:
|
|||
|
||||
# Test
|
||||
test:
|
||||
go test -v -cover ./...
|
||||
go test -v ./...
|
||||
|
||||
# Generates new jwt key pair
|
||||
generate-jwt-key:
|
||||
|
@ -95,6 +95,20 @@ _htmx-download:
|
|||
mkdir -p {{STATIC_DIR}}/js
|
||||
curl -sLo {{STATIC_DIR}}/js/htmx.min.js https://unpkg.com/htmx.org/dist/htmx.min.js
|
||||
|
||||
_monaco-download:
|
||||
rm -rf {{STATIC_DIR}}/monaco
|
||||
npm install monaco-editor@0.46.0
|
||||
mv node_modules/monaco-editor/min {{STATIC_DIR}}/monaco
|
||||
rm -rf node_modules
|
||||
|
||||
# We onlt care about javascript language
|
||||
find {{STATIC_DIR}}/monaco/vs/basic-languages/ \
|
||||
-type d \
|
||||
-not -name 'javascript' \
|
||||
-not -name 'typescript' \
|
||||
-not -name 'basic-languages' \
|
||||
-prune -exec rm -rf {} \;
|
||||
|
||||
_feather-icons-download:
|
||||
mkdir -p {{STATIC_DIR}}/icons
|
||||
curl -sLo {{STATIC_DIR}}/icons/feather-sprite.svg https://unpkg.com/feather-icons/dist/feather-sprite.svg
|
||||
|
|
17
package-lock.json
generated
Normal file
17
package-lock.json
generated
Normal file
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"name": "zdravko",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"dependencies": {
|
||||
"monaco-editor": "^0.46.0"
|
||||
}
|
||||
},
|
||||
"node_modules/monaco-editor": {
|
||||
"version": "0.46.0",
|
||||
"resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.46.0.tgz",
|
||||
"integrity": "sha512-ADwtLIIww+9FKybWscd7OCfm9odsFYHImBRI1v9AviGce55QY8raT+9ihH8jX/E/e6QVSGM+pKj4jSUSRmALNQ=="
|
||||
}
|
||||
}
|
||||
}
|
5
package.json
Normal file
5
package.json
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"dependencies": {
|
||||
"monaco-editor": "^0.46.0"
|
||||
}
|
||||
}
|
23
pkg/api/api.go
Normal file
23
pkg/api/api.go
Normal file
|
@ -0,0 +1,23 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func NewRequest(method string, urlString string, token string, body io.Reader) (*http.Request, error) {
|
||||
headers := http.Header{}
|
||||
headers.Add("Authorization", "Bearer "+token)
|
||||
|
||||
if body != nil {
|
||||
headers.Add("Content-Type", "application/json")
|
||||
}
|
||||
|
||||
req, err := http.NewRequest(method, urlString, body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.Header = headers
|
||||
|
||||
return req, nil
|
||||
}
|
6
pkg/api/healthchecks.go
Normal file
6
pkg/api/healthchecks.go
Normal file
|
@ -0,0 +1,6 @@
|
|||
package api
|
||||
|
||||
type ApiV1HealthchecksHistoryPOSTBody struct {
|
||||
Status string `json:"status"`
|
||||
Note string `json:"note"`
|
||||
}
|
105
pkg/k6/k6.go
105
pkg/k6/k6.go
|
@ -12,8 +12,6 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
"go.k6.io/k6/errext"
|
||||
"go.k6.io/k6/errext/exitcodes"
|
||||
"go.k6.io/k6/event"
|
||||
"go.k6.io/k6/execution"
|
||||
"go.k6.io/k6/execution/local"
|
||||
|
@ -39,6 +37,11 @@ const (
|
|||
waitForTracerProviderStopTimeout = 3 * time.Minute
|
||||
)
|
||||
|
||||
type ExecutionResult struct {
|
||||
Note string
|
||||
Success bool
|
||||
}
|
||||
|
||||
type Execution struct {
|
||||
FS fsext.Fs
|
||||
Env map[string]string
|
||||
|
@ -53,6 +56,7 @@ type Execution struct {
|
|||
|
||||
func NewExecution(logger *slog.Logger, script string) *Execution {
|
||||
loggerCompat := logrus.StandardLogger()
|
||||
loggerCompat.SetLevel(logrus.DebugLevel)
|
||||
|
||||
return &Execution{
|
||||
FS: fsext.NewOsFs(),
|
||||
|
@ -136,10 +140,7 @@ func (e *Execution) setupTracerProvider(ctx context.Context, test *loadedAndConf
|
|||
return nil
|
||||
}
|
||||
|
||||
func (e *Execution) Run(ctx context.Context) error {
|
||||
var err error
|
||||
var logger logrus.FieldLogger = logrus.StandardLogger()
|
||||
|
||||
func (e *Execution) Run(ctx context.Context) (result *ExecutionResult, err error) {
|
||||
globalCtx, globalCancel := context.WithCancel(ctx)
|
||||
defer globalCancel()
|
||||
|
||||
|
@ -151,7 +152,7 @@ func (e *Execution) Run(ctx context.Context) error {
|
|||
// runCtx is used for the test run execution and is created with the special
|
||||
// execution.NewTestRunContext() function so that it can be aborted even
|
||||
// from sub-contexts while also attaching a reason for the abort.
|
||||
runCtx, runAbort := execution.NewTestRunContext(lingerCtx, logger)
|
||||
runCtx, runAbort := execution.NewTestRunContext(lingerCtx, e.LoggerCompat)
|
||||
|
||||
emitEvent := func(evt *event.Event) func() {
|
||||
waitDone := e.Events.Emit(evt)
|
||||
|
@ -159,7 +160,7 @@ func (e *Execution) Run(ctx context.Context) error {
|
|||
waitCtx, waitCancel := context.WithTimeout(globalCtx, waitEventDoneTimeout)
|
||||
defer waitCancel()
|
||||
if werr := waitDone(waitCtx); werr != nil {
|
||||
logger.WithError(werr).Warn()
|
||||
e.Logger.With(werr).Warn("")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -175,17 +176,17 @@ func (e *Execution) Run(ctx context.Context) error {
|
|||
|
||||
configuredTest, controller, err := e.loadLocalTest()
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err = e.setupTracerProvider(globalCtx, configuredTest); err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
waitTracesFlushed := func() {
|
||||
ctx, cancel := context.WithTimeout(globalCtx, waitForTracerProviderStopTimeout)
|
||||
defer cancel()
|
||||
if tpErr := configuredTest.preInitState.TracerProvider.Shutdown(ctx); tpErr != nil {
|
||||
logger.Errorf("The tracer provider didn't stop gracefully: %v", tpErr)
|
||||
e.Logger.Error("The tracer provider didn't stop gracefully", tpErr)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -193,14 +194,14 @@ func (e *Execution) Run(ctx context.Context) error {
|
|||
conf := configuredTest.config
|
||||
testRunState, err := configuredTest.buildTestRunState(conf)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Create a local execution scheduler wrapping the runner.
|
||||
logger.Debug("Initializing the execution scheduler...")
|
||||
e.Logger.Debug("Initializing the execution scheduler...")
|
||||
execScheduler, err := execution.NewScheduler(testRunState, controller)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
backgroundProcesses := &sync.WaitGroup{}
|
||||
|
@ -210,9 +211,9 @@ func (e *Execution) Run(ctx context.Context) error {
|
|||
// executionPlan := execScheduler.GetExecutionPlan()
|
||||
outputs := []output.Output{}
|
||||
|
||||
metricsEngine, err := engine.NewMetricsEngine(testRunState.Registry, logger)
|
||||
metricsEngine, err := engine.NewMetricsEngine(testRunState.Registry, e.LoggerCompat)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// We'll need to pipe metrics to the MetricsEngine and process them if any
|
||||
|
@ -223,7 +224,7 @@ func (e *Execution) Run(ctx context.Context) error {
|
|||
if shouldProcessMetrics {
|
||||
err = metricsEngine.InitSubMetricsAndThresholds(conf, testRunState.RuntimeOptions.NoThresholds.Bool)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
// We'll need to pipe metrics to the MetricsEngine if either the
|
||||
// thresholds or the end-of-test summary are enabled.
|
||||
|
@ -234,7 +235,7 @@ func (e *Execution) Run(ctx context.Context) error {
|
|||
executionState := execScheduler.GetState()
|
||||
if !testRunState.RuntimeOptions.NoSummary.Bool {
|
||||
defer func() {
|
||||
logger.Debug("Generating the end-of-test summary...")
|
||||
e.Logger.Debug("Generating the end-of-test summary...")
|
||||
summaryResult, hsErr := configuredTest.initRunner.HandleSummary(globalCtx, &lib.Summary{
|
||||
Metrics: metricsEngine.ObservedMetrics,
|
||||
RootGroup: testRunState.Runner.GetDefaultGroup(),
|
||||
|
@ -249,21 +250,21 @@ func (e *Execution) Run(ctx context.Context) error {
|
|||
for _, o := range summaryResult {
|
||||
_, err := io.Copy(os.Stdout, o)
|
||||
if err != nil {
|
||||
logger.WithError(err).Error("failed to write summary output")
|
||||
e.Logger.With(err).Error("failed to write summary output")
|
||||
}
|
||||
}
|
||||
}
|
||||
if hsErr != nil {
|
||||
logger.WithError(hsErr).Error("failed to handle the end-of-test summary")
|
||||
e.Logger.With(hsErr).Error("failed to handle the end-of-test summary")
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
waitInitDone := emitEvent(&event.Event{Type: event.Init})
|
||||
|
||||
outputManager := output.NewManager(outputs, logger, func(err error) {
|
||||
outputManager := output.NewManager(outputs, e.LoggerCompat, func(err error) {
|
||||
if err != nil {
|
||||
logger.WithError(err).Error("Received error to stop from output")
|
||||
e.Logger.With(err).Error("Received error to stop from output")
|
||||
}
|
||||
// TODO: attach run status and exit code?
|
||||
runAbort(err)
|
||||
|
@ -271,10 +272,10 @@ func (e *Execution) Run(ctx context.Context) error {
|
|||
samples := make(chan metrics.SampleContainer, configuredTest.config.MetricSamplesBufferSize.Int64)
|
||||
waitOutputsFlushed, stopOutputs, err := outputManager.Start(samples)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
defer func() {
|
||||
logger.Debug("Stopping outputs...")
|
||||
e.Logger.Debug("Stopping outputs...")
|
||||
// We call waitOutputsFlushed() below because the threshold calculations
|
||||
// need all of the metrics to be sent to the MetricsEngine before we can
|
||||
// calculate them one last time. We need the threshold calculated here,
|
||||
|
@ -286,35 +287,29 @@ func (e *Execution) Run(ctx context.Context) error {
|
|||
finalizeThresholds := metricsEngine.StartThresholdCalculations(
|
||||
metricsIngester, runAbort, executionState.GetCurrentTestRunDuration,
|
||||
)
|
||||
handleFinalThresholdCalculation := func() {
|
||||
// This gets called after the Samples channel has been closed and
|
||||
// the OutputManager has flushed all of the cached samples to
|
||||
// outputs (including MetricsEngine's ingester). So we are sure
|
||||
// there won't be any more metrics being sent.
|
||||
logger.Debug("Finalizing thresholds...")
|
||||
breachedThresholds := finalizeThresholds()
|
||||
if len(breachedThresholds) == 0 {
|
||||
return
|
||||
}
|
||||
tErr := errext.WithAbortReasonIfNone(
|
||||
errext.WithExitCodeIfNone(
|
||||
fmt.Errorf("thresholds on metrics '%s' have been crossed", strings.Join(breachedThresholds, ", ")),
|
||||
exitcodes.ThresholdsHaveFailed,
|
||||
), errext.AbortedByThresholdsAfterTestEnd)
|
||||
|
||||
if err == nil {
|
||||
err = tErr
|
||||
} else {
|
||||
logger.WithError(tErr).Debug("Crossed thresholds, but test already exited with another error")
|
||||
}
|
||||
}
|
||||
if finalizeThresholds != nil {
|
||||
defer handleFinalThresholdCalculation()
|
||||
defer func() {
|
||||
// This gets called after the Samples channel has been closed and
|
||||
// the OutputManager has flushed all of the cached samples to
|
||||
// outputs (including MetricsEngine's ingester). So we are sure
|
||||
// there won't be any more metrics being sent.
|
||||
e.Logger.Debug("Finalizing thresholds...")
|
||||
breachedThresholds := finalizeThresholds()
|
||||
if len(breachedThresholds) == 0 {
|
||||
return
|
||||
}
|
||||
if err == nil {
|
||||
result = &ExecutionResult{
|
||||
Success: false,
|
||||
Note: fmt.Sprintf("thresholds on metrics '%s' have been crossed", strings.Join(breachedThresholds, ", ")),
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
defer func() {
|
||||
logger.Debug("Waiting for metrics and traces processing to finish...")
|
||||
e.Logger.Debug("Waiting for metrics and traces processing to finish...")
|
||||
close(samples)
|
||||
|
||||
ww := [...]func(){
|
||||
|
@ -332,13 +327,13 @@ func (e *Execution) Run(ctx context.Context) error {
|
|||
}
|
||||
wg.Wait()
|
||||
|
||||
logger.Debug("Metrics and traces processing finished!")
|
||||
e.Logger.Debug("Metrics and traces processing finished!")
|
||||
}()
|
||||
|
||||
// Initialize the VUs and executors
|
||||
stopVUEmission, err := execScheduler.Init(runCtx, samples)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
defer stopVUEmission()
|
||||
|
||||
|
@ -357,16 +352,16 @@ func (e *Execution) Run(ctx context.Context) error {
|
|||
// Check what the execScheduler.Run() error is.
|
||||
if err != nil {
|
||||
err = common.UnwrapGojaInterruptedError(err)
|
||||
logger.WithError(err).Debug("Test finished with an error")
|
||||
return err
|
||||
e.Logger.With(err).Debug("Test finished with an error")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Warn if no iterations could be completed.
|
||||
if executionState.GetFullIterationCount() == 0 {
|
||||
logger.Warn("No script iterations fully finished, consider making the test duration longer")
|
||||
e.Logger.Warn("No script iterations fully finished, consider making the test duration longer")
|
||||
}
|
||||
|
||||
logger.Debug("Test finished cleanly")
|
||||
e.Logger.Debug("Test finished cleanly")
|
||||
|
||||
return nil
|
||||
return &ExecutionResult{Success: true, Note: ""}, nil
|
||||
}
|
||||
|
|
|
@ -3,12 +3,23 @@ package k6
|
|||
import (
|
||||
"context"
|
||||
"log/slog"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func getLogger() *slog.Logger {
|
||||
opts := &slog.HandlerOptions{
|
||||
Level: slog.LevelDebug,
|
||||
}
|
||||
|
||||
handler := slog.NewTextHandler(os.Stdout, opts)
|
||||
|
||||
return slog.New(handler)
|
||||
}
|
||||
|
||||
func TestK6Success(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
logger := slog.Default()
|
||||
logger := getLogger()
|
||||
|
||||
script := `
|
||||
import http from 'k6/http';
|
||||
|
@ -27,15 +38,18 @@ export default function () {
|
|||
|
||||
execution := NewExecution(logger, script)
|
||||
|
||||
err := execution.Run(ctx)
|
||||
result, err := execution.Run(ctx)
|
||||
if err != nil {
|
||||
t.Errorf("Error starting execution: %v", err)
|
||||
}
|
||||
if result != nil {
|
||||
t.Logf("Result: %v", result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestK6Fail(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
logger := slog.Default()
|
||||
logger := getLogger()
|
||||
|
||||
script := `
|
||||
import http from 'k6/http';
|
||||
|
@ -55,8 +69,11 @@ export default function () {
|
|||
|
||||
execution := NewExecution(logger, script)
|
||||
|
||||
err := execution.Run(ctx)
|
||||
result, err := execution.Run(ctx)
|
||||
if err != nil {
|
||||
t.Errorf("Error starting execution: %v", err)
|
||||
}
|
||||
if result != nil {
|
||||
t.Logf("Result: %v", result)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -98,7 +98,7 @@ func (s *Server) Start() error {
|
|||
apiv1 := s.echo.Group("/api/v1")
|
||||
apiv1.Use(h.Authenticated)
|
||||
apiv1.GET("/workers/connect", h.ApiV1WorkersConnectGET)
|
||||
apiv1.POST("/healthcheck/:slug/history", h.ApiV1HealthchecksHistoryPOST)
|
||||
apiv1.POST("/healthchecks/:slug/history", h.ApiV1HealthchecksHistoryPOST)
|
||||
|
||||
// Error handler
|
||||
s.echo.HTTPErrorHandler = func(err error, c echo.Context) {
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
"code.tjo.space/mentos1386/zdravko/internal/config"
|
||||
"code.tjo.space/mentos1386/zdravko/internal/temporal"
|
||||
"code.tjo.space/mentos1386/zdravko/internal/workflows"
|
||||
"code.tjo.space/mentos1386/zdravko/pkg/api"
|
||||
"code.tjo.space/mentos1386/zdravko/pkg/retry"
|
||||
"github.com/pkg/errors"
|
||||
"go.temporal.io/sdk/worker"
|
||||
|
@ -23,13 +24,10 @@ type ConnectionConfig struct {
|
|||
}
|
||||
|
||||
func getConnectionConfig(token string, apiUrl string) (*ConnectionConfig, error) {
|
||||
url := apiUrl + "/api/v1/workers/connect"
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, url, nil)
|
||||
req, err := api.NewRequest(http.MethodGet, apiUrl+"/api/v1/workers/connect", token, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.Header.Add("Authorization", "Bearer "+token)
|
||||
|
||||
return retry.Retry(10, 3*time.Second, func() (*ConnectionConfig, error) {
|
||||
res, err := http.DefaultClient.Do(req)
|
||||
|
@ -82,14 +80,17 @@ func (w *Worker) Start() error {
|
|||
}
|
||||
|
||||
// Create a new Worker
|
||||
// TODO: Maybe identify by region or something?
|
||||
w.worker = worker.New(temporalClient, config.Group, worker.Options{})
|
||||
|
||||
workerActivities := activities.NewActivities(w.cfg)
|
||||
workerWorkflows := workflows.NewWorkflows(workerActivities)
|
||||
|
||||
// Register Workflows
|
||||
w.worker.RegisterWorkflow(workflows.HealthcheckWorkflowDefinition)
|
||||
w.worker.RegisterWorkflow(workerWorkflows.HealthcheckWorkflowDefinition)
|
||||
|
||||
// Register Activities
|
||||
w.worker.RegisterActivity(activities.Healthcheck)
|
||||
w.worker.RegisterActivity(workerActivities.Healthcheck)
|
||||
w.worker.RegisterActivity(workerActivities.HealthcheckAddToHistory)
|
||||
|
||||
return w.worker.Run(worker.InterruptCh())
|
||||
}
|
||||
|
|
|
@ -668,6 +668,10 @@ video {
|
|||
display: grid;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.h-20 {
|
||||
height: 5rem;
|
||||
}
|
||||
|
@ -688,6 +692,10 @@ video {
|
|||
height: 2rem;
|
||||
}
|
||||
|
||||
.h-96 {
|
||||
height: 24rem;
|
||||
}
|
||||
|
||||
.w-20 {
|
||||
width: 5rem;
|
||||
}
|
||||
|
@ -1309,10 +1317,3 @@ video {
|
|||
.rtl\:text-right:where([dir="rtl"], [dir="rtl"] *) {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.dark\:text-white {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(255 255 255 / var(--tw-text-opacity));
|
||||
}
|
||||
}
|
||||
|
|
Binary file not shown.
|
@ -0,0 +1,8 @@
|
|||
/*!-----------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Version: 0.46.0(21007360cad28648bdf46282a2592cb47c3a7a6f)
|
||||
* Released under the MIT license
|
||||
* https://github.com/microsoft/vscode/blob/main/LICENSE.txt
|
||||
*-----------------------------------------------------------*/define("vs/base/common/worker/simpleWorker.nls.de",{"vs/base/common/platform":["_"],"vs/editor/common/languages":["Array","Boolescher Wert","Klasse","Konstante","Konstruktor","Enumeration","Enumerationsmember","Ereignis","Feld","Datei","Funktion","Schnittstelle","Schl\xFCssel","Methode","Modul","Namespace","NULL","Zahl","Objekt","Operator","Paket","Eigenschaft","Zeichenfolge","Struktur","Typparameter","Variable","{0} ({1})"]});
|
||||
|
||||
//# sourceMappingURL=../../../../../min-maps/vs/base/common/worker/simpleWorker.nls.de.js.map
|
|
@ -0,0 +1,8 @@
|
|||
/*!-----------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Version: 0.46.0(21007360cad28648bdf46282a2592cb47c3a7a6f)
|
||||
* Released under the MIT license
|
||||
* https://github.com/microsoft/vscode/blob/main/LICENSE.txt
|
||||
*-----------------------------------------------------------*/define("vs/base/common/worker/simpleWorker.nls.es",{"vs/base/common/platform":["_"],"vs/editor/common/languages":["matriz","booleano","clase","constante","constructor","enumeraci\xF3n","miembro de la enumeraci\xF3n","evento","campo","archivo","funci\xF3n","interfaz","clave","m\xE9todo","m\xF3dulo","espacio de nombres","NULL","n\xFAmero","objeto","operador","paquete","propiedad","cadena","estructura","par\xE1metro de tipo","variable","{0} ({1})"]});
|
||||
|
||||
//# sourceMappingURL=../../../../../min-maps/vs/base/common/worker/simpleWorker.nls.es.js.map
|
|
@ -0,0 +1,8 @@
|
|||
/*!-----------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Version: 0.46.0(21007360cad28648bdf46282a2592cb47c3a7a6f)
|
||||
* Released under the MIT license
|
||||
* https://github.com/microsoft/vscode/blob/main/LICENSE.txt
|
||||
*-----------------------------------------------------------*/define("vs/base/common/worker/simpleWorker.nls.fr",{"vs/base/common/platform":["_"],"vs/editor/common/languages":["tableau","bool\xE9en","classe","constante","constructeur","\xE9num\xE9ration","membre d'\xE9num\xE9ration","\xE9v\xE9nement","champ","fichier","fonction","interface","cl\xE9","m\xE9thode","module","espace de noms","NULL","nombre","objet","op\xE9rateur","package","propri\xE9t\xE9","cha\xEEne","struct","param\xE8tre de type","variable","{0} ({1})"]});
|
||||
|
||||
//# sourceMappingURL=../../../../../min-maps/vs/base/common/worker/simpleWorker.nls.fr.js.map
|
|
@ -0,0 +1,8 @@
|
|||
/*!-----------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Version: 0.46.0(21007360cad28648bdf46282a2592cb47c3a7a6f)
|
||||
* Released under the MIT license
|
||||
* https://github.com/microsoft/vscode/blob/main/LICENSE.txt
|
||||
*-----------------------------------------------------------*/define("vs/base/common/worker/simpleWorker.nls.it",{"vs/base/common/platform":["_"],"vs/editor/common/languages":["matrice","valore booleano","classe","costante","costruttore","enumerazione","membro di enumerazione","evento","campo","file","funzione","interfaccia","chiave","metodo","modulo","spazio dei nomi","Null","numero","oggetto","operatore","pacchetto","propriet\xE0","stringa","struct","parametro di tipo","variabile","{0} ({1})"]});
|
||||
|
||||
//# sourceMappingURL=../../../../../min-maps/vs/base/common/worker/simpleWorker.nls.it.js.map
|
|
@ -0,0 +1,8 @@
|
|||
/*!-----------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Version: 0.46.0(21007360cad28648bdf46282a2592cb47c3a7a6f)
|
||||
* Released under the MIT license
|
||||
* https://github.com/microsoft/vscode/blob/main/LICENSE.txt
|
||||
*-----------------------------------------------------------*/define("vs/base/common/worker/simpleWorker.nls.ja",{"vs/base/common/platform":["_"],"vs/editor/common/languages":["\u914D\u5217","\u30D6\u30FC\u30EB\u5024","\u30AF\u30E9\u30B9","\u5B9A\u6570","\u30B3\u30F3\u30B9\u30C8\u30E9\u30AF\u30BF\u30FC","\u5217\u6319\u578B","\u5217\u6319\u578B\u30E1\u30F3\u30D0\u30FC","\u30A4\u30D9\u30F3\u30C8","\u30D5\u30A3\u30FC\u30EB\u30C9","\u30D5\u30A1\u30A4\u30EB","\u95A2\u6570","\u30A4\u30F3\u30BF\u30FC\u30D5\u30A7\u30A4\u30B9","\u30AD\u30FC","\u30E1\u30BD\u30C3\u30C9","\u30E2\u30B8\u30E5\u30FC\u30EB","\u540D\u524D\u7A7A\u9593","NULL","\u6570\u5024","\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8","\u6F14\u7B97\u5B50","\u30D1\u30C3\u30B1\u30FC\u30B8","\u30D7\u30ED\u30D1\u30C6\u30A3","\u6587\u5B57\u5217","\u69CB\u9020\u4F53","\u578B\u30D1\u30E9\u30E1\u30FC\u30BF\u30FC","\u5909\u6570","{0} ({1})"]});
|
||||
|
||||
//# sourceMappingURL=../../../../../min-maps/vs/base/common/worker/simpleWorker.nls.ja.js.map
|
|
@ -0,0 +1,8 @@
|
|||
/*!-----------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Version: 0.46.0(21007360cad28648bdf46282a2592cb47c3a7a6f)
|
||||
* Released under the MIT license
|
||||
* https://github.com/microsoft/vscode/blob/main/LICENSE.txt
|
||||
*-----------------------------------------------------------*/define("vs/base/common/worker/simpleWorker.nls",{"vs/base/common/platform":["_"],"vs/editor/common/languages":["array","boolean","class","constant","constructor","enumeration","enumeration member","event","field","file","function","interface","key","method","module","namespace","null","number","object","operator","package","property","string","struct","type parameter","variable","{0} ({1})"]});
|
||||
|
||||
//# sourceMappingURL=../../../../../min-maps/vs/base/common/worker/simpleWorker.nls.js.map
|
|
@ -0,0 +1,8 @@
|
|||
/*!-----------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Version: 0.46.0(21007360cad28648bdf46282a2592cb47c3a7a6f)
|
||||
* Released under the MIT license
|
||||
* https://github.com/microsoft/vscode/blob/main/LICENSE.txt
|
||||
*-----------------------------------------------------------*/define("vs/base/common/worker/simpleWorker.nls.ko",{"vs/base/common/platform":["_"],"vs/editor/common/languages":["\uBC30\uC5F4","\uBD80\uC6B8","\uD074\uB798\uC2A4","\uC0C1\uC218","\uC0DD\uC131\uC790","\uC5F4\uAC70\uD615","\uC5F4\uAC70\uD615 \uBA64\uBC84","\uC774\uBCA4\uD2B8","\uD544\uB4DC","\uD30C\uC77C","\uD568\uC218","\uC778\uD130\uD398\uC774\uC2A4","\uD0A4","\uBA54\uC11C\uB4DC","\uBAA8\uB4C8","\uB124\uC784\uC2A4\uD398\uC774\uC2A4","Null","\uC22B\uC790","\uAC1C\uCCB4","\uC5F0\uC0B0\uC790","\uD328\uD0A4\uC9C0","\uC18D\uC131","\uBB38\uC790\uC5F4","\uAD6C\uC870\uCCB4","\uD615\uC2DD \uB9E4\uAC1C \uBCC0\uC218","\uBCC0\uC218","{0}({1})"]});
|
||||
|
||||
//# sourceMappingURL=../../../../../min-maps/vs/base/common/worker/simpleWorker.nls.ko.js.map
|
|
@ -0,0 +1,8 @@
|
|||
/*!-----------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Version: 0.46.0(21007360cad28648bdf46282a2592cb47c3a7a6f)
|
||||
* Released under the MIT license
|
||||
* https://github.com/microsoft/vscode/blob/main/LICENSE.txt
|
||||
*-----------------------------------------------------------*/define("vs/base/common/worker/simpleWorker.nls.ru",{"vs/base/common/platform":["_"],"vs/editor/common/languages":["\u043C\u0430\u0441\u0441\u0438\u0432","\u043B\u043E\u0433\u0438\u0447\u0435\u0441\u043A\u043E\u0435 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435","\u043A\u043B\u0430\u0441\u0441","\u043A\u043E\u043D\u0441\u0442\u0430\u043D\u0442\u0430","\u043A\u043E\u043D\u0441\u0442\u0440\u0443\u043A\u0442\u043E\u0440","\u043F\u0435\u0440\u0435\u0447\u0438\u0441\u043B\u0435\u043D\u0438\u0435","\u044D\u043B\u0435\u043C\u0435\u043D\u0442 \u043F\u0435\u0440\u0435\u0447\u0438\u0441\u043B\u0435\u043D\u0438\u044F","\u0441\u043E\u0431\u044B\u0442\u0438\u0435","\u043F\u043E\u043B\u0435","\u0444\u0430\u0439\u043B","\u0444\u0443\u043D\u043A\u0446\u0438\u044F","\u0438\u043D\u0442\u0435\u0440\u0444\u0435\u0439\u0441","\u043A\u043B\u044E\u0447","\u043C\u0435\u0442\u043E\u0434","\u043C\u043E\u0434\u0443\u043B\u044C","\u043F\u0440\u043E\u0441\u0442\u0440\u0430\u043D\u0441\u0442\u0432\u043E \u0438\u043C\u0435\u043D","NULL","\u0447\u0438\u0441\u043B\u043E","\u043E\u0431\u044A\u0435\u043A\u0442","\u043E\u043F\u0435\u0440\u0430\u0442\u043E\u0440","\u043F\u0430\u043A\u0435\u0442","\u0441\u0432\u043E\u0439\u0441\u0442\u0432\u043E","\u0441\u0442\u0440\u043E\u043A\u0430","\u0441\u0442\u0440\u0443\u043A\u0442\u0443\u0440\u0430","\u043F\u0430\u0440\u0430\u043C\u0435\u0442\u0440 \u0442\u0438\u043F\u0430","\u041F\u0435\u0440\u0435\u043C\u0435\u043D\u043D\u0430\u044F","{0} ({1})"]});
|
||||
|
||||
//# sourceMappingURL=../../../../../min-maps/vs/base/common/worker/simpleWorker.nls.ru.js.map
|
|
@ -0,0 +1,8 @@
|
|||
/*!-----------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Version: 0.46.0(21007360cad28648bdf46282a2592cb47c3a7a6f)
|
||||
* Released under the MIT license
|
||||
* https://github.com/microsoft/vscode/blob/main/LICENSE.txt
|
||||
*-----------------------------------------------------------*/define("vs/base/common/worker/simpleWorker.nls.zh-cn",{"vs/base/common/platform":["_"],"vs/editor/common/languages":["\u6570\u7EC4","\u5E03\u5C14\u503C","\u7C7B","\u5E38\u6570","\u6784\u9020\u51FD\u6570","\u679A\u4E3E","\u679A\u4E3E\u6210\u5458","\u4E8B\u4EF6","\u5B57\u6BB5","\u6587\u4EF6","\u51FD\u6570","\u63A5\u53E3","\u952E","\u65B9\u6CD5","\u6A21\u5757","\u547D\u540D\u7A7A\u95F4","Null","\u6570\u5B57","\u5BF9\u8C61","\u8FD0\u7B97\u7B26","\u5305","\u5C5E\u6027","\u5B57\u7B26\u4E32","\u7ED3\u6784","\u7C7B\u578B\u53C2\u6570","\u53D8\u91CF","{0} ({1})"]});
|
||||
|
||||
//# sourceMappingURL=../../../../../min-maps/vs/base/common/worker/simpleWorker.nls.zh-cn.js.map
|
|
@ -0,0 +1,8 @@
|
|||
/*!-----------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Version: 0.46.0(21007360cad28648bdf46282a2592cb47c3a7a6f)
|
||||
* Released under the MIT license
|
||||
* https://github.com/microsoft/vscode/blob/main/LICENSE.txt
|
||||
*-----------------------------------------------------------*/define("vs/base/common/worker/simpleWorker.nls.zh-tw",{"vs/base/common/platform":["_"],"vs/editor/common/languages":["\u9663\u5217","\u5E03\u6797\u503C","\u985E\u5225","\u5E38\u6578","\u5EFA\u69CB\u51FD\u5F0F","\u5217\u8209","\u5217\u8209\u6210\u54E1","\u4E8B\u4EF6","\u6B04\u4F4D","\u6A94\u6848","\u51FD\u5F0F","\u4ECB\u9762","\u7D22\u5F15\u9375","\u65B9\u6CD5","\u6A21\u7D44","\u547D\u540D\u7A7A\u9593","null","\u6578\u5B57","\u7269\u4EF6","\u904B\u7B97\u5B50","\u5957\u4EF6","\u5C6C\u6027","\u5B57\u4E32","\u7D50\u69CB","\u578B\u5225\u53C3\u6578","\u8B8A\u6578","{0} ({1})"]});
|
||||
|
||||
//# sourceMappingURL=../../../../../min-maps/vs/base/common/worker/simpleWorker.nls.zh-tw.js.map
|
27
web/static/monaco/vs/base/worker/workerMain.js
Normal file
27
web/static/monaco/vs/base/worker/workerMain.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
6
web/static/monaco/vs/editor/editor.main.css
Normal file
6
web/static/monaco/vs/editor/editor.main.css
Normal file
File diff suppressed because one or more lines are too long
762
web/static/monaco/vs/editor/editor.main.js
Normal file
762
web/static/monaco/vs/editor/editor.main.js
Normal file
File diff suppressed because one or more lines are too long
15
web/static/monaco/vs/editor/editor.main.nls.de.js
Normal file
15
web/static/monaco/vs/editor/editor.main.nls.de.js
Normal file
File diff suppressed because one or more lines are too long
15
web/static/monaco/vs/editor/editor.main.nls.es.js
Normal file
15
web/static/monaco/vs/editor/editor.main.nls.es.js
Normal file
File diff suppressed because one or more lines are too long
13
web/static/monaco/vs/editor/editor.main.nls.fr.js
Normal file
13
web/static/monaco/vs/editor/editor.main.nls.fr.js
Normal file
File diff suppressed because one or more lines are too long
13
web/static/monaco/vs/editor/editor.main.nls.it.js
Normal file
13
web/static/monaco/vs/editor/editor.main.nls.it.js
Normal file
File diff suppressed because one or more lines are too long
15
web/static/monaco/vs/editor/editor.main.nls.ja.js
Normal file
15
web/static/monaco/vs/editor/editor.main.nls.ja.js
Normal file
File diff suppressed because one or more lines are too long
13
web/static/monaco/vs/editor/editor.main.nls.js
Normal file
13
web/static/monaco/vs/editor/editor.main.nls.js
Normal file
File diff suppressed because one or more lines are too long
13
web/static/monaco/vs/editor/editor.main.nls.ko.js
Normal file
13
web/static/monaco/vs/editor/editor.main.nls.ko.js
Normal file
File diff suppressed because one or more lines are too long
15
web/static/monaco/vs/editor/editor.main.nls.ru.js
Normal file
15
web/static/monaco/vs/editor/editor.main.nls.ru.js
Normal file
File diff suppressed because one or more lines are too long
15
web/static/monaco/vs/editor/editor.main.nls.zh-cn.js
Normal file
15
web/static/monaco/vs/editor/editor.main.nls.zh-cn.js
Normal file
File diff suppressed because one or more lines are too long
13
web/static/monaco/vs/editor/editor.main.nls.zh-tw.js
Normal file
13
web/static/monaco/vs/editor/editor.main.nls.zh-tw.js
Normal file
File diff suppressed because one or more lines are too long
13
web/static/monaco/vs/language/css/cssMode.js
Normal file
13
web/static/monaco/vs/language/css/cssMode.js
Normal file
File diff suppressed because one or more lines are too long
78
web/static/monaco/vs/language/css/cssWorker.js
Normal file
78
web/static/monaco/vs/language/css/cssWorker.js
Normal file
File diff suppressed because one or more lines are too long
13
web/static/monaco/vs/language/html/htmlMode.js
Normal file
13
web/static/monaco/vs/language/html/htmlMode.js
Normal file
File diff suppressed because one or more lines are too long
452
web/static/monaco/vs/language/html/htmlWorker.js
Normal file
452
web/static/monaco/vs/language/html/htmlWorker.js
Normal file
File diff suppressed because one or more lines are too long
15
web/static/monaco/vs/language/json/jsonMode.js
Normal file
15
web/static/monaco/vs/language/json/jsonMode.js
Normal file
File diff suppressed because one or more lines are too long
36
web/static/monaco/vs/language/json/jsonWorker.js
Normal file
36
web/static/monaco/vs/language/json/jsonWorker.js
Normal file
File diff suppressed because one or more lines are too long
20
web/static/monaco/vs/language/typescript/tsMode.js
Normal file
20
web/static/monaco/vs/language/typescript/tsMode.js
Normal file
File diff suppressed because one or more lines are too long
37016
web/static/monaco/vs/language/typescript/tsWorker.js
Normal file
37016
web/static/monaco/vs/language/typescript/tsWorker.js
Normal file
File diff suppressed because one or more lines are too long
11
web/static/monaco/vs/loader.js
Normal file
11
web/static/monaco/vs/loader.js
Normal file
File diff suppressed because one or more lines are too long
|
@ -3,7 +3,7 @@
|
|||
<h1 class="text-lg font-semibold text-gray-900">
|
||||
Creating new Healthcheck.
|
||||
</h1>
|
||||
<form class="max-w-sm mt-4" action="/settings/healthchecks/create" method="post">
|
||||
<form class="mt-4" action="/settings/healthchecks/create" method="post">
|
||||
<div class="mb-5">
|
||||
<label for="name" class="block mb-2 text-sm font-medium text-gray-900">Name</label>
|
||||
<input type="name" name="name" id="name" placeholder="Github.com" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5"/>
|
||||
|
@ -17,21 +17,51 @@
|
|||
<input type="text" name="schedule" id="schedule" placeholder="* * * * *" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5"/>
|
||||
</div>
|
||||
<div class="mb-5">
|
||||
<label for="script" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Your message</label>
|
||||
<textarea id="script" name="script" rows="4" class="block p-2.5 w-full text-sm text-gray-900 bg-gray-50 rounded-lg border border-gray-300 focus:ring-blue-500 focus:border-blue-500" placeholder="import http from 'k6/http';
|
||||
import { sleep } from 'k6';
|
||||
<label for="script" class="block mb-2 text-sm font-medium text-gray-900">Script</label>
|
||||
<input required type="hidden" id="script" name="script">
|
||||
<div id="editor" class="block w-full h-96 rounded-lg border border-gray-300 overflow-hidden"></div>
|
||||
</div>
|
||||
<button type="submit" onclick="save()" class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm w-full sm:w-auto px-5 py-2.5 text-center">Create</button>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
|
||||
<script src="/static/monaco/vs/loader.js"></script>
|
||||
<script>
|
||||
function save() {
|
||||
const script = window.editor.getValue();
|
||||
document.getElementById('script').value = script;
|
||||
}
|
||||
|
||||
script = `import http from 'k6/http';
|
||||
|
||||
export const options = {
|
||||
vus: 10, // not working atm
|
||||
duration: '30s', // not working atm
|
||||
thresholds: {
|
||||
// http errors should be less than 1%
|
||||
http_req_failed: ['rate<0.01'],
|
||||
},
|
||||
vus: 10,
|
||||
duration: '5s',
|
||||
};
|
||||
|
||||
export default function () {
|
||||
http.get('https://test.k6.io');
|
||||
sleep(1);
|
||||
}"></textarea>
|
||||
</div>
|
||||
<button type="submit" class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm w-full sm:w-auto px-5 py-2.5 text-center">Create</button>
|
||||
</form>
|
||||
</section>
|
||||
http.get('https://example.com');
|
||||
}
|
||||
`
|
||||
|
||||
require.config({ paths: { vs: '/static/monaco/vs' } });
|
||||
require(['vs/editor/editor.main'], function () {
|
||||
window.editor = monaco.editor.create(document.getElementById('editor'), {
|
||||
value: script,
|
||||
language: 'javascript',
|
||||
minimap: { enabled: false },
|
||||
});
|
||||
|
||||
const divElem = document.getElementById('editor');
|
||||
const resizeObserver = new ResizeObserver(entries => {
|
||||
window.editor.layout();
|
||||
});
|
||||
resizeObserver.observe(divElem);
|
||||
});
|
||||
</script>
|
||||
{{end}}
|
||||
|
|
Loading…
Reference in a new issue