mirror of
https://github.com/mentos1386/zdravko.git
synced 2024-11-21 23:33:34 +00:00
feat: check history and ui fixes
This commit is contained in:
parent
813c76fc3e
commit
da53c04659
15 changed files with 215 additions and 97 deletions
|
@ -142,7 +142,10 @@ const (
|
||||||
type TargetHistory struct {
|
type TargetHistory struct {
|
||||||
CreatedAt *Time `db:"created_at"`
|
CreatedAt *Time `db:"created_at"`
|
||||||
|
|
||||||
TargetId string `db:"target_id"`
|
TargetId string `db:"target_id"`
|
||||||
Status TargetStatus `db:"status"`
|
WorkerGroupId string `db:"worker_group_id"`
|
||||||
Note string `db:"note"`
|
CheckId string `db:"check_id"`
|
||||||
|
|
||||||
|
Status TargetStatus `db:"status"`
|
||||||
|
Note string `db:"note"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,15 +92,19 @@ END;
|
||||||
-- +migrate StatementEnd
|
-- +migrate StatementEnd
|
||||||
|
|
||||||
CREATE TABLE target_histories (
|
CREATE TABLE target_histories (
|
||||||
target_id TEXT NOT NULL,
|
target_id TEXT NOT NULL,
|
||||||
|
worker_group_id TEXT NOT NULL,
|
||||||
|
check_id TEXT NOT NULL,
|
||||||
|
|
||||||
status TEXT NOT NULL,
|
status TEXT NOT NULL,
|
||||||
note TEXT NOT NULL,
|
note TEXT NOT NULL,
|
||||||
|
|
||||||
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ')),
|
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ')),
|
||||||
|
|
||||||
PRIMARY KEY (target_id, created_at),
|
PRIMARY KEY (target_id, worker_group_id, check_id, created_at),
|
||||||
CONSTRAINT fk_target_histories_target FOREIGN KEY (target_id) REFERENCES targets(id) ON DELETE CASCADE
|
CONSTRAINT fk_target_histories_target FOREIGN KEY (target_id) REFERENCES targets(id) ON DELETE CASCADE,
|
||||||
|
CONSTRAINT fk_target_histories_worker_group FOREIGN KEY (worker_group_id) REFERENCES worker_groups(id) ON DELETE CASCADE,
|
||||||
|
CONSTRAINT fk_target_histories_check FOREIGN KEY (check_id) REFERENCES checks(id) ON DELETE CASCADE
|
||||||
) STRICT;
|
) STRICT;
|
||||||
|
|
||||||
-- +migrate Down
|
-- +migrate Down
|
||||||
|
|
|
@ -19,9 +19,11 @@ func (a *Activities) AddTargetHistory(ctx context.Context, param temporal.Activi
|
||||||
}
|
}
|
||||||
|
|
||||||
err := services.AddHistoryForTarget(ctx, a.db, &models.TargetHistory{
|
err := services.AddHistoryForTarget(ctx, a.db, &models.TargetHistory{
|
||||||
TargetId: param.Target.Id,
|
TargetId: param.Target.Id,
|
||||||
Status: status,
|
WorkerGroupId: param.WorkerGroupId,
|
||||||
Note: param.Note,
|
CheckId: param.CheckId,
|
||||||
|
Status: status,
|
||||||
|
Note: param.Note,
|
||||||
})
|
})
|
||||||
|
|
||||||
return &temporal.ActivityAddTargetHistoryResult{}, err
|
return &temporal.ActivityAddTargetHistoryResult{}, err
|
||||||
|
|
|
@ -71,7 +71,8 @@ func (h *BaseHandler) SettingsChecksGET(c echo.Context) error {
|
||||||
for i, check := range checks {
|
for i, check := range checks {
|
||||||
state, err := services.GetCheckState(context.Background(), h.temporal, check.Id)
|
state, err := services.GetCheckState(context.Background(), h.temporal, check.Id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
h.logger.Error("Failed to get check state", "error", err)
|
||||||
|
state = models.CheckStateUnknown
|
||||||
}
|
}
|
||||||
checksWithState[i] = &CheckWithWorkerGroupsAndState{
|
checksWithState[i] = &CheckWithWorkerGroupsAndState{
|
||||||
CheckWithWorkerGroups: check,
|
CheckWithWorkerGroups: check,
|
||||||
|
|
|
@ -267,7 +267,7 @@ func CreateOrUpdateCheckSchedule(
|
||||||
ID: getScheduleId(check.Id),
|
ID: getScheduleId(check.Id),
|
||||||
Workflow: internaltemporal.WorkflowCheckName,
|
Workflow: internaltemporal.WorkflowCheckName,
|
||||||
Args: args,
|
Args: args,
|
||||||
TaskQueue: "default",
|
TaskQueue: internaltemporal.TEMPORAL_SERVER_QUEUE,
|
||||||
RetryPolicy: &temporal.RetryPolicy{
|
RetryPolicy: &temporal.RetryPolicy{
|
||||||
MaximumAttempts: 3,
|
MaximumAttempts: 3,
|
||||||
},
|
},
|
||||||
|
|
|
@ -5,20 +5,26 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/mentos1386/zdravko/internal/temporal"
|
||||||
|
"go.temporal.io/api/enums/v1"
|
||||||
"go.temporal.io/api/workflowservice/v1"
|
"go.temporal.io/api/workflowservice/v1"
|
||||||
"go.temporal.io/sdk/client"
|
"go.temporal.io/sdk/client"
|
||||||
)
|
)
|
||||||
|
|
||||||
type CheckHistory struct {
|
type CheckHistory struct {
|
||||||
CheckId string
|
CheckId string
|
||||||
Status string
|
Status string
|
||||||
Duration time.Duration
|
Duration time.Duration
|
||||||
|
StartTime time.Time
|
||||||
|
EndTime time.Time
|
||||||
|
WorkerGroupName string
|
||||||
|
Note string
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetLastNCheckHistory(ctx context.Context, temporal client.Client, n int32) ([]*CheckHistory, error) {
|
func GetLastNCheckHistory(ctx context.Context, t client.Client, n int32) ([]*CheckHistory, error) {
|
||||||
var checkHistory []*CheckHistory
|
var checkHistory []*CheckHistory
|
||||||
|
|
||||||
response, err := temporal.ListWorkflow(ctx, &workflowservice.ListWorkflowExecutionsRequest{
|
response, err := t.ListWorkflow(ctx, &workflowservice.ListWorkflowExecutionsRequest{
|
||||||
PageSize: n,
|
PageSize: n,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -29,21 +35,37 @@ func GetLastNCheckHistory(ctx context.Context, temporal client.Client, n int32)
|
||||||
|
|
||||||
for _, execution := range executions {
|
for _, execution := range executions {
|
||||||
scheduleId := string(execution.GetSearchAttributes().GetIndexedFields()["TemporalScheduledById"].Data)
|
scheduleId := string(execution.GetSearchAttributes().GetIndexedFields()["TemporalScheduledById"].Data)
|
||||||
checkId := scheduleId[len("check-"):]
|
|
||||||
|
// Remove the quotes around the checkId and the prefix.
|
||||||
|
checkId := scheduleId[len("\"check-") : len(scheduleId)-1]
|
||||||
|
|
||||||
|
var result temporal.WorkflowCheckResult
|
||||||
|
if execution.Status != enums.WORKFLOW_EXECUTION_STATUS_RUNNING {
|
||||||
|
workflowRun := t.GetWorkflow(ctx, execution.GetExecution().GetWorkflowId(), execution.GetExecution().GetRunId())
|
||||||
|
err := workflowRun.Get(ctx, &result)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
checkHistory = append(checkHistory, &CheckHistory{
|
checkHistory = append(checkHistory, &CheckHistory{
|
||||||
CheckId: checkId,
|
CheckId: checkId,
|
||||||
Duration: execution.CloseTime.AsTime().Sub(execution.StartTime.AsTime()),
|
Duration: execution.CloseTime.AsTime().Sub(execution.StartTime.AsTime()),
|
||||||
Status: execution.Status.String(),
|
StartTime: execution.StartTime.AsTime(),
|
||||||
|
EndTime: execution.CloseTime.AsTime(),
|
||||||
|
Status: execution.Status.String(),
|
||||||
|
WorkerGroupName: execution.GetTaskQueue(),
|
||||||
|
Note: result.Note,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return checkHistory, nil
|
return checkHistory, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetCheckHistoryForCheck(ctx context.Context, temporal client.Client, checkId string) ([]*CheckHistory, error) {
|
func GetCheckHistoryForCheck(ctx context.Context, t client.Client, checkId string) ([]*CheckHistory, error) {
|
||||||
var checkHistory []*CheckHistory
|
var checkHistory []*CheckHistory
|
||||||
|
|
||||||
response, err := temporal.ListWorkflow(ctx, &workflowservice.ListWorkflowExecutionsRequest{
|
response, err := t.ListWorkflow(ctx, &workflowservice.ListWorkflowExecutionsRequest{
|
||||||
PageSize: 10,
|
PageSize: 10,
|
||||||
Query: fmt.Sprintf(`TemporalScheduledById = "%s"`, getScheduleId(checkId)),
|
Query: fmt.Sprintf(`TemporalScheduledById = "%s"`, getScheduleId(checkId)),
|
||||||
})
|
})
|
||||||
|
@ -55,11 +77,27 @@ func GetCheckHistoryForCheck(ctx context.Context, temporal client.Client, checkI
|
||||||
|
|
||||||
for _, execution := range executions {
|
for _, execution := range executions {
|
||||||
scheduleId := string(execution.GetSearchAttributes().GetIndexedFields()["TemporalScheduledById"].Data)
|
scheduleId := string(execution.GetSearchAttributes().GetIndexedFields()["TemporalScheduledById"].Data)
|
||||||
checkId := scheduleId[len("check-"):]
|
|
||||||
|
// Remove the quotes around the checkId and the prefix.
|
||||||
|
checkId := scheduleId[len("\"check-") : len(scheduleId)-1]
|
||||||
|
|
||||||
|
var result temporal.WorkflowCheckResult
|
||||||
|
if execution.Status != enums.WORKFLOW_EXECUTION_STATUS_RUNNING {
|
||||||
|
workflowRun := t.GetWorkflow(ctx, execution.GetExecution().GetWorkflowId(), execution.GetExecution().GetRunId())
|
||||||
|
err := workflowRun.Get(ctx, &result)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
checkHistory = append(checkHistory, &CheckHistory{
|
checkHistory = append(checkHistory, &CheckHistory{
|
||||||
CheckId: checkId,
|
CheckId: checkId,
|
||||||
Duration: execution.CloseTime.AsTime().Sub(execution.StartTime.AsTime()),
|
Duration: execution.CloseTime.AsTime().Sub(execution.StartTime.AsTime()),
|
||||||
Status: execution.Status.String(),
|
StartTime: execution.StartTime.AsTime(),
|
||||||
|
EndTime: execution.CloseTime.AsTime(),
|
||||||
|
Status: execution.Status.String(),
|
||||||
|
WorkerGroupName: execution.GetTaskQueue(),
|
||||||
|
Note: result.Note,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,13 +3,15 @@ package services
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/mentos1386/zdravko/database/models"
|
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
|
"github.com/mentos1386/zdravko/database/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
type TargetHistory struct {
|
type TargetHistory struct {
|
||||||
*models.TargetHistory
|
*models.TargetHistory
|
||||||
TargetName string `db:"target_name"`
|
TargetName string `db:"target_name"`
|
||||||
|
WorkerGroupName string `db:"worker_group_name"`
|
||||||
|
CheckName string `db:"check_name"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetLastNTargetHistory(ctx context.Context, db *sqlx.DB, n int) ([]*TargetHistory, error) {
|
func GetLastNTargetHistory(ctx context.Context, db *sqlx.DB, n int) ([]*TargetHistory, error) {
|
||||||
|
@ -17,9 +19,13 @@ func GetLastNTargetHistory(ctx context.Context, db *sqlx.DB, n int) ([]*TargetHi
|
||||||
err := db.SelectContext(ctx, &targetHistory, `
|
err := db.SelectContext(ctx, &targetHistory, `
|
||||||
SELECT
|
SELECT
|
||||||
th.*,
|
th.*,
|
||||||
t.name AS target_name
|
t.name AS target_name,
|
||||||
|
wg.name AS worker_group_name,
|
||||||
|
c.name AS check_name
|
||||||
FROM target_histories th
|
FROM target_histories th
|
||||||
LEFT JOIN targets t ON th.target_id = t.id
|
LEFT JOIN targets t ON th.target_id = t.id
|
||||||
|
LEFT JOIN worker_groups wg ON th.worker_group_id = wg.id
|
||||||
|
LEFT JOIN checks c ON th.check_id = c.id
|
||||||
WHERE th.target_id = $1
|
WHERE th.target_id = $1
|
||||||
ORDER BY th.created_at DESC
|
ORDER BY th.created_at DESC
|
||||||
LIMIT $1
|
LIMIT $1
|
||||||
|
@ -32,9 +38,13 @@ func GetTargetHistoryForTarget(ctx context.Context, db *sqlx.DB, targetId string
|
||||||
err := db.SelectContext(ctx, &targetHistory, `
|
err := db.SelectContext(ctx, &targetHistory, `
|
||||||
SELECT
|
SELECT
|
||||||
th.*,
|
th.*,
|
||||||
t.name AS target_name
|
t.name AS target_name,
|
||||||
|
wg.name AS worker_group_name,
|
||||||
|
c.name AS check_name
|
||||||
FROM target_histories th
|
FROM target_histories th
|
||||||
LEFT JOIN targets t ON th.target_id = t.id
|
LEFT JOIN targets t ON th.target_id = t.id
|
||||||
|
LEFT JOIN worker_groups wg ON th.worker_group_id = wg.id
|
||||||
|
LEFT JOIN checks c ON th.check_id = c.id
|
||||||
WHERE th.target_id = $1
|
WHERE th.target_id = $1
|
||||||
ORDER BY th.created_at DESC
|
ORDER BY th.created_at DESC
|
||||||
`, targetId)
|
`, targetId)
|
||||||
|
@ -46,10 +56,14 @@ func AddHistoryForTarget(ctx context.Context, db *sqlx.DB, history *models.Targe
|
||||||
`
|
`
|
||||||
INSERT INTO target_histories (
|
INSERT INTO target_histories (
|
||||||
target_id,
|
target_id,
|
||||||
|
worker_group_id,
|
||||||
|
check_id,
|
||||||
status,
|
status,
|
||||||
note
|
note
|
||||||
) VALUES (
|
) VALUES (
|
||||||
:target_id,
|
:target_id,
|
||||||
|
:worker_group_id,
|
||||||
|
:check_id,
|
||||||
:status,
|
:status,
|
||||||
:note
|
:note
|
||||||
)`,
|
)`,
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package workflows
|
package workflows
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log/slog"
|
|
||||||
"sort"
|
"sort"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -9,7 +8,7 @@ import (
|
||||||
"go.temporal.io/sdk/workflow"
|
"go.temporal.io/sdk/workflow"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (w *Workflows) CheckWorkflowDefinition(ctx workflow.Context, param temporal.WorkflowCheckParam) error {
|
func (w *Workflows) CheckWorkflowDefinition(ctx workflow.Context, param temporal.WorkflowCheckParam) (*temporal.WorkflowCheckResult, error) {
|
||||||
workerGroupIds := param.WorkerGroupIds
|
workerGroupIds := param.WorkerGroupIds
|
||||||
sort.Strings(workerGroupIds)
|
sort.Strings(workerGroupIds)
|
||||||
|
|
||||||
|
@ -25,7 +24,7 @@ func (w *Workflows) CheckWorkflowDefinition(ctx workflow.Context, param temporal
|
||||||
},
|
},
|
||||||
).Get(ctx, &targetsFilterResult)
|
).Get(ctx, &targetsFilterResult)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, target := range targetsFilterResult.Targets {
|
for _, target := range targetsFilterResult.Targets {
|
||||||
|
@ -43,7 +42,7 @@ func (w *Workflows) CheckWorkflowDefinition(ctx workflow.Context, param temporal
|
||||||
},
|
},
|
||||||
).Get(ctx, &checkResult)
|
).Get(ctx, &checkResult)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
status := temporal.AddTargetHistoryStatusFailure
|
status := temporal.AddTargetHistoryStatusFailure
|
||||||
|
@ -59,18 +58,20 @@ func (w *Workflows) CheckWorkflowDefinition(ctx workflow.Context, param temporal
|
||||||
}),
|
}),
|
||||||
temporal.ActivityAddTargetHistoryName,
|
temporal.ActivityAddTargetHistoryName,
|
||||||
&temporal.ActivityAddTargetHistoryParam{
|
&temporal.ActivityAddTargetHistoryParam{
|
||||||
Target: target,
|
Target: target,
|
||||||
Status: status,
|
WorkerGroupId: workerGroupId,
|
||||||
Note: checkResult.Note,
|
CheckId: param.CheckId,
|
||||||
|
Status: status,
|
||||||
|
Note: checkResult.Note,
|
||||||
},
|
},
|
||||||
).Get(ctx, &addTargetHistoryResult)
|
).Get(ctx, &addTargetHistoryResult)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
slog.Info("Check %s status: %s", param.CheckId, status)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return &temporal.WorkflowCheckResult{
|
||||||
|
Note: "Check workflow completed",
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,9 +9,11 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
type ActivityAddTargetHistoryParam struct {
|
type ActivityAddTargetHistoryParam struct {
|
||||||
Target *Target
|
Target *Target
|
||||||
Status AddTargetHistoryStatus
|
WorkerGroupId string
|
||||||
Note string
|
CheckId string
|
||||||
|
Status AddTargetHistoryStatus
|
||||||
|
Note string
|
||||||
}
|
}
|
||||||
|
|
||||||
type ActivityAddTargetHistoryResult struct {
|
type ActivityAddTargetHistoryResult struct {
|
||||||
|
|
|
@ -7,4 +7,8 @@ type WorkflowCheckParam struct {
|
||||||
WorkerGroupIds []string
|
WorkerGroupIds []string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type WorkflowCheckResult struct {
|
||||||
|
Note string
|
||||||
|
}
|
||||||
|
|
||||||
const WorkflowCheckName = "CHECK_WORKFLOW"
|
const WorkflowCheckName = "CHECK_WORKFLOW"
|
||||||
|
|
|
@ -991,6 +991,11 @@ video {
|
||||||
background-color: rgb(253 186 116 / var(--tw-bg-opacity));
|
background-color: rgb(253 186 116 / var(--tw-bg-opacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.bg-purple-100 {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(243 232 255 / var(--tw-bg-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
.bg-red-100 {
|
.bg-red-100 {
|
||||||
--tw-bg-opacity: 1;
|
--tw-bg-opacity: 1;
|
||||||
background-color: rgb(254 226 226 / var(--tw-bg-opacity));
|
background-color: rgb(254 226 226 / var(--tw-bg-opacity));
|
||||||
|
@ -1225,6 +1230,11 @@ video {
|
||||||
color: rgb(22 101 52 / var(--tw-text-opacity));
|
color: rgb(22 101 52 / var(--tw-text-opacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.text-purple-800 {
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
color: rgb(107 33 168 / var(--tw-text-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
.text-red-600 {
|
.text-red-600 {
|
||||||
--tw-text-opacity: 1;
|
--tw-text-opacity: 1;
|
||||||
color: rgb(220 38 38 / var(--tw-text-opacity));
|
color: rgb(220 38 38 / var(--tw-text-opacity));
|
||||||
|
|
|
@ -118,7 +118,8 @@
|
||||||
<th>Check ID</th>
|
<th>Check ID</th>
|
||||||
<th>Status</th>
|
<th>Status</th>
|
||||||
<th>Worker Group</th>
|
<th>Worker Group</th>
|
||||||
<th>Created At</th>
|
<th>Started At</th>
|
||||||
|
<th>Ended At</th>
|
||||||
<th>Duration</th>
|
<th>Duration</th>
|
||||||
<th>Note</th>
|
<th>Note</th>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -130,36 +131,35 @@
|
||||||
<td>{{ .CheckId }}</td>
|
<td>{{ .CheckId }}</td>
|
||||||
<td>
|
<td>
|
||||||
<span
|
<span
|
||||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full {{ if eq .Status "SUCCESS" }}
|
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-blue-100 text-blue-800"
|
||||||
bg-green-100 text-green-800
|
|
||||||
{{ else }}
|
|
||||||
bg-red-100 text-red-800
|
|
||||||
{{ end }}"
|
|
||||||
>
|
>
|
||||||
{{ .Status }}
|
{{ .Status }}...
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<span
|
<span
|
||||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-blue-100 text-blue-800"
|
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-blue-100 text-blue-800"
|
||||||
>
|
>
|
||||||
{ .WorkerGroupName }
|
{{ .WorkerGroupName }}
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
<td>{ .CreatedAt.Time.Format "2006-01-02 15:04:05" }</td>
|
<td>{{ .StartTime.Format "2006-01-02 15:04:05" }}</td>
|
||||||
<td>/</td>
|
<td></td>
|
||||||
<td class="whitespace-normal">/</td>
|
<td></td>
|
||||||
|
<td class="whitespace-normal"></td>
|
||||||
</tr>
|
</tr>
|
||||||
{{ else }}
|
{{ else }}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ .CheckId }}</td>
|
<td>{{ .CheckId }}</td>
|
||||||
<td>
|
<td>
|
||||||
<span
|
<span
|
||||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full {{ if eq .Status "SUCCESS" }}
|
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full
|
||||||
bg-green-100 text-green-800
|
{{ if eq .Status "Completed" }}
|
||||||
|
bg-purple-100 text-purple-800
|
||||||
{{ else }}
|
{{ else }}
|
||||||
bg-red-100 text-red-800
|
bg-red-100 text-red-800
|
||||||
{{ end }}"
|
{{ end }}
|
||||||
|
"
|
||||||
>
|
>
|
||||||
{{ .Status }}
|
{{ .Status }}
|
||||||
</span>
|
</span>
|
||||||
|
@ -168,12 +168,13 @@
|
||||||
<span
|
<span
|
||||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-blue-100 text-blue-800"
|
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-blue-100 text-blue-800"
|
||||||
>
|
>
|
||||||
{ .WorkerGroupName }
|
{{ .WorkerGroupName }}
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
<td>{ .CreatedAt.Time.Format "2006-01-02 15:04:05" }</td>
|
<td>{{ .StartTime.Format "2006-01-02 15:04:05" }}</td>
|
||||||
<td>{{ .Duration }}</td>
|
<td>{{ .EndTime.Format "2006-01-02 15:04:05" }}</td>
|
||||||
<td class="whitespace-normal">{ .Note }</td>
|
<td>{{ DurationRoundMillisecond .Duration }}</td>
|
||||||
|
<td class="whitespace-normal">{{ .Note }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
|
@ -42,52 +42,76 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<section class="mt-4">
|
<section>
|
||||||
<table>
|
<table>
|
||||||
<caption>
|
<caption>
|
||||||
Execution History
|
History
|
||||||
<p>Last 10 executions for all checks and worker groups.</p>
|
<p>Last 10 executions.</p>
|
||||||
</caption>
|
</caption>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Check</th>
|
<th>Check ID</th>
|
||||||
<th>Worker Group</th>
|
|
||||||
<th>Status</th>
|
<th>Status</th>
|
||||||
<th>Executed At</th>
|
<th>Worker Group</th>
|
||||||
|
<th>Started At</th>
|
||||||
|
<th>Ended At</th>
|
||||||
|
<th>Duration</th>
|
||||||
<th>Note</th>
|
<th>Note</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{{ range .History }}
|
{{ range .History }}
|
||||||
<tr>
|
{{ if eq .Status "Running" }}
|
||||||
<th>
|
<tr>
|
||||||
<a
|
<td>{{ .CheckId }}</td>
|
||||||
class="underline hover:text-blue-600"
|
<td>
|
||||||
href="/settings/checks/{{ .CheckId }}"
|
<span
|
||||||
>{{ .CheckId }}</a
|
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-blue-100 text-blue-800"
|
||||||
>
|
>
|
||||||
</th>
|
{{ .Status }}...
|
||||||
<td>
|
</span>
|
||||||
<span
|
</td>
|
||||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-blue-100 text-blue-800"
|
<td>
|
||||||
>
|
<span
|
||||||
{ .WorkerGroupName }
|
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-blue-100 text-blue-800"
|
||||||
</span>
|
>
|
||||||
</td>
|
{{ .WorkerGroupName }}
|
||||||
<td>
|
</span>
|
||||||
<span
|
</td>
|
||||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full {{ if eq .Status "SUCCESS" }}
|
<td>{{ .StartTime.Format "2006-01-02 15:04:05" }}</td>
|
||||||
bg-green-100 text-green-800
|
<td></td>
|
||||||
{{ else }}
|
<td></td>
|
||||||
bg-red-100 text-red-800
|
<td class="whitespace-normal"></td>
|
||||||
{{ end }}"
|
</tr>
|
||||||
>
|
{{ else }}
|
||||||
{{ .Status }}
|
<tr>
|
||||||
</span>
|
<td>{{ .CheckId }}</td>
|
||||||
</td>
|
<td>
|
||||||
<td>{ .CreatedAt.Time.Format "2006-01-02 15:04:05" }</td>
|
<span
|
||||||
<td class="whitespace-normal">{ .Note }</td>
|
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full
|
||||||
</tr>
|
{{ if eq .Status "Completed" }}
|
||||||
|
bg-purple-100 text-purple-800
|
||||||
|
{{ else }}
|
||||||
|
bg-red-100 text-red-800
|
||||||
|
{{ end }}
|
||||||
|
"
|
||||||
|
>
|
||||||
|
{{ .Status }}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span
|
||||||
|
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-blue-100 text-blue-800"
|
||||||
|
>
|
||||||
|
{{ .WorkerGroupName }}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
<td>{{ .StartTime.Format "2006-01-02 15:04:05" }}</td>
|
||||||
|
<td>{{ .EndTime.Format "2006-01-02 15:04:05" }}</td>
|
||||||
|
<td>{{ DurationRoundMillisecond .Duration }}</td>
|
||||||
|
<td class="whitespace-normal">{{ .Note }}</td>
|
||||||
|
</tr>
|
||||||
|
{{ end }}
|
||||||
{{ end }}
|
{{ end }}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
|
@ -116,6 +116,7 @@
|
||||||
<tr>
|
<tr>
|
||||||
<th>Status</th>
|
<th>Status</th>
|
||||||
<th>Worker Group</th>
|
<th>Worker Group</th>
|
||||||
|
<th>Check</th>
|
||||||
<th>Created At</th>
|
<th>Created At</th>
|
||||||
<th>Duration</th>
|
<th>Duration</th>
|
||||||
<th>Note</th>
|
<th>Note</th>
|
||||||
|
@ -142,6 +143,13 @@
|
||||||
{{ .WorkerGroupName }}
|
{{ .WorkerGroupName }}
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
|
<td>
|
||||||
|
<span
|
||||||
|
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-blue-100 text-blue-800"
|
||||||
|
>
|
||||||
|
{{ .CheckName }}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{{ .CreatedAt.Time.Format "2006-01-02 15:04:05" }}
|
{{ .CreatedAt.Time.Format "2006-01-02 15:04:05" }}
|
||||||
</td>
|
</td>
|
||||||
|
|
|
@ -26,6 +26,12 @@ func load(files ...string) *template.Template {
|
||||||
|
|
||||||
t := template.New("default").Funcs(
|
t := template.New("default").Funcs(
|
||||||
template.FuncMap{
|
template.FuncMap{
|
||||||
|
"DurationRoundSecond": func(d time.Duration) time.Duration {
|
||||||
|
return d.Round(time.Second)
|
||||||
|
},
|
||||||
|
"DurationRoundMillisecond": func(d time.Duration) time.Duration {
|
||||||
|
return d.Round(time.Millisecond)
|
||||||
|
},
|
||||||
"StringsJoin": strings.Join,
|
"StringsJoin": strings.Join,
|
||||||
"Now": time.Now,
|
"Now": time.Now,
|
||||||
"ScriptUnescapeString": script.UnescapeString,
|
"ScriptUnescapeString": script.UnescapeString,
|
||||||
|
|
Loading…
Reference in a new issue