Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit645da33

Browse files
test: fix TestDescCacheTimestampUpdate flake (#20975)
## Problem`TestDescCacheTimestampUpdate` was flaky on Windows CI because`time.Now()` has ~15.6ms resolution, causing consecutive calls to returnidentical timestamps.## SolutionInject `quartz.Clock` into `MetricsAggregator` using an options pattern,making the test deterministic by using a mock clock with explicit timeadvancement.### Changes- Add `clock quartz.Clock` field to `MetricsAggregator` struct- Add `WithClock()` option for dependency injection- Replace all `time.Now()` calls with `ma.clock.Now()`- Update test to use mock clock with `mClock.Advance(time.Second)`---This PR was fully generated by [`mux`](https://github.com/coder/mux)using Claude Opus 4.5, and reviewed by me.Closescoder/internal#1146
1 parentab4366f commit645da33

File tree

2 files changed

+30
-9
lines changed

2 files changed

+30
-9
lines changed

‎coderd/prometheusmetrics/aggregator.go‎

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ import (
1616
agentproto"github.com/coder/coder/v2/agent/proto"
1717
"github.com/coder/coder/v2/coderd/agentmetrics"
1818
"github.com/coder/coder/v2/coderd/pproflabel"
19+
20+
"github.com/coder/quartz"
1921
)
2022

2123
const (
@@ -47,6 +49,7 @@ type MetricsAggregator struct {
4749

4850
log slog.Logger
4951
metricsCleanupInterval time.Duration
52+
clock quartz.Clock
5053

5154
collectChchan (chan []prometheus.Metric)
5255
updateChchanupdateRequest
@@ -151,7 +154,7 @@ func (am *annotatedMetric) shallowCopy() annotatedMetric {
151154
}
152155
}
153156

154-
funcNewMetricsAggregator(logger slog.Logger,registerer prometheus.Registerer,duration time.Duration,aggregateByLabels []string) (*MetricsAggregator,error) {
157+
funcNewMetricsAggregator(logger slog.Logger,registerer prometheus.Registerer,duration time.Duration,aggregateByLabels []string,options...func(*MetricsAggregator)) (*MetricsAggregator,error) {
155158
metricsCleanupInterval:=defaultMetricsCleanupInterval
156159
ifduration>0 {
157160
metricsCleanupInterval=duration
@@ -192,9 +195,10 @@ func NewMetricsAggregator(logger slog.Logger, registerer prometheus.Registerer,
192195
returnnil,err
193196
}
194197

195-
return&MetricsAggregator{
198+
ma:=&MetricsAggregator{
196199
log:logger.Named(loggerName),
197200
metricsCleanupInterval:metricsCleanupInterval,
201+
clock:quartz.NewReal(),
198202

199203
store:map[metricKey]annotatedMetric{},
200204

@@ -206,7 +210,19 @@ func NewMetricsAggregator(logger slog.Logger, registerer prometheus.Registerer,
206210
cleanupHistogram:cleanupHistogram,
207211

208212
aggregateByLabels:aggregateByLabels,
209-
},nil
213+
}
214+
215+
for_,option:=rangeoptions {
216+
option(ma)
217+
}
218+
219+
returnma,nil
220+
}
221+
222+
funcWithClock(clock quartz.Clock)func(*MetricsAggregator) {
223+
returnfunc(ma*MetricsAggregator) {
224+
ma.clock=clock
225+
}
210226
}
211227

212228
// labelAggregator is used to control cardinality of collected Prometheus metrics by pre-aggregating series based on given labels.
@@ -349,7 +365,7 @@ func (ma *MetricsAggregator) Run(ctx context.Context) func() {
349365
ma.log.Debug(ctx,"clean expired metrics")
350366

351367
timer:=prometheus.NewTimer(ma.cleanupHistogram)
352-
now:=time.Now()
368+
now:=ma.clock.Now()
353369

354370
forkey,val:=rangema.store {
355371
ifnow.After(val.expiryDate) {
@@ -407,7 +423,7 @@ func (ma *MetricsAggregator) getOrCreateDesc(name string, help string, baseLabel
407423
}
408424
key:=cacheKeyForDesc(name,baseLabelNames,extraLabels)
409425
ifd,ok:=ma.descCache[key];ok {
410-
d.lastUsed=time.Now()
426+
d.lastUsed=ma.clock.Now()
411427
ma.descCache[key]=d
412428
returnd.desc
413429
}
@@ -419,7 +435,7 @@ func (ma *MetricsAggregator) getOrCreateDesc(name string, help string, baseLabel
419435
labels[nBase+i]=l.Name
420436
}
421437
d:=prometheus.NewDesc(name,help,labels,nil)
422-
ma.descCache[key]=descCacheEntry{d,time.Now()}
438+
ma.descCache[key]=descCacheEntry{d,ma.clock.Now()}
423439
returnd
424440
}
425441

@@ -497,7 +513,7 @@ func (ma *MetricsAggregator) Update(ctx context.Context, labels AgentMetricLabel
497513
templateName:labels.TemplateName,
498514
metrics:metrics,
499515

500-
timestamp:time.Now(),
516+
timestamp:ma.clock.Now(),
501517
}:
502518
case<-ctx.Done():
503519
ma.log.Debug(ctx,"update request is canceled")
@@ -508,7 +524,7 @@ func (ma *MetricsAggregator) Update(ctx context.Context, labels AgentMetricLabel
508524

509525
// Move to a function for testability
510526
func (ma*MetricsAggregator)cleanupDescCache() {
511-
now:=time.Now()
527+
now:=ma.clock.Now()
512528
forkey,entry:=rangema.descCache {
513529
ifnow.Sub(entry.lastUsed)>ma.metricsCleanupInterval {
514530
delete(ma.descCache,key)

‎coderd/prometheusmetrics/aggregator_internal_test.go‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
agentproto"github.com/coder/coder/v2/agent/proto"
1212
"github.com/coder/coder/v2/coderd/agentmetrics"
1313
"github.com/coder/coder/v2/testutil"
14+
"github.com/coder/quartz"
1415
)
1516

1617
funcTestDescCache_DescExpire(t*testing.T) {
@@ -62,8 +63,9 @@ func TestDescCache_DescExpire(t *testing.T) {
6263
funcTestDescCacheTimestampUpdate(t*testing.T) {
6364
t.Parallel()
6465

66+
mClock:=quartz.NewMock(t)
6567
registry:=prometheus.NewRegistry()
66-
ma,err:=NewMetricsAggregator(slogtest.Make(t,nil),registry,time.Hour,nil)
68+
ma,err:=NewMetricsAggregator(slogtest.Make(t,nil),registry,time.Hour,nil,WithClock(mClock))
6769
require.NoError(t,err)
6870

6971
baseLabelNames:= []string{"label1","label2"}
@@ -78,6 +80,9 @@ func TestDescCacheTimestampUpdate(t *testing.T) {
7880
initialEntry:=ma.descCache[key]
7981
initialTime:=initialEntry.lastUsed
8082

83+
// Advance the mock clock to ensure a different timestamp
84+
mClock.Advance(time.Second)
85+
8186
desc2:=ma.getOrCreateDesc("test_metric","help text",baseLabelNames,extraLabels)
8287
require.NotNil(t,desc2)
8388

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp