mirror of
https://github.com/coder/coder.git
synced 2025-07-12 00:14:10 +00:00
Closes https://github.com/coder/internal/issues/509 --------- Signed-off-by: Danny Kopping <dannykopping@gmail.com>
124 lines
4.6 KiB
Go
124 lines
4.6 KiB
Go
package prebuilds
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
"cdr.dev/slog"
|
|
|
|
"github.com/prometheus/client_golang/prometheus"
|
|
|
|
"github.com/coder/coder/v2/coderd/database"
|
|
"github.com/coder/coder/v2/coderd/database/dbauthz"
|
|
"github.com/coder/coder/v2/coderd/prebuilds"
|
|
)
|
|
|
|
var (
|
|
labels = []string{"template_name", "preset_name", "organization_name"}
|
|
createdPrebuildsDesc = prometheus.NewDesc(
|
|
"coderd_prebuilt_workspaces_created_total",
|
|
"Total number of prebuilt workspaces that have been created to meet the desired instance count of each "+
|
|
"template preset.",
|
|
labels,
|
|
nil,
|
|
)
|
|
failedPrebuildsDesc = prometheus.NewDesc(
|
|
"coderd_prebuilt_workspaces_failed_total",
|
|
"Total number of prebuilt workspaces that failed to build.",
|
|
labels,
|
|
nil,
|
|
)
|
|
claimedPrebuildsDesc = prometheus.NewDesc(
|
|
"coderd_prebuilt_workspaces_claimed_total",
|
|
"Total number of prebuilt workspaces which were claimed by users. Claiming refers to creating a workspace "+
|
|
"with a preset selected for which eligible prebuilt workspaces are available and one is reassigned to a user.",
|
|
labels,
|
|
nil,
|
|
)
|
|
desiredPrebuildsDesc = prometheus.NewDesc(
|
|
"coderd_prebuilt_workspaces_desired",
|
|
"Target number of prebuilt workspaces that should be available for each template preset.",
|
|
labels,
|
|
nil,
|
|
)
|
|
runningPrebuildsDesc = prometheus.NewDesc(
|
|
"coderd_prebuilt_workspaces_running",
|
|
"Current number of prebuilt workspaces that are in a running state. These workspaces have started "+
|
|
"successfully but may not yet be claimable by users (see coderd_prebuilt_workspaces_eligible).",
|
|
labels,
|
|
nil,
|
|
)
|
|
eligiblePrebuildsDesc = prometheus.NewDesc(
|
|
"coderd_prebuilt_workspaces_eligible",
|
|
"Current number of prebuilt workspaces that are eligible to be claimed by users. These are workspaces that "+
|
|
"have completed their build process with their agent reporting 'ready' status.",
|
|
labels,
|
|
nil,
|
|
)
|
|
)
|
|
|
|
type MetricsCollector struct {
|
|
database database.Store
|
|
logger slog.Logger
|
|
snapshotter prebuilds.StateSnapshotter
|
|
}
|
|
|
|
var _ prometheus.Collector = new(MetricsCollector)
|
|
|
|
func NewMetricsCollector(db database.Store, logger slog.Logger, snapshotter prebuilds.StateSnapshotter) *MetricsCollector {
|
|
return &MetricsCollector{
|
|
database: db,
|
|
logger: logger.Named("prebuilds_metrics_collector"),
|
|
snapshotter: snapshotter,
|
|
}
|
|
}
|
|
|
|
func (*MetricsCollector) Describe(descCh chan<- *prometheus.Desc) {
|
|
descCh <- createdPrebuildsDesc
|
|
descCh <- failedPrebuildsDesc
|
|
descCh <- claimedPrebuildsDesc
|
|
descCh <- desiredPrebuildsDesc
|
|
descCh <- runningPrebuildsDesc
|
|
descCh <- eligiblePrebuildsDesc
|
|
}
|
|
|
|
func (mc *MetricsCollector) Collect(metricsCh chan<- prometheus.Metric) {
|
|
// nolint:gocritic // We need to set an authz context to read metrics from the db.
|
|
ctx, cancel := context.WithTimeout(dbauthz.AsPrebuildsOrchestrator(context.Background()), 10*time.Second)
|
|
defer cancel()
|
|
prebuildMetrics, err := mc.database.GetPrebuildMetrics(ctx)
|
|
if err != nil {
|
|
mc.logger.Error(ctx, "failed to get prebuild metrics", slog.Error(err))
|
|
return
|
|
}
|
|
|
|
for _, metric := range prebuildMetrics {
|
|
metricsCh <- prometheus.MustNewConstMetric(createdPrebuildsDesc, prometheus.CounterValue, float64(metric.CreatedCount), metric.TemplateName, metric.PresetName, metric.OrganizationName)
|
|
metricsCh <- prometheus.MustNewConstMetric(failedPrebuildsDesc, prometheus.CounterValue, float64(metric.FailedCount), metric.TemplateName, metric.PresetName, metric.OrganizationName)
|
|
metricsCh <- prometheus.MustNewConstMetric(claimedPrebuildsDesc, prometheus.CounterValue, float64(metric.ClaimedCount), metric.TemplateName, metric.PresetName, metric.OrganizationName)
|
|
}
|
|
|
|
snapshot, err := mc.snapshotter.SnapshotState(ctx, mc.database)
|
|
if err != nil {
|
|
mc.logger.Error(ctx, "failed to get latest prebuild state", slog.Error(err))
|
|
return
|
|
}
|
|
|
|
for _, preset := range snapshot.Presets {
|
|
if !preset.UsingActiveVersion {
|
|
continue
|
|
}
|
|
|
|
presetSnapshot, err := snapshot.FilterByPreset(preset.ID)
|
|
if err != nil {
|
|
mc.logger.Error(ctx, "failed to filter by preset", slog.Error(err))
|
|
continue
|
|
}
|
|
state := presetSnapshot.CalculateState()
|
|
|
|
metricsCh <- prometheus.MustNewConstMetric(desiredPrebuildsDesc, prometheus.GaugeValue, float64(state.Desired), preset.TemplateName, preset.Name, preset.OrganizationName)
|
|
metricsCh <- prometheus.MustNewConstMetric(runningPrebuildsDesc, prometheus.GaugeValue, float64(state.Actual), preset.TemplateName, preset.Name, preset.OrganizationName)
|
|
metricsCh <- prometheus.MustNewConstMetric(eligiblePrebuildsDesc, prometheus.GaugeValue, float64(state.Eligible), preset.TemplateName, preset.Name, preset.OrganizationName)
|
|
}
|
|
}
|