Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(worker-visibility): extend worker table with 5 fields #772

Merged
merged 31 commits into from
Jun 16, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
bd25ad9
feat(worker-availability): extend worker table with 4 fields
KellyMerrick Feb 27, 2023
a38c69f
Merge branch 'main' into worker_visibility
KellyMerrick Feb 27, 2023
723e453
fix(main): merge main into branch
KellyMerrick Apr 6, 2023
5483e0f
fix(api-metrics.go): fix merge conflicts
KellyMerrick Apr 6, 2023
fdb8cb8
Merge branch 'worker_visibility' of github.com:go-vela/server into wo…
KellyMerrick Apr 6, 2023
822800a
fix(api-worker.go): clean up merge text
KellyMerrick Apr 6, 2023
98691a5
Merge branch 'main' into worker_visibility
KellyMerrick Apr 12, 2023
540d7d0
fix(api/worker.go): correct closing brace
KellyMerrick Apr 12, 2023
55dba0a
Merge branch 'main' of github.com:go-vela/server into worker_visibility
KellyMerrick Apr 26, 2023
11f5a1e
Merge branch 'main' into worker_visibility
KellyMerrick Apr 26, 2023
e1f128c
feat(metrics.go): update list of worker statuses; merge in main
KellyMerrick May 17, 2023
56f3e25
Merge branch 'worker_visibility' of github.com:go-vela/server into wo…
KellyMerrick May 17, 2023
b9ae9af
feat(metrics.go): add idle_worker_count
KellyMerrick May 18, 2023
49ca50d
feat(worker): modify permissions to all worker for work towards updat…
KellyMerrick May 22, 2023
e5e7c08
fix(runningBuildIDs): allow nil update to list
KellyMerrick May 31, 2023
e8eda6a
feat(worker): update last_status_update_at in the database
KellyMerrick Jun 1, 2023
4d79db4
feat(worker): add LastBuildStartedAt field
KellyMerrick Jun 2, 2023
6073481
fix(worker): allow update of last build started and finished
KellyMerrick Jun 2, 2023
b4f39c4
Merge branch 'main' into worker_visibility
KellyMerrick Jun 2, 2023
3f60d07
Merge branch 'main' of github.com:go-vela/server into worker_visibility
KellyMerrick Jun 2, 2023
2e22e2f
Merge branch 'main' of github.com:go-vela/server into worker_visibility
KellyMerrick Jun 8, 2023
1d36eb7
Merge branch 'main' of github.com:go-vela/server into worker_visibility
KellyMerrick Jun 8, 2023
99541ac
test(worker): ensure all new fields are added to relevant tests
KellyMerrick Jun 8, 2023
b2707d9
Merge branch 'worker_visibility' of github.com:go-vela/server into wo…
KellyMerrick Jun 8, 2023
d3dd14f
Merge branch 'main' of github.com:go-vela/server into worker_visibility
KellyMerrick Jun 12, 2023
a79873a
chore(worker_visibility): pull in types and server main
KellyMerrick Jun 12, 2023
8640cd0
chore(worker_visibility): pull in types and server main
KellyMerrick Jun 14, 2023
c648ab8
addressed feedback
timhuynh94 Jun 14, 2023
999a1db
fix(running_build_ids): correct copy/paste, size should be 500
KellyMerrick Jun 15, 2023
56aea85
fix(running-builds): not requiring a list in body for updates
KellyMerrick Jun 15, 2023
60996b8
Merge branch 'main' into worker_visibility
KellyMerrick Jun 15, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 101 additions & 5 deletions api/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (

"github.com/gin-gonic/gin"
"github.com/go-vela/server/database"
"github.com/go-vela/types/constants"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
"github.com/prometheus/client_golang/prometheus/promhttp"
Expand Down Expand Up @@ -53,6 +54,19 @@ type MetricsQueryParameters struct {
ActiveWorkerCount bool `form:"active_worker_count"`
// InactiveWorkerCount represents total number of inactive workers
InactiveWorkerCount bool `form:"inactive_worker_count"`

// UnregisteredWorkerCount represents total number of workers with a status of unregistered
UnregisteredWorkerCount bool `form:"unregistered_worker_count"`
// AvailableWorkerCount represents total number of workers with a status of available,
// where worker RunningBuildIDs.length < worker BuildLimit
AvailableWorkerCount bool `form:"available_worker_count"`
// BusyWorkerCount represents total number of workers with a status of busy,
// where worker BuildLimit == worker RunningBuildIDs.length
BusyWorkerCount bool `form:"busy_worker_count"`
// BusyWorkerCount represents total number of workers with a status of maintenance
MaintenanceWorkerCount bool `form:"maintenance_worker_count"`
// ErrorWorkerCount represents total number of workers with a status of error
ErrorWorkerCount bool `form:"error_worker_count"`
}

// predefine Prometheus metrics else they will be regenerated
Expand Down Expand Up @@ -172,6 +186,31 @@ var (
// description: Indicates a request for inactive worker count
// type: boolean
// default: false
// - in: query
// name: unregistered_worker_count
// description: Indicates a request for unregistered worker count
// type: boolean
// default: false
// - in: query
// name: available_worker_count
// description: Indicates a request for available worker count
// type: boolean
// default: false
// - in: query
// name: busy_worker_count
// description: Indicates a request for busy worker count
// type: boolean
// default: false
// - in: query
// name: maintenance_worker_count
// description: Indicates a request for maintenance worker count
// type: boolean
// default: false
// - in: query
// name: error_worker_count
// description: Indicates a request for error worker count
// type: boolean
// default: false
// responses:
// '200':
// description: Successfully retrieved the Vela metrics
Expand Down Expand Up @@ -356,14 +395,19 @@ func recordGauges(c *gin.Context) {

// add worker metrics
var (
buildLimit int64
activeWorkers int64
inactiveWorkers int64
buildLimit int64
activeWorkers int64
inactiveWorkers int64
unregisteredWorkers int64
availableWorkers int64
busyWorkers int64
maintenanceWorkers int64
errorWorkers int64
)

// get worker metrics based on request query parameters
// worker_build_limit, active_worker_count, inactive_worker_count
if q.WorkerBuildLimit || q.ActiveWorkerCount || q.InactiveWorkerCount {
// worker_build_limit, active_worker_count, inactive_worker_count, unregistered_worker_count, available_worker_count, busy_worker_count, maintenance_worker_count, error_worker_count
if q.WorkerBuildLimit || q.ActiveWorkerCount || q.InactiveWorkerCount || q.UnregisteredWorkerCount || q.AvailableWorkerCount || q.BusyWorkerCount || q.MaintenanceWorkerCount || q.ErrorWorkerCount {
// send API call to capture the workers
workers, err := database.FromContext(c).ListWorkers()
if err != nil {
Expand All @@ -372,6 +416,8 @@ func recordGauges(c *gin.Context) {

// get the unix time from worker_active_interval ago
before := time.Now().UTC().Add(-c.Value("worker_active_interval").(time.Duration)).Unix()

// active, inactive counts
for _, worker := range workers {
// check if the worker checked in within the last worker_active_interval
if worker.GetLastCheckedIn() >= before {
Expand All @@ -382,6 +428,31 @@ func recordGauges(c *gin.Context) {
}
}

// available, busy, maintenance, error counts
for _, worker := range workers {
timhuynh94 marked this conversation as resolved.
Show resolved Hide resolved
// check if the worker checked in within the last worker_active_interval
if worker.GetLastCheckedIn() >= before {

switch worker.GetStatus() {
KellyMerrick marked this conversation as resolved.
Show resolved Hide resolved
KellyMerrick marked this conversation as resolved.
Show resolved Hide resolved
ecrupper marked this conversation as resolved.
Show resolved Hide resolved
ecrupper marked this conversation as resolved.
Show resolved Hide resolved
case constants.WorkerStatusUnregistered:
KellyMerrick marked this conversation as resolved.
Show resolved Hide resolved
KellyMerrick marked this conversation as resolved.
Show resolved Hide resolved

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [golangci] reported by reviewdog 🐶
undefined: constants.WorkerStatusUnregistered

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [golangci] reported by reviewdog 🐶
undefined: constants.WorkerStatusUnregistered

availableWorkers++
case constants.WorkerStatusBusy:
KellyMerrick marked this conversation as resolved.
Show resolved Hide resolved
KellyMerrick marked this conversation as resolved.
Show resolved Hide resolved
ecrupper marked this conversation as resolved.
Show resolved Hide resolved
ecrupper marked this conversation as resolved.
Show resolved Hide resolved
busyWorkers++
case constants.WorkerStatusMaintenance:
KellyMerrick marked this conversation as resolved.
Show resolved Hide resolved
KellyMerrick marked this conversation as resolved.
Show resolved Hide resolved

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [golangci] reported by reviewdog 🐶
undefined: constants.WorkerStatusMaintenance

KellyMerrick marked this conversation as resolved.
Show resolved Hide resolved
maintenanceWorkers++
case constants.WorkerStatusError:
KellyMerrick marked this conversation as resolved.
Show resolved Hide resolved
KellyMerrick marked this conversation as resolved.
Show resolved Hide resolved
ecrupper marked this conversation as resolved.
Show resolved Hide resolved
KellyMerrick marked this conversation as resolved.
Show resolved Hide resolved
errorWorkers++
}
}
}

// unregistered count
for _, worker := range workers {
if worker.GetStatus() == constants.WorkerStatusUnregistered {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [golangci] reported by reviewdog 🐶
worker.GetStatus undefined (type *library.Worker has no field or method GetStatus) (typecheck)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [golangci] reported by reviewdog 🐶
worker.GetStatus undefined (type *library.Worker has no field or method GetStatus)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [golangci] reported by reviewdog 🐶
undefined: constants.WorkerStatusUnregistered

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [golangci] reported by reviewdog 🐶
worker.GetStatus undefined (type *library.Worker has no field or method GetStatus)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [golangci] reported by reviewdog 🐶
undefined: constants.WorkerStatusUnregistered

KellyMerrick marked this conversation as resolved.
Show resolved Hide resolved
KellyMerrick marked this conversation as resolved.
Show resolved Hide resolved
unregisteredWorkers++
}
}

// apply metrics based on request query parameters
// worker_build_limit
if q.WorkerBuildLimit {
Expand All @@ -397,5 +468,30 @@ func recordGauges(c *gin.Context) {
if q.InactiveWorkerCount {
totals.WithLabelValues("worker", "count", "inactive").Set(float64(inactiveWorkers))
}

// unregistered_worker_count
if q.UnregisteredWorkerCount {
totals.WithLabelValues("worker", "count", "unregistered").Set(float64(unregisteredWorkers))
}

// available_worker_count
if q.AvailableWorkerCount {
totals.WithLabelValues("worker", "count", "available").Set(float64(availableWorkers))
}

// busy_worker_count
if q.BusyWorkerCount {
totals.WithLabelValues("worker", "count", "busy").Set(float64(busyWorkers))
}

// maintenance_worker_count
if q.MaintenanceWorkerCount {
totals.WithLabelValues("worker", "count", "maintenance").Set(float64(maintenanceWorkers))
}

// error_worker_count
if q.ErrorWorkerCount {
totals.WithLabelValues("worker", "count", "error").Set(float64(errorWorkers))
}
}
}
20 changes: 20 additions & 0 deletions api/worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,26 @@ func UpdateWorker(c *gin.Context) {
w.SetActive(input.GetActive())
}

if len(input.GetStatus()) > 0 {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [golangci] reported by reviewdog 🐶
input.GetStatus undefined (type *library.Worker has no field or method GetStatus) (typecheck)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [golangci] reported by reviewdog 🐶
input.GetStatus undefined (type *library.Worker has no field or method GetStatus)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [golangci] reported by reviewdog 🐶
input.GetStatus undefined (type *library.Worker has no field or method GetStatus)

KellyMerrick marked this conversation as resolved.
Show resolved Hide resolved
// update status if set
w.SetStatus(input.GetStatus())

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [golangci] reported by reviewdog 🐶
w.SetStatus undefined (type *library.Worker has no field or method SetStatus) (typecheck)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [golangci] reported by reviewdog 🐶
w.SetStatus undefined (type *library.Worker has no field or method SetStatus)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [golangci] reported by reviewdog 🐶
input.GetStatus undefined (type *library.Worker has no field or method GetStatus)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [golangci] reported by reviewdog 🐶
too many errors) (typecheck)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [golangci] reported by reviewdog 🐶
w.SetStatus undefined (type *library.Worker has no field or method SetStatus)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [golangci] reported by reviewdog 🐶
input.GetStatus undefined (type *library.Worker has no field or method GetStatus)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [golangci] reported by reviewdog 🐶
too many errors) (typecheck)

}

if input.GetLastStatusUpdateAt() > 0 {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [golangci] reported by reviewdog 🐶
input.GetLastStatusUpdateAt undefined (type *library.Worker has no field or method GetLastStatusUpdateAt) (typecheck)

// update LastStatusUpdateAt if set
w.SetLastStatusUpdateAt(input.GetLastStatusUpdateAt())

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [golangci] reported by reviewdog 🐶
w.SetLastStatusUpdateAt undefined (type *library.Worker has no field or method SetLastStatusUpdateAt) (typecheck)

}

if len(input.GetRunningBuildIDs()) > 0 {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [golangci] reported by reviewdog 🐶
input.GetRunningBuildIDs undefined (type *library.Worker has no field or method GetRunningBuildIDs) (typecheck)

// update RunningBuildIDs if set
w.SetRunningBuildIDs(input.GetRunningBuildIDs())

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [golangci] reported by reviewdog 🐶
w.SetRunningBuildIDs undefined (type *library.Worker has no field or method SetRunningBuildIDs) (typecheck)

}

if input.GetLastBuildFinishedAt() > 0 {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [golangci] reported by reviewdog 🐶
input.GetLastBuildFinishedAt undefined (type *library.Worker has no field or method GetLastBuildFinishedAt) (typecheck)

// update LastBuildFinishedAt if set
w.SetLastBuildFinishedAt(input.GetLastBuildFinishedAt())

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [golangci] reported by reviewdog 🐶
w.SetLastBuildFinishedAt undefined (type *library.Worker has no field or method SetLastBuildFinishedAt) (typecheck)

}

if input.GetLastCheckedIn() > 0 {
// update LastCheckedIn if set
w.SetLastCheckedIn(input.GetLastCheckedIn())
Expand Down
6 changes: 3 additions & 3 deletions database/worker/create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ func TestWorker_Engine_CreateWorker(t *testing.T) {

// ensure the mock expects the query
_mock.ExpectQuery(`INSERT INTO "workers"
("hostname","address","routes","active","last_checked_in","build_limit","id")
VALUES ($1,$2,$3,$4,$5,$6,$7) RETURNING "id"`).
WithArgs("worker_0", "localhost", nil, true, nil, nil, 1).
("hostname","address","routes","active","status","last_status_update_at","running_build_ids","last_build_finished_at","last_checked_in","build_limit","id")
VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11) RETURNING "id"`).
WithArgs("worker_0", "localhost", nil, true, nil, nil, nil, nil, nil, nil, 1).
WillReturnRows(_rows)

_sqlite := testSqlite(t)
Expand Down
37 changes: 22 additions & 15 deletions database/worker/table.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,29 +14,36 @@ const (
CREATE TABLE
IF NOT EXISTS
workers (
id SERIAL PRIMARY KEY,
hostname VARCHAR(250),
address VARCHAR(250),
routes VARCHAR(1000),
active BOOLEAN,
last_checked_in INTEGER,
build_limit INTEGER,
id SERIAL PRIMARY KEY,
hostname VARCHAR(250),
address VARCHAR(250),
routes VARCHAR(1000),
active BOOLEAN,
status VARCHAR(50),
last_status_update_at INTEGER,
running_build_ids VARCHAR(1000),
last_build_finished_at INTEGER,
last_checked_in INTEGER,
build_limit INTEGER,
UNIQUE(hostname)
);
`

// CreateSqliteTable represents a query to create the Sqlite workers table.
CreateSqliteTable = `
CREATE TABLE
IF NOT EXISTS
workers (
id INTEGER PRIMARY KEY AUTOINCREMENT,
hostname TEXT,
address TEXT,
routes TEXT,
active BOOLEAN,
last_checked_in INTEGER,
build_limit INTEGER,
id INTEGER PRIMARY KEY AUTOINCREMENT,
hostname TEXT,
address TEXT,
routes TEXT,
active BOOLEAN,
status VARCHAR(50),
last_status_update_at INTEGER,
running_build_ids VARCHAR(1000),
last_build_finished_at INTEGER,
last_checked_in INTEGER,
build_limit INTEGER,
UNIQUE(hostname)
);
`
Expand Down
6 changes: 3 additions & 3 deletions database/worker/update_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ func TestWorker_Engine_UpdateWorker(t *testing.T) {

// ensure the mock expects the query
_mock.ExpectExec(`UPDATE "workers"
SET "hostname"=$1,"address"=$2,"routes"=$3,"active"=$4,"last_checked_in"=$5,"build_limit"=$6
WHERE "id" = $7`).
WithArgs("worker_0", "localhost", nil, true, nil, nil, 1).
SET "hostname"=$1,"address"=$2,"routes"=$3,"active"=$4,"status"=$5,"last_status_update_at"=$6,"running_build_ids"=$7,"last_build_finished_at"=$8,"last_checked_in"=$9,"build_limit"=$10
WHERE "id" = $11`).
WithArgs("worker_0", "localhost", nil, true, nil, nil, nil, nil, nil, nil, 1).
WillReturnResult(sqlmock.NewResult(1, 1))

_sqlite := testSqlite(t)
Expand Down
18 changes: 11 additions & 7 deletions database/worker/worker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,12 +170,16 @@ func testSqlite(t *testing.T) *engine {
// Worker type with all fields set to their zero values.
func testWorker() *library.Worker {
return &library.Worker{
ID: new(int64),
Hostname: new(string),
Address: new(string),
Routes: new([]string),
Active: new(bool),
BuildLimit: new(int64),
LastCheckedIn: new(int64),
ID: new(int64),
Hostname: new(string),
Address: new(string),
Routes: new([]string),
Active: new(bool),
Status: new(string),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [golangci] reported by reviewdog 🐶
unknown field Status in struct literal of type library.Worker (typecheck)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [golangci] reported by reviewdog 🐶
unknown field Status in struct literal of type library.Worker

LastStatusUpdateAt: new(int64),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [golangci] reported by reviewdog 🐶
unknown field LastStatusUpdateAt in struct literal of type library.Worker (typecheck)

KellyMerrick marked this conversation as resolved.
Show resolved Hide resolved
RunningBuildIDs: new([]string),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [golangci] reported by reviewdog 🐶
unknown field RunningBuildIDs in struct literal of type library.Worker (typecheck)

KellyMerrick marked this conversation as resolved.
Show resolved Hide resolved
LastBuildFinishedAt: new(int64),
KellyMerrick marked this conversation as resolved.
Show resolved Hide resolved
LastCheckedIn: new(int64),
BuildLimit: new(int64),
}
}
4 changes: 4 additions & 0 deletions router/middleware/worker/worker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ func TestWorker_Establish(t *testing.T) {
want.SetAddress("localhost")
want.SetRoutes([]string{"foo", "bar", "baz"})
want.SetActive(true)
want.SetStatus("available")
KellyMerrick marked this conversation as resolved.
Show resolved Hide resolved
KellyMerrick marked this conversation as resolved.
Show resolved Hide resolved
want.SetLastStatusUpdateAt(12345)
KellyMerrick marked this conversation as resolved.
Show resolved Hide resolved
KellyMerrick marked this conversation as resolved.
Show resolved Hide resolved
want.SetRunningBuildIDs([]string{})
KellyMerrick marked this conversation as resolved.
Show resolved Hide resolved
KellyMerrick marked this conversation as resolved.
Show resolved Hide resolved
want.SetLastBuildFinishedAt(12345)
KellyMerrick marked this conversation as resolved.
Show resolved Hide resolved
want.SetLastCheckedIn(12345)
want.SetBuildLimit(0)

Expand Down