@@ -2,6 +2,7 @@ package prebuilds
22
33import (
44 "context"
5+ "fmt"
56 "sync/atomic"
67 "time"
78
@@ -11,7 +12,6 @@ import (
1112 "cdr.dev/slog"
1213
1314 "github.com/coder/coder/v2/coderd/database"
14- "github.com/coder/coder/v2/coderd/database/dbauthz"
1515 "github.com/coder/coder/v2/coderd/prebuilds"
1616)
1717
5757 labels ,
5858 nil ,
5959 )
60+ lastUpdateDesc = prometheus .NewDesc (
61+ "coderd_prebuilt_workspaces_metrics_last_updated" ,
62+ "The unix timestamp when the metrics related to prebuilt workspaces were last updated; these metrics are cached." ,
63+ []string {},
64+ nil ,
65+ )
6066)
6167
6268const (
@@ -74,7 +80,6 @@ type MetricsCollector struct {
7480
7581var _ prometheus.Collector = new (MetricsCollector )
7682
77- // NewMetricsCollector returns a
7883func NewMetricsCollector (db database.Store , logger slog.Logger , snapshotter prebuilds.StateSnapshotter ) * MetricsCollector {
7984 log := logger .Named ("prebuilds_metrics_collector" )
8085 return & MetricsCollector {
@@ -91,18 +96,16 @@ func (*MetricsCollector) Describe(descCh chan<- *prometheus.Desc) {
9196 descCh <- desiredPrebuildsDesc
9297 descCh <- runningPrebuildsDesc
9398 descCh <- eligiblePrebuildsDesc
99+ descCh <- lastUpdateDesc
94100}
95101
96102// Collect uses the cached state to set configured metrics.
97103// The state is cached because this function can be called multiple times per second and retrieving the current state
98104// is an expensive operation.
99105func (mc * MetricsCollector ) Collect (metricsCh chan <- prometheus.Metric ) {
100- // nolint:gocritic // We need to set an authz context to read metrics from the db.
101- ctx := dbauthz .AsPrebuildsOrchestrator (context .Background ())
102-
103- currentState := mc .latestState .Load ()
106+ currentState := mc .latestState .Load () // Grab a copy; it's ok if it goes stale during the course of this func.
104107 if currentState == nil {
105- mc .logger .Warn (ctx , "failed to set prebuilds metrics; state not set" )
108+ mc .logger .Warn (context . Background () , "failed to set prebuilds metrics; state not set" )
106109 return
107110 }
108111
@@ -119,7 +122,7 @@ func (mc *MetricsCollector) Collect(metricsCh chan<- prometheus.Metric) {
119122
120123 presetSnapshot , err := currentState .snapshot .FilterByPreset (preset .ID )
121124 if err != nil {
122- mc .logger .Error (ctx , "failed to filter by preset" , slog .Error (err ))
125+ mc .logger .Error (context . Background () , "failed to filter by preset" , slog .Error (err ))
123126 continue
124127 }
125128 state := presetSnapshot .CalculateState ()
@@ -128,11 +131,14 @@ func (mc *MetricsCollector) Collect(metricsCh chan<- prometheus.Metric) {
128131 metricsCh <- prometheus .MustNewConstMetric (runningPrebuildsDesc , prometheus .GaugeValue , float64 (state .Actual ), preset .TemplateName , preset .Name , preset .OrganizationName )
129132 metricsCh <- prometheus .MustNewConstMetric (eligiblePrebuildsDesc , prometheus .GaugeValue , float64 (state .Eligible ), preset .TemplateName , preset .Name , preset .OrganizationName )
130133 }
134+
135+ metricsCh <- prometheus .MustNewConstMetric (lastUpdateDesc , prometheus .GaugeValue , float64 (currentState .createdAt .Unix ()))
131136}
132137
133138type state struct {
134139 prebuildMetrics []database.GetPrebuildMetricsRow
135140 snapshot * prebuilds.GlobalSnapshot
141+ createdAt time.Time
136142}
137143
138144// BackgroundFetch updates the metrics state every given interval.
@@ -157,6 +163,7 @@ func (mc *MetricsCollector) BackgroundFetch(ctx context.Context, updateInterval,
157163
158164// UpdateState builds the current metrics state.
159165func (mc * MetricsCollector ) UpdateState (ctx context.Context , timeout time.Duration ) error {
166+ start := time .Now ()
160167 mc .logger .Debug (ctx , "fetching prebuilds metrics state" )
161168 fetchCtx , fetchCancel := context .WithTimeout (ctx , timeout )
162169 defer fetchCancel ()
@@ -170,11 +177,12 @@ func (mc *MetricsCollector) UpdateState(ctx context.Context, timeout time.Durati
170177 if err != nil {
171178 return xerrors .Errorf ("snapshot state: %w" , err )
172179 }
173- mc .logger .Debug (ctx , "fetched prebuilds metrics state" )
180+ mc .logger .Debug (ctx , "fetched prebuilds metrics state" , slog . F ( "duration_secs" , fmt . Sprintf ( "%.2f" , time . Since ( start ). Seconds ())) )
174181
175182 mc .latestState .Store (& state {
176183 prebuildMetrics : prebuildMetrics ,
177184 snapshot : snapshot ,
185+ createdAt : time .Now (),
178186 })
179187 return nil
180188}
0 commit comments