feat(api): add prometheus metric coderd_workspace_builds_total (#6314)

This PR adds the prometheus metric coderd_workspace_builds_total.
It measures the total number of workspace builds, along with a number of labels intended to be useful for an operator debugging a failed workspace build trying to discover the scope of the issue.
This commit is contained in:
Cian Johnston
2023-02-23 01:28:10 +00:00
committed by GitHub
parent 2a8a147e7d
commit 43e8ba0811
8 changed files with 101 additions and 50 deletions

View File

@ -210,6 +210,8 @@ func (server *Server) AcquireJob(ctx context.Context, _ *proto.Empty) (*proto.Ac
WorkspaceOwnerEmail: owner.Email, WorkspaceOwnerEmail: owner.Email,
WorkspaceId: workspace.ID.String(), WorkspaceId: workspace.ID.String(),
WorkspaceOwnerId: owner.ID.String(), WorkspaceOwnerId: owner.ID.String(),
TemplateName: template.Name,
TemplateVersion: templateVersion.Name,
}, },
}, },
} }

View File

@ -206,6 +206,8 @@ func TestAcquireJob(t *testing.T) {
WorkspaceOwnerEmail: user.Email, WorkspaceOwnerEmail: user.Email,
WorkspaceId: workspace.ID.String(), WorkspaceId: workspace.ID.String(),
WorkspaceOwnerId: user.ID.String(), WorkspaceOwnerId: user.ID.String(),
TemplateName: template.Name,
TemplateVersion: version.Name,
}, },
}, },
}) })

View File

@ -30,7 +30,7 @@ The environment variable `CODER_PROMETHEUS_ENABLE` will be enabled automatically
<!-- Code generated by 'make docs/admin/prometheus.md'. DO NOT EDIT --> <!-- Code generated by 'make docs/admin/prometheus.md'. DO NOT EDIT -->
| Name | Type | Description | Labels | | Name | Type | Description | Labels |
| -------------------------------------------- | --------- | ------------------------------------------------------------------ | ---------------------- | | -------------------------------------------- | --------- | ------------------------------------------------------------------ | ----------------------------------------------------------------------------------- |
| `coderd_api_active_users_duration_hour` | gauge | The number of users that have been active within the last hour. | | | `coderd_api_active_users_duration_hour` | gauge | The number of users that have been active within the last hour. | |
| `coderd_api_concurrent_requests` | gauge | The number of concurrent API requests. | | | `coderd_api_concurrent_requests` | gauge | The number of concurrent API requests. | |
| `coderd_api_concurrent_websockets` | gauge | The total number of concurrent API websockets. | | | `coderd_api_concurrent_websockets` | gauge | The total number of concurrent API websockets. | |
@ -40,6 +40,7 @@ The environment variable `CODER_PROMETHEUS_ENABLE` will be enabled automatically
| `coderd_api_workspace_latest_build_total` | gauge | The latest workspace builds with a status. | `status` | | `coderd_api_workspace_latest_build_total` | gauge | The latest workspace builds with a status. | `status` |
| `coderd_provisionerd_job_timings_seconds` | histogram | The provisioner job time duration in seconds. | `provisioner` `status` | | `coderd_provisionerd_job_timings_seconds` | histogram | The provisioner job time duration in seconds. | `provisioner` `status` |
| `coderd_provisionerd_jobs_current` | gauge | The number of currently running provisioner jobs. | `provisioner` | | `coderd_provisionerd_jobs_current` | gauge | The number of currently running provisioner jobs. | `provisioner` |
| `coderd_workspace_builds_total` | counter | The number of workspaces started, updated, or deleted. | `action` `owner_email` `status` `template_name` `template_version` `workspace_name` |
| `go_gc_duration_seconds` | summary | A summary of the pause duration of garbage collection cycles. | | | `go_gc_duration_seconds` | summary | A summary of the pause duration of garbage collection cycles. | |
| `go_goroutines` | gauge | Number of goroutines that currently exist. | | | `go_goroutines` | gauge | Number of goroutines that currently exist. | |
| `go_info` | gauge | Information about the Go environment. | `version` | | `go_info` | gauge | Information about the Go environment. | `version` |

View File

@ -157,6 +157,12 @@ func NewMetrics(reg prometheus.Registerer) Metrics {
60 * 60, // 1hr 60 * 60, // 1hr
}, },
}, []string{"provisioner", "status"}), }, []string{"provisioner", "status"}),
WorkspaceBuilds: auto.NewCounterVec(prometheus.CounterOpts{
Namespace: "coderd",
Subsystem: "", // Explicitly empty to make this a top-level metric.
Name: "workspace_builds_total",
Help: "The number of workspaces started, updated, or deleted.",
}, []string{"owner_email", "workspace_name", "template_name", "template_version", "action", "status"}),
}, },
} }
} }

View File

@ -77,6 +77,8 @@ type Metrics struct {
ConcurrentJobs *prometheus.GaugeVec ConcurrentJobs *prometheus.GaugeVec
// JobTimings also counts the total amount of jobs. // JobTimings also counts the total amount of jobs.
JobTimings *prometheus.HistogramVec JobTimings *prometheus.HistogramVec
// WorkspaceBuilds counts workspace build successes and failures.
WorkspaceBuilds *prometheus.CounterVec
} }
type JobUpdater interface { type JobUpdater interface {
@ -161,6 +163,16 @@ func (r *Runner) Run() {
} }
concurrentGauge.Dec() concurrentGauge.Dec()
if build := r.job.GetWorkspaceBuild(); build != nil {
r.metrics.WorkspaceBuilds.WithLabelValues(
build.Metadata.WorkspaceOwnerEmail,
build.Metadata.WorkspaceName,
build.Metadata.TemplateName,
build.Metadata.TemplateVersion,
build.Metadata.WorkspaceTransition.String(),
status,
).Inc()
}
r.metrics.JobTimings.WithLabelValues(r.job.Provisioner, status).Observe(time.Since(start).Seconds()) r.metrics.JobTimings.WithLabelValues(r.job.Provisioner, status).Observe(time.Since(start).Seconds())
}() }()

View File

@ -1976,6 +1976,8 @@ type Provision_Metadata struct {
WorkspaceId string `protobuf:"bytes,5,opt,name=workspace_id,json=workspaceId,proto3" json:"workspace_id,omitempty"` WorkspaceId string `protobuf:"bytes,5,opt,name=workspace_id,json=workspaceId,proto3" json:"workspace_id,omitempty"`
WorkspaceOwnerId string `protobuf:"bytes,6,opt,name=workspace_owner_id,json=workspaceOwnerId,proto3" json:"workspace_owner_id,omitempty"` WorkspaceOwnerId string `protobuf:"bytes,6,opt,name=workspace_owner_id,json=workspaceOwnerId,proto3" json:"workspace_owner_id,omitempty"`
WorkspaceOwnerEmail string `protobuf:"bytes,7,opt,name=workspace_owner_email,json=workspaceOwnerEmail,proto3" json:"workspace_owner_email,omitempty"` WorkspaceOwnerEmail string `protobuf:"bytes,7,opt,name=workspace_owner_email,json=workspaceOwnerEmail,proto3" json:"workspace_owner_email,omitempty"`
TemplateName string `protobuf:"bytes,8,opt,name=template_name,json=templateName,proto3" json:"template_name,omitempty"`
TemplateVersion string `protobuf:"bytes,9,opt,name=template_version,json=templateVersion,proto3" json:"template_version,omitempty"`
} }
func (x *Provision_Metadata) Reset() { func (x *Provision_Metadata) Reset() {
@ -2059,6 +2061,20 @@ func (x *Provision_Metadata) GetWorkspaceOwnerEmail() string {
return "" return ""
} }
func (x *Provision_Metadata) GetTemplateName() string {
if x != nil {
return x.TemplateName
}
return ""
}
func (x *Provision_Metadata) GetTemplateVersion() string {
if x != nil {
return x.TemplateVersion
}
return ""
}
// Config represents execution configuration shared by both Plan and // Config represents execution configuration shared by both Plan and
// Apply commands. // Apply commands.
type Provision_Config struct { type Provision_Config struct {
@ -2793,8 +2809,8 @@ var file_provisionersdk_proto_provisioner_proto_rawDesc = []byte{
0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e,
0x50, 0x61, 0x72, 0x73, 0x65, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x48, 0x00, 0x50, 0x61, 0x72, 0x73, 0x65, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x48, 0x00,
0x52, 0x08, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x42, 0x06, 0x0a, 0x04, 0x74, 0x79, 0x52, 0x08, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x42, 0x06, 0x0a, 0x04, 0x74, 0x79,
0x70, 0x65, 0x22, 0xc7, 0x0a, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x70, 0x65, 0x22, 0x97, 0x0b, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e,
0x1a, 0xd1, 0x02, 0x0a, 0x08, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x1b, 0x0a, 0x1a, 0xa1, 0x03, 0x0a, 0x08, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x1b, 0x0a,
0x09, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x09, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
0x52, 0x08, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x55, 0x72, 0x6c, 0x12, 0x53, 0x0a, 0x14, 0x77, 0x6f, 0x52, 0x08, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x55, 0x72, 0x6c, 0x12, 0x53, 0x0a, 0x14, 0x77, 0x6f,
0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69,
@ -2815,7 +2831,12 @@ var file_provisionersdk_proto_provisioner_proto_rawDesc = []byte{
0x12, 0x32, 0x0a, 0x15, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6f, 0x77, 0x12, 0x32, 0x0a, 0x15, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x6f, 0x77,
0x6e, 0x65, 0x72, 0x5f, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x6e, 0x65, 0x72, 0x5f, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52,
0x13, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x45, 0x13, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x45,
0x6d, 0x61, 0x69, 0x6c, 0x1a, 0x79, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1c, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x23, 0x0a, 0x0d, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65,
0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x74, 0x65, 0x6d,
0x70, 0x6c, 0x61, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x74, 0x65, 0x6d,
0x70, 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x09, 0x20,
0x01, 0x28, 0x09, 0x52, 0x0f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x56, 0x65, 0x72,
0x73, 0x69, 0x6f, 0x6e, 0x1a, 0x79, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1c,
0x0a, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0a, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28,
0x09, 0x52, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x09, 0x52, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x14, 0x0a, 0x05,
0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x73, 0x74, 0x61, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x73, 0x74, 0x61,

View File

@ -220,6 +220,8 @@ message Provision {
string workspace_id = 5; string workspace_id = 5;
string workspace_owner_id = 6; string workspace_owner_id = 6;
string workspace_owner_email = 7; string workspace_owner_email = 7;
string template_name = 8;
string template_version = 9;
} }
// Config represents execution configuration shared by both Plan and // Config represents execution configuration shared by both Plan and

View File

@ -584,6 +584,11 @@ coderd_provisionerd_job_timings_seconds_count{provisioner="terraform",status="su
# HELP coderd_provisionerd_jobs_current The number of currently running provisioner jobs. # HELP coderd_provisionerd_jobs_current The number of currently running provisioner jobs.
# TYPE coderd_provisionerd_jobs_current gauge # TYPE coderd_provisionerd_jobs_current gauge
coderd_provisionerd_jobs_current{provisioner="terraform"} 0 coderd_provisionerd_jobs_current{provisioner="terraform"} 0
# HELP coderd_workspace_builds_total The number of workspaces started, updated, or deleted.
# TYPE coderd_workspace_builds_total counter
coderd_workspace_builds_total{action="START",owner_email="admin@coder.com",status="failed",template_name="docker",template_version="gallant_wright0",workspace_name="test1"} 1
coderd_workspace_builds_total{action="START",owner_email="admin@coder.com",status="success",template_name="docker",template_version="gallant_wright0",workspace_name="test1"} 1
coderd_workspace_builds_total{action="STOP",owner_email="admin@coder.com",status="success",template_name="docker",template_version="gallant_wright0",workspace_name="test1"} 1
# HELP go_gc_duration_seconds A summary of the pause duration of garbage collection cycles. # HELP go_gc_duration_seconds A summary of the pause duration of garbage collection cycles.
# TYPE go_gc_duration_seconds summary # TYPE go_gc_duration_seconds summary
go_gc_duration_seconds{quantile="0"} 2.4056e-05 go_gc_duration_seconds{quantile="0"} 2.4056e-05