@@ -2,6 +2,9 @@ package prebuilds
2
2
3
3
import (
4
4
"context"
5
+ "fmt"
6
+ "sync"
7
+ "sync/atomic"
5
8
"time"
6
9
7
10
"cdr.dev/slog"
35
38
labels ,
36
39
nil ,
37
40
)
41
+ resourceReplacementsDesc = prometheus .NewDesc (
42
+ "coderd_prebuilt_workspaces_resource_replacements_total" ,
43
+ "Total number of prebuilt workspaces whose resource(s) got replaced upon being claimed. " +
44
+ "In Terraform, drift on immutable attributes results in resource replacement. " +
45
+ "This represents a worst-case scenario for prebuilt workspaces because the pre-provisioned resource " +
46
+ "would have been recreated when claiming, thus obviating the point of pre-provisioning. " +
47
+ "See https://coder.com/docs/admin/templates/extending-templates/prebuilt-workspaces.md#preventing-resource-replacement" ,
48
+ labels ,
49
+ nil ,
50
+ )
38
51
desiredPrebuildsDesc = prometheus .NewDesc (
39
52
"coderd_prebuilt_workspaces_desired" ,
40
53
"Target number of prebuilt workspaces that should be available for each template preset." ,
@@ -61,22 +74,27 @@ type MetricsCollector struct {
61
74
database database.Store
62
75
logger slog.Logger
63
76
snapshotter prebuilds.StateSnapshotter
77
+
78
+ replacementsCounter map [replacementKey ]* atomic.Int64
79
+ replacementsCounterMu sync.Mutex
64
80
}
65
81
66
82
var _ prometheus.Collector = new (MetricsCollector )
67
83
68
84
func NewMetricsCollector (db database.Store , logger slog.Logger , snapshotter prebuilds.StateSnapshotter ) * MetricsCollector {
69
85
return & MetricsCollector {
70
- database : db ,
71
- logger : logger .Named ("prebuilds_metrics_collector" ),
72
- snapshotter : snapshotter ,
86
+ database : db ,
87
+ logger : logger .Named ("prebuilds_metrics_collector" ),
88
+ snapshotter : snapshotter ,
89
+ replacementsCounter : make (map [replacementKey ]* atomic.Int64 ),
73
90
}
74
91
}
75
92
76
93
func (* MetricsCollector ) Describe (descCh chan <- * prometheus.Desc ) {
77
94
descCh <- createdPrebuildsDesc
78
95
descCh <- failedPrebuildsDesc
79
96
descCh <- claimedPrebuildsDesc
97
+ descCh <- resourceReplacementsDesc
80
98
descCh <- desiredPrebuildsDesc
81
99
descCh <- runningPrebuildsDesc
82
100
descCh <- eligiblePrebuildsDesc
@@ -98,6 +116,12 @@ func (mc *MetricsCollector) Collect(metricsCh chan<- prometheus.Metric) {
98
116
metricsCh <- prometheus .MustNewConstMetric (claimedPrebuildsDesc , prometheus .CounterValue , float64 (metric .ClaimedCount ), metric .TemplateName , metric .PresetName , metric .OrganizationName )
99
117
}
100
118
119
+ mc .replacementsCounterMu .Lock ()
120
+ for key , val := range mc .replacementsCounter {
121
+ metricsCh <- prometheus .MustNewConstMetric (resourceReplacementsDesc , prometheus .CounterValue , float64 (val .Load ()), key .templateName , key .presetName , key .orgName )
122
+ }
123
+ mc .replacementsCounterMu .Unlock ()
124
+
101
125
snapshot , err := mc .snapshotter .SnapshotState (ctx , mc .database )
102
126
if err != nil {
103
127
mc .logger .Error (ctx , "failed to get latest prebuild state" , slog .Error (err ))
@@ -121,3 +145,22 @@ func (mc *MetricsCollector) Collect(metricsCh chan<- prometheus.Metric) {
121
145
metricsCh <- prometheus .MustNewConstMetric (eligiblePrebuildsDesc , prometheus .GaugeValue , float64 (state .Eligible ), preset .TemplateName , preset .Name , preset .OrganizationName )
122
146
}
123
147
}
148
+
149
+ type replacementKey struct {
150
+ orgName , templateName , presetName string
151
+ }
152
+
153
+ func (k replacementKey ) String () string {
154
+ return fmt .Sprintf ("%s:%s:%s" , k .orgName , k .templateName , k .presetName )
155
+ }
156
+
157
+ func (mc * MetricsCollector ) trackResourceReplacement (orgName , templateName , presetName string ) {
158
+ mc .replacementsCounterMu .Lock ()
159
+ defer mc .replacementsCounterMu .Unlock ()
160
+
161
+ key := replacementKey {orgName : orgName , templateName : templateName , presetName : presetName }
162
+ if _ , ok := mc .replacementsCounter [key ]; ! ok {
163
+ mc .replacementsCounter [key ] = & atomic.Int64 {}
164
+ }
165
+ mc .replacementsCounter [key ].Add (1 )
166
+ }
0 commit comments