Workspaces tracks the total number of workspaces with labels on status.
(ctx context.Context, logger slog.Logger, registerer prometheus.Registerer, db database.Store, duration time.Duration)
| 128 | |
| 129 | // Workspaces tracks the total number of workspaces with labels on status. |
| 130 | func Workspaces(ctx context.Context, logger slog.Logger, registerer prometheus.Registerer, db database.Store, duration time.Duration) (func(), error) { |
| 131 | if duration == 0 { |
| 132 | duration = defaultRefreshRate |
| 133 | } |
| 134 | |
| 135 | workspaceLatestBuildTotals := prometheus.NewGaugeVec(prometheus.GaugeOpts{ |
| 136 | Namespace: "coderd", |
| 137 | Subsystem: "api", |
| 138 | Name: "workspace_latest_build", |
| 139 | Help: "The current number of workspace builds by status for all non-deleted workspaces.", |
| 140 | }, []string{"status"}) |
| 141 | if err := registerer.Register(workspaceLatestBuildTotals); err != nil { |
| 142 | return nil, err |
| 143 | } |
| 144 | |
| 145 | workspaceLatestBuildStatuses := prometheus.NewGaugeVec(prometheus.GaugeOpts{ |
| 146 | Namespace: "coderd", |
| 147 | Name: "workspace_latest_build_status", |
| 148 | Help: "The current workspace statuses by template, transition, and owner for all non-deleted workspaces.", |
| 149 | }, []string{"status", "template_name", "template_version", "workspace_owner", "workspace_transition"}) |
| 150 | if err := registerer.Register(workspaceLatestBuildStatuses); err != nil { |
| 151 | return nil, err |
| 152 | } |
| 153 | |
| 154 | workspaceCreationTotal := prometheus.NewCounterVec( |
| 155 | prometheus.CounterOpts{ |
| 156 | Namespace: "coderd", |
| 157 | Name: "workspace_creation_total", |
| 158 | Help: "Total regular (non-prebuilt) workspace creations by organization, template, and preset.", |
| 159 | }, |
| 160 | []string{"organization_name", "template_name", "preset_name"}, |
| 161 | ) |
| 162 | if err := registerer.Register(workspaceCreationTotal); err != nil { |
| 163 | return nil, err |
| 164 | } |
| 165 | |
| 166 | ctx, cancelFunc := context.WithCancel(ctx) |
| 167 | done := make(chan struct{}) |
| 168 | |
| 169 | updateWorkspaceMetrics := func() { |
| 170 | // Don't count deleted workspaces as part of these metrics. |
| 171 | ws, err := db.GetWorkspacesForWorkspaceMetrics(ctx) |
| 172 | if err != nil { |
| 173 | if errors.Is(err, sql.ErrNoRows) { |
| 174 | workspaceLatestBuildTotals.Reset() |
| 175 | workspaceLatestBuildStatuses.Reset() |
| 176 | } else { |
| 177 | logger.Warn(ctx, "failed to load active workspaces for metrics", slog.Error(err)) |
| 178 | } |
| 179 | return |
| 180 | } |
| 181 | |
| 182 | workspaceLatestBuildTotals.Reset() |
| 183 | workspaceLatestBuildStatuses.Reset() |
| 184 | |
| 185 | for _, w := range ws { |
| 186 | status := string(w.LatestBuildStatus) |
| 187 | workspaceLatestBuildTotals.WithLabelValues(status).Add(1) |