mirror of
https://github.com/coder/coder.git
synced 2025-07-06 15:41:45 +00:00
add prebuild metrics and observability
Signed-off-by: Danny Kopping <danny@coder.com>
This commit is contained in:
@ -1977,6 +1977,13 @@ func (q *querier) GetParameterSchemasByJobID(ctx context.Context, jobID uuid.UUI
|
||||
return q.db.GetParameterSchemasByJobID(ctx, jobID)
|
||||
}
|
||||
|
||||
func (q *querier) GetPrebuildMetrics(ctx context.Context) ([]database.GetPrebuildMetricsRow, error) {
|
||||
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceTemplate); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return q.db.GetPrebuildMetrics(ctx)
|
||||
}
|
||||
|
||||
func (q *querier) GetPrebuildsInProgress(ctx context.Context) ([]database.GetPrebuildsInProgressRow, error) {
|
||||
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceTemplate); err != nil {
|
||||
return nil, err
|
||||
|
@ -3784,6 +3784,10 @@ func (q *FakeQuerier) GetParameterSchemasByJobID(_ context.Context, jobID uuid.U
|
||||
return parameters, nil
|
||||
}
|
||||
|
||||
func (q *FakeQuerier) GetPrebuildMetrics(ctx context.Context) ([]database.GetPrebuildMetricsRow, error) {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func (q *FakeQuerier) GetPrebuildsInProgress(ctx context.Context) ([]database.GetPrebuildsInProgressRow, error) {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
@ -987,6 +987,13 @@ func (m queryMetricsStore) GetParameterSchemasByJobID(ctx context.Context, jobID
|
||||
return schemas, err
|
||||
}
|
||||
|
||||
func (m queryMetricsStore) GetPrebuildMetrics(ctx context.Context) ([]database.GetPrebuildMetricsRow, error) {
|
||||
start := time.Now()
|
||||
r0, r1 := m.s.GetPrebuildMetrics(ctx)
|
||||
m.queryLatencies.WithLabelValues("GetPrebuildMetrics").Observe(time.Since(start).Seconds())
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
func (m queryMetricsStore) GetPrebuildsInProgress(ctx context.Context) ([]database.GetPrebuildsInProgressRow, error) {
|
||||
start := time.Now()
|
||||
r0, r1 := m.s.GetPrebuildsInProgress(ctx)
|
||||
|
@ -2031,6 +2031,21 @@ func (mr *MockStoreMockRecorder) GetParameterSchemasByJobID(ctx, jobID any) *gom
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetParameterSchemasByJobID", reflect.TypeOf((*MockStore)(nil).GetParameterSchemasByJobID), ctx, jobID)
|
||||
}
|
||||
|
||||
// GetPrebuildMetrics mocks base method.
|
||||
func (m *MockStore) GetPrebuildMetrics(ctx context.Context) ([]database.GetPrebuildMetricsRow, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetPrebuildMetrics", ctx)
|
||||
ret0, _ := ret[0].([]database.GetPrebuildMetricsRow)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetPrebuildMetrics indicates an expected call of GetPrebuildMetrics.
|
||||
func (mr *MockStoreMockRecorder) GetPrebuildMetrics(ctx any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPrebuildMetrics", reflect.TypeOf((*MockStore)(nil).GetPrebuildMetrics), ctx)
|
||||
}
|
||||
|
||||
// GetPrebuildsInProgress mocks base method.
|
||||
func (m *MockStore) GetPrebuildsInProgress(ctx context.Context) ([]database.GetPrebuildsInProgressRow, error) {
|
||||
m.ctrl.T.Helper()
|
||||
|
@ -204,6 +204,7 @@ type sqlcQuerier interface {
|
||||
GetOrganizations(ctx context.Context, arg GetOrganizationsParams) ([]Organization, error)
|
||||
GetOrganizationsByUserID(ctx context.Context, userID uuid.UUID) ([]Organization, error)
|
||||
GetParameterSchemasByJobID(ctx context.Context, jobID uuid.UUID) ([]ParameterSchema, error)
|
||||
GetPrebuildMetrics(ctx context.Context) ([]GetPrebuildMetricsRow, error)
|
||||
GetPrebuildsInProgress(ctx context.Context) ([]GetPrebuildsInProgressRow, error)
|
||||
GetPresetByWorkspaceBuildID(ctx context.Context, workspaceBuildID uuid.UUID) (TemplateVersionPreset, error)
|
||||
GetPresetParametersByTemplateVersionID(ctx context.Context, templateVersionID uuid.UUID) ([]TemplateVersionPresetParameter, error)
|
||||
|
@ -5442,6 +5442,91 @@ func (q *sqlQuerier) ClaimPrebuild(ctx context.Context, arg ClaimPrebuildParams)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getPrebuildMetrics = `-- name: GetPrebuildMetrics :many
|
||||
SELECT
|
||||
t.name as template_name,
|
||||
tvp.name as preset_name,
|
||||
COUNT(*) FILTER ( -- created
|
||||
-- TODO (sasswart): double check which job statuses should be included here
|
||||
WHERE
|
||||
pj.initiator_id = 'c42fdf75-3097-471c-8c33-fb52454d81c0'::uuid
|
||||
AND pj.job_status = 'succeeded'::provisioner_job_status
|
||||
) as created,
|
||||
COUNT(*) FILTER ( -- failed
|
||||
-- TODO (sasswart): should we count cancelled here?
|
||||
WHERE pj.initiator_id = 'c42fdf75-3097-471c-8c33-fb52454d81c0'::uuid
|
||||
AND pj.job_status = 'failed'::provisioner_job_status
|
||||
) as failed,
|
||||
COUNT(*) FILTER ( -- assigned
|
||||
WHERE pj.initiator_id = 'c42fdf75-3097-471c-8c33-fb52454d81c0'::uuid
|
||||
AND NOT w.owner_id = 'c42fdf75-3097-471c-8c33-fb52454d81c0'::uuid
|
||||
) as assigned,
|
||||
COUNT(*) FILTER ( -- exhausted
|
||||
-- TODO (sasswart): write a filter to count this
|
||||
-- we should be able to count:
|
||||
-- - workspace builds
|
||||
-- - that have a preset id
|
||||
-- - and that preset has prebuilds enabled
|
||||
-- - and the job for the prebuild was initiated by a user other than the prebuilds user
|
||||
WHERE
|
||||
wb.template_version_preset_id IS NOT NULL
|
||||
AND w.owner_id != 'c42fdf75-3097-471c-8c33-fb52454d81c0'::uuid
|
||||
AND wb.initiator_id != 'c42fdf75-3097-471c-8c33-fb52454d81c0'::uuid
|
||||
) as exhausted,
|
||||
COUNT(*) FILTER ( -- used_preset
|
||||
WHERE wb.template_version_preset_id IS NOT NULL
|
||||
) as used_preset
|
||||
FROM workspace_builds wb
|
||||
INNER JOIN provisioner_jobs pj ON wb.job_id = pj.id
|
||||
LEFT JOIN workspaces w ON wb.workspace_id = w.id
|
||||
LEFT JOIN template_version_presets tvp ON wb.template_version_preset_id = tvp.id
|
||||
LEFT JOIN template_versions tv ON tv.id = wb.template_version_id
|
||||
LEFT JOIN templates t ON t.id = tv.template_id
|
||||
WHERE pj.initiator_id = 'c42fdf75-3097-471c-8c33-fb52454d81c0'::uuid
|
||||
GROUP BY t.name, tvp.name
|
||||
`
|
||||
|
||||
type GetPrebuildMetricsRow struct {
|
||||
TemplateName sql.NullString `db:"template_name" json:"template_name"`
|
||||
PresetName sql.NullString `db:"preset_name" json:"preset_name"`
|
||||
Created int64 `db:"created" json:"created"`
|
||||
Failed int64 `db:"failed" json:"failed"`
|
||||
Assigned int64 `db:"assigned" json:"assigned"`
|
||||
Exhausted int64 `db:"exhausted" json:"exhausted"`
|
||||
UsedPreset int64 `db:"used_preset" json:"used_preset"`
|
||||
}
|
||||
|
||||
func (q *sqlQuerier) GetPrebuildMetrics(ctx context.Context) ([]GetPrebuildMetricsRow, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getPrebuildMetrics)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []GetPrebuildMetricsRow
|
||||
for rows.Next() {
|
||||
var i GetPrebuildMetricsRow
|
||||
if err := rows.Scan(
|
||||
&i.TemplateName,
|
||||
&i.PresetName,
|
||||
&i.Created,
|
||||
&i.Failed,
|
||||
&i.Assigned,
|
||||
&i.Exhausted,
|
||||
&i.UsedPreset,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getPrebuildsInProgress = `-- name: GetPrebuildsInProgress :many
|
||||
SELECT t.id AS template_id, wpb.template_version_id, wpb.transition, COUNT(wpb.transition) AS count
|
||||
FROM workspace_latest_build wlb
|
||||
|
@ -71,3 +71,46 @@ RETURNING w.id, w.name;
|
||||
INSERT INTO template_version_preset_prebuilds (id, preset_id, desired_instances, invalidate_after_secs)
|
||||
VALUES (@id::uuid, @preset_id::uuid, @desired_instances::int, @invalidate_after_secs::int)
|
||||
RETURNING *;
|
||||
|
||||
-- name: GetPrebuildMetrics :many
|
||||
SELECT
|
||||
t.name as template_name,
|
||||
tvp.name as preset_name,
|
||||
COUNT(*) FILTER ( -- created
|
||||
-- TODO (sasswart): double check which job statuses should be included here
|
||||
WHERE
|
||||
pj.initiator_id = 'c42fdf75-3097-471c-8c33-fb52454d81c0'::uuid
|
||||
AND pj.job_status = 'succeeded'::provisioner_job_status
|
||||
) as created,
|
||||
COUNT(*) FILTER ( -- failed
|
||||
-- TODO (sasswart): should we count cancelled here?
|
||||
WHERE pj.initiator_id = 'c42fdf75-3097-471c-8c33-fb52454d81c0'::uuid
|
||||
AND pj.job_status = 'failed'::provisioner_job_status
|
||||
) as failed,
|
||||
COUNT(*) FILTER ( -- assigned
|
||||
WHERE pj.initiator_id = 'c42fdf75-3097-471c-8c33-fb52454d81c0'::uuid
|
||||
AND NOT w.owner_id = 'c42fdf75-3097-471c-8c33-fb52454d81c0'::uuid
|
||||
) as assigned,
|
||||
COUNT(*) FILTER ( -- exhausted
|
||||
-- TODO (sasswart): write a filter to count this
|
||||
-- we should be able to count:
|
||||
-- - workspace builds
|
||||
-- - that have a preset id
|
||||
-- - and that preset has prebuilds enabled
|
||||
-- - and the job for the prebuild was initiated by a user other than the prebuilds user
|
||||
WHERE
|
||||
wb.template_version_preset_id IS NOT NULL
|
||||
AND w.owner_id != 'c42fdf75-3097-471c-8c33-fb52454d81c0'::uuid
|
||||
AND wb.initiator_id != 'c42fdf75-3097-471c-8c33-fb52454d81c0'::uuid
|
||||
) as exhausted,
|
||||
COUNT(*) FILTER ( -- used_preset
|
||||
WHERE wb.template_version_preset_id IS NOT NULL
|
||||
) as used_preset
|
||||
FROM workspace_builds wb
|
||||
INNER JOIN provisioner_jobs pj ON wb.job_id = pj.id
|
||||
LEFT JOIN workspaces w ON wb.workspace_id = w.id
|
||||
LEFT JOIN template_version_presets tvp ON wb.template_version_preset_id = tvp.id
|
||||
LEFT JOIN template_versions tv ON tv.id = wb.template_version_id
|
||||
LEFT JOIN templates t ON t.id = tv.template_id
|
||||
WHERE pj.initiator_id = 'c42fdf75-3097-471c-8c33-fb52454d81c0'::uuid
|
||||
GROUP BY t.name, tvp.name;
|
||||
|
Reference in New Issue
Block a user