diff --git a/pkg/backup/BUILD.bazel b/pkg/backup/BUILD.bazel index 356a2fe7c41f..1943fe65acc3 100644 --- a/pkg/backup/BUILD.bazel +++ b/pkg/backup/BUILD.bazel @@ -157,6 +157,7 @@ go_library( "//pkg/util/tracing", "//pkg/util/tracing/tracingpb", "//pkg/util/uuid", + "@com_github_cockroachdb_crlib//crtime", "@com_github_cockroachdb_errors//:errors", "@com_github_cockroachdb_logtags//:logtags", "@com_github_cockroachdb_pebble//:pebble", diff --git a/pkg/backup/restore_job.go b/pkg/backup/restore_job.go index 644c6e99f6e6..0ede0169c68d 100644 --- a/pkg/backup/restore_job.go +++ b/pkg/backup/restore_job.go @@ -79,6 +79,7 @@ import ( "github.com/cockroachdb/cockroach/pkg/util/timeutil" "github.com/cockroachdb/cockroach/pkg/util/tracing" "github.com/cockroachdb/cockroach/pkg/util/uuid" + "github.com/cockroachdb/crlib/crtime" "github.com/cockroachdb/errors" "github.com/cockroachdb/pebble" ) @@ -215,7 +216,7 @@ func restoreWithRetry( // dying), so if we receive a retryable error, re-plan and retry the restore. retryOpts, progThreshold := getRetryOptionsAndProgressThreshold(execCtx) logRate := restoreRetryLogRate.Get(&execCtx.ExecCfg().Settings.SV) - logThrottler := util.Every(logRate) + logThrottler := util.EveryMono(logRate) var ( res roachpb.RowCount err error @@ -255,7 +256,7 @@ func restoreWithRetry( log.Dev.Warningf(ctx, "encountered retryable error: %+v", err) - if logThrottler.ShouldProcess(timeutil.Now()) { + if logThrottler.ShouldProcess(crtime.NowMono()) { // We throttle the logging of errors to the jobs messages table to avoid // flooding the table during the hot loop of a retry. if err := execCtx.ExecCfg().InternalDB.Txn(ctx, func(ctx context.Context, txn isql.Txn) error { diff --git a/pkg/ccl/changefeedccl/cdcevent/BUILD.bazel b/pkg/ccl/changefeedccl/cdcevent/BUILD.bazel index 6c29b4e4b3fd..11863830cdfa 100644 --- a/pkg/ccl/changefeedccl/cdcevent/BUILD.bazel +++ b/pkg/ccl/changefeedccl/cdcevent/BUILD.bazel @@ -43,6 +43,7 @@ go_library( "//pkg/util/json", "//pkg/util/log", "//pkg/util/protoutil", + "@com_github_cockroachdb_crlib//crtime", "@com_github_cockroachdb_errors//:errors", "@com_github_cockroachdb_redact//:redact", ], diff --git a/pkg/ccl/changefeedccl/cdcevent/rowfetcher_cache.go b/pkg/ccl/changefeedccl/cdcevent/rowfetcher_cache.go index fa77b97db2a4..05459a4dacdd 100644 --- a/pkg/ccl/changefeedccl/cdcevent/rowfetcher_cache.go +++ b/pkg/ccl/changefeedccl/cdcevent/rowfetcher_cache.go @@ -28,6 +28,7 @@ import ( "github.com/cockroachdb/cockroach/pkg/util/encoding" "github.com/cockroachdb/cockroach/pkg/util/hlc" "github.com/cockroachdb/cockroach/pkg/util/log" + "github.com/cockroachdb/crlib/crtime" "github.com/cockroachdb/errors" ) @@ -318,7 +319,7 @@ func (c *rowFetcherCache) RowFetcherForColumnFamily( Alloc: &c.a, Spec: &spec, TraceKV: c.rfArgs.traceKV, - TraceKVEvery: &util.EveryN{N: c.rfArgs.traceKVLogFrequency}, + TraceKVEvery: &util.EveryN[crtime.Mono]{N: c.rfArgs.traceKVLogFrequency}, }, ); err != nil { return nil, nil, err diff --git a/pkg/ccl/changefeedccl/changefeed_processors.go b/pkg/ccl/changefeedccl/changefeed_processors.go index c61eefd8a2bc..8341ae6c4fd8 100644 --- a/pkg/ccl/changefeedccl/changefeed_processors.go +++ b/pkg/ccl/changefeedccl/changefeed_processors.go @@ -1115,7 +1115,7 @@ const ( ) // slowLogEveryN rate-limits the logging of slow spans -var slowLogEveryN = log.Every(slowSpanMaxFrequency) +var slowLogEveryN = util.Every(slowSpanMaxFrequency) // jobState encapsulates changefeed job state. type jobState struct { @@ -2432,7 +2432,7 @@ type saveRateConfig struct { // duration it takes to save progress. type saveRateLimiter struct { config saveRateConfig - warnEveryN util.EveryN + warnEveryN util.EveryN[time.Time] clock timeutil.TimeSource diff --git a/pkg/cmd/roachtest/roachtestutil/utils.go b/pkg/cmd/roachtest/roachtestutil/utils.go index ad02fb8ce3c1..b660c580d97b 100644 --- a/pkg/cmd/roachtest/roachtestutil/utils.go +++ b/pkg/cmd/roachtest/roachtestutil/utils.go @@ -59,7 +59,7 @@ func SetDefaultAdminUIPort(c cluster.Cluster, opts *install.StartOpts) { // recently a given log message has been emitted so that it can determine // whether it's worth logging again. type EveryN struct { - util.EveryN + util.EveryN[time.Time] } // Every is a convenience constructor for an EveryN object that allows a log diff --git a/pkg/kv/kvserver/raft_log_queue.go b/pkg/kv/kvserver/raft_log_queue.go index e580374c9a9a..a640a249f43c 100644 --- a/pkg/kv/kvserver/raft_log_queue.go +++ b/pkg/kv/kvserver/raft_log_queue.go @@ -26,6 +26,7 @@ import ( "github.com/cockroachdb/cockroach/pkg/util/humanizeutil" "github.com/cockroachdb/cockroach/pkg/util/log" "github.com/cockroachdb/cockroach/pkg/util/timeutil" + "github.com/cockroachdb/crlib/crtime" "github.com/cockroachdb/errors" "github.com/cockroachdb/redact" ) @@ -147,7 +148,7 @@ type raftLogQueue struct { *baseQueue db *kv.DB - logSnapshots util.EveryN + logSnapshots util.EveryN[crtime.Mono] } var _ queueImpl = &raftLogQueue{} @@ -162,7 +163,7 @@ var _ queueImpl = &raftLogQueue{} func newRaftLogQueue(store *Store, db *kv.DB) *raftLogQueue { rlq := &raftLogQueue{ db: db, - logSnapshots: util.Every(10 * time.Second), + logSnapshots: util.EveryMono(10 * time.Second), } rlq.baseQueue = newBaseQueue( "raftlog", rlq, store, @@ -689,7 +690,7 @@ func (rlq *raftLogQueue) process( return false, nil } - if n := decision.NumNewRaftSnapshots(); log.V(1) || n > 0 && rlq.logSnapshots.ShouldProcess(timeutil.Now()) { + if n := decision.NumNewRaftSnapshots(); log.V(1) || n > 0 && rlq.logSnapshots.ShouldProcess(crtime.NowMono()) { log.KvExec.Infof(ctx, "%v", redact.Safe(decision.String())) log.KvDistribution.Infof(ctx, "%v", redact.Safe(decision.String())) } else { diff --git a/pkg/kv/kvserver/replica.go b/pkg/kv/kvserver/replica.go index 0701176bcba5..d517b29ed6db 100644 --- a/pkg/kv/kvserver/replica.go +++ b/pkg/kv/kvserver/replica.go @@ -59,6 +59,7 @@ import ( "github.com/cockroachdb/cockroach/pkg/util/syncutil" "github.com/cockroachdb/cockroach/pkg/util/tracing" "github.com/cockroachdb/cockroach/pkg/util/uuid" + "github.com/cockroachdb/crlib/crtime" "github.com/cockroachdb/errors" "github.com/cockroachdb/redact" "github.com/kr/pretty" @@ -1056,7 +1057,7 @@ type Replica struct { // information and without explicit throttling some replicas will offer once // per applied Raft command, which is silly and also clogs up the queues' // semaphores. - splitQueueThrottle, mergeQueueThrottle util.EveryN + splitQueueThrottle, mergeQueueThrottle util.EveryN[crtime.Mono] // loadBasedSplitter keeps information about load-based splitting. loadBasedSplitter split.Decider diff --git a/pkg/kv/kvserver/replica_app_batch.go b/pkg/kv/kvserver/replica_app_batch.go index c65f7fb0f41b..3bcf3bdfaac4 100644 --- a/pkg/kv/kvserver/replica_app_batch.go +++ b/pkg/kv/kvserver/replica_app_batch.go @@ -20,6 +20,7 @@ import ( "github.com/cockroachdb/cockroach/pkg/util/log" "github.com/cockroachdb/cockroach/pkg/util/log/logcrash" "github.com/cockroachdb/cockroach/pkg/util/timeutil" + "github.com/cockroachdb/crlib/crtime" "github.com/cockroachdb/errors" "github.com/cockroachdb/redact" ) @@ -688,7 +689,7 @@ func (b *replicaAppBatch) ApplyToStateMachine(ctx context.Context) error { // Record the number of keys written to the replica. b.r.loadStats.RecordWriteKeys(float64(b.ab.numMutations)) - now := timeutil.Now() + now := crtime.NowMono() if needsSplitBySize && r.splitQueueThrottle.ShouldProcess(now) { r.store.splitQueue.MaybeAddAsync(ctx, r, r.store.Clock().NowAsClockTimestamp()) } diff --git a/pkg/kv/kvserver/replica_init.go b/pkg/kv/kvserver/replica_init.go index 6d3bbe7bea3f..6f2f63628e26 100644 --- a/pkg/kv/kvserver/replica_init.go +++ b/pkg/kv/kvserver/replica_init.go @@ -242,8 +242,8 @@ func newUninitializedReplicaWithoutRaftGroup(store *Store, id roachpb.FullReplic store.TestingKnobs().DisableSyncLogWriteToss, } - r.splitQueueThrottle = util.Every(splitQueueThrottleDuration) - r.mergeQueueThrottle = util.Every(mergeQueueThrottleDuration) + r.splitQueueThrottle = util.EveryMono(splitQueueThrottleDuration) + r.mergeQueueThrottle = util.EveryMono(mergeQueueThrottleDuration) onTrip := func() { telemetry.Inc(telemetryTripAsync) diff --git a/pkg/spanconfig/spanconfigjob/BUILD.bazel b/pkg/spanconfig/spanconfigjob/BUILD.bazel index 596e723f4b2e..4edfc10401bc 100644 --- a/pkg/spanconfig/spanconfigjob/BUILD.bazel +++ b/pkg/spanconfig/spanconfigjob/BUILD.bazel @@ -18,6 +18,7 @@ go_library( "//pkg/util/retry", "//pkg/util/syncutil", "//pkg/util/timeutil", + "@com_github_cockroachdb_crlib//crtime", "@com_github_cockroachdb_errors//:errors", ], ) diff --git a/pkg/spanconfig/spanconfigjob/job.go b/pkg/spanconfig/spanconfigjob/job.go index ce99fe4c605d..2bacf2228983 100644 --- a/pkg/spanconfig/spanconfigjob/job.go +++ b/pkg/spanconfig/spanconfigjob/job.go @@ -21,6 +21,7 @@ import ( "github.com/cockroachdb/cockroach/pkg/util/retry" "github.com/cockroachdb/cockroach/pkg/util/syncutil" "github.com/cockroachdb/cockroach/pkg/util/timeutil" + "github.com/cockroachdb/crlib/crtime" "github.com/cockroachdb/errors" ) @@ -101,14 +102,14 @@ func (r *resumer) Resume(ctx context.Context, execCtxI interface{}) (jobErr erro settingValues := &execCtx.ExecCfg().Settings.SV persistCheckpointsMu := struct { syncutil.Mutex - util.EveryN + util.EveryN[crtime.Mono] }{} - persistCheckpointsMu.EveryN = util.Every(ReconciliationJobCheckpointInterval.Get(settingValues)) + persistCheckpointsMu.EveryN = util.EveryMono(ReconciliationJobCheckpointInterval.Get(settingValues)) ReconciliationJobCheckpointInterval.SetOnChange(settingValues, func(ctx context.Context) { persistCheckpointsMu.Lock() defer persistCheckpointsMu.Unlock() - persistCheckpointsMu.EveryN = util.Every(ReconciliationJobCheckpointInterval.Get(settingValues)) + persistCheckpointsMu.EveryN = util.EveryMono(ReconciliationJobCheckpointInterval.Get(settingValues)) }) checkpointingDisabled := false @@ -152,7 +153,7 @@ func (r *resumer) Resume(ctx context.Context, execCtxI interface{}) (jobErr erro shouldPersistCheckpoint := func() bool { persistCheckpointsMu.Lock() defer persistCheckpointsMu.Unlock() - return persistCheckpointsMu.ShouldProcess(timeutil.Now()) + return persistCheckpointsMu.ShouldProcess(crtime.NowMono()) }() if !shouldPersistCheckpoint { diff --git a/pkg/spanconfig/spanconfigsqlwatcher/BUILD.bazel b/pkg/spanconfig/spanconfigsqlwatcher/BUILD.bazel index 05bfa66083af..a2022df27b4f 100644 --- a/pkg/spanconfig/spanconfigsqlwatcher/BUILD.bazel +++ b/pkg/spanconfig/spanconfigsqlwatcher/BUILD.bazel @@ -35,7 +35,7 @@ go_library( "//pkg/util/protoutil", "//pkg/util/stop", "//pkg/util/syncutil", - "//pkg/util/timeutil", + "@com_github_cockroachdb_crlib//crtime", "@com_github_cockroachdb_errors//:errors", ], ) diff --git a/pkg/spanconfig/spanconfigsqlwatcher/sqlwatcher.go b/pkg/spanconfig/spanconfigsqlwatcher/sqlwatcher.go index 1de24248bb2a..0fa2ad985c9b 100644 --- a/pkg/spanconfig/spanconfigsqlwatcher/sqlwatcher.go +++ b/pkg/spanconfig/spanconfigsqlwatcher/sqlwatcher.go @@ -26,7 +26,7 @@ import ( "github.com/cockroachdb/cockroach/pkg/util/log" "github.com/cockroachdb/cockroach/pkg/util/log/logcrash" "github.com/cockroachdb/cockroach/pkg/util/stop" - "github.com/cockroachdb/cockroach/pkg/util/timeutil" + "github.com/cockroachdb/crlib/crtime" "github.com/cockroachdb/errors" ) @@ -151,7 +151,7 @@ func (s *SQLWatcher) watch( } defer ptsRF.Close() - checkpointNoops := util.Every(s.checkpointNoopsEvery) + checkpointNoops := util.EveryMono(s.checkpointNoopsEvery) for { select { case <-ctx.Done(): @@ -166,7 +166,7 @@ func (s *SQLWatcher) watch( return err } if len(sqlUpdates) == 0 && - (!checkpointNoops.ShouldProcess(timeutil.Now()) || s.knobs.SQLWatcherSkipNoopCheckpoints) { + (!checkpointNoops.ShouldProcess(crtime.NowMono()) || s.knobs.SQLWatcherSkipNoopCheckpoints) { continue } if err := handler(ctx, sqlUpdates, combinedFrontierTS); err != nil { diff --git a/pkg/sql/row/BUILD.bazel b/pkg/sql/row/BUILD.bazel index 4a3bac013e0a..4007cc71cce9 100644 --- a/pkg/sql/row/BUILD.bazel +++ b/pkg/sql/row/BUILD.bazel @@ -94,6 +94,7 @@ go_library( "//pkg/util/timeutil", "//pkg/util/unique", "//pkg/util/uuid", + "@com_github_cockroachdb_crlib//crtime", "@com_github_cockroachdb_errors//:errors", "@com_github_lib_pq//oid", ], diff --git a/pkg/sql/row/fetcher.go b/pkg/sql/row/fetcher.go index 2b1a878de492..7d528d396b76 100644 --- a/pkg/sql/row/fetcher.go +++ b/pkg/sql/row/fetcher.go @@ -39,6 +39,7 @@ import ( "github.com/cockroachdb/cockroach/pkg/util/log" "github.com/cockroachdb/cockroach/pkg/util/mon" "github.com/cockroachdb/cockroach/pkg/util/timeutil" + "github.com/cockroachdb/crlib/crtime" "github.com/cockroachdb/errors" "github.com/lib/pq/oid" ) @@ -339,7 +340,7 @@ type FetcherInitArgs struct { TraceKV bool // TraceKVEvery controls how often KVs are sampled for logging with traceKV // enabled. - TraceKVEvery *util.EveryN + TraceKVEvery *util.EveryN[crtime.Mono] ForceProductionKVBatchSize bool // SpansCanOverlap indicates whether the spans in a given batch can overlap // with one another. If it is true, spans that correspond to the same row must @@ -1196,7 +1197,7 @@ func (rf *Fetcher) NextRow(ctx context.Context) (row rowenc.EncDatumRow, spanID // log.EveryN will always print under verbosity level 2. // The caller may choose to set it to avoid logging // too many rows. If unset, we log every KV. - if rf.args.TraceKV && (rf.args.TraceKVEvery == nil || rf.args.TraceKVEvery.ShouldProcess(timeutil.Now())) { + if rf.args.TraceKV && (rf.args.TraceKVEvery == nil || rf.args.TraceKVEvery.ShouldProcess(crtime.NowMono())) { log.VEventf(ctx, TraceKVVerbosity, "fetched: %s -> %s", prettyKey, prettyVal) } diff --git a/pkg/sql/rowexec/BUILD.bazel b/pkg/sql/rowexec/BUILD.bazel index 7308113e78a3..f6d647ad7140 100644 --- a/pkg/sql/rowexec/BUILD.bazel +++ b/pkg/sql/rowexec/BUILD.bazel @@ -118,6 +118,7 @@ go_library( "//pkg/util/tracing/tracingpb", "//pkg/util/vector", "@com_github_axiomhq_hyperloglog//:hyperloglog", + "@com_github_cockroachdb_crlib//crtime", "@com_github_cockroachdb_errors//:errors", "@com_github_cockroachdb_logtags//:logtags", "@com_github_cockroachdb_redact//:redact", diff --git a/pkg/sql/rowexec/sample_aggregator.go b/pkg/sql/rowexec/sample_aggregator.go index 65b37562088f..fa95e4ce39db 100644 --- a/pkg/sql/rowexec/sample_aggregator.go +++ b/pkg/sql/rowexec/sample_aggregator.go @@ -30,9 +30,9 @@ import ( "github.com/cockroachdb/cockroach/pkg/util/intsets" "github.com/cockroachdb/cockroach/pkg/util/log" "github.com/cockroachdb/cockroach/pkg/util/mon" - "github.com/cockroachdb/cockroach/pkg/util/timeutil" "github.com/cockroachdb/cockroach/pkg/util/tracing" "github.com/cockroachdb/cockroach/pkg/util/tracing/tracingpb" + "github.com/cockroachdb/crlib/crtime" "github.com/cockroachdb/errors" ) @@ -245,14 +245,14 @@ func (s *sampleAggregator) mainLoop( } var rowsProcessed uint64 - progressUpdates := util.Every(SampleAggregatorProgressInterval) + progressUpdates := util.EveryMono(SampleAggregatorProgressInterval) var da tree.DatumAlloc for { row, meta := s.input.Next() if meta != nil { if meta.SamplerProgress != nil { rowsProcessed += meta.SamplerProgress.RowsProcessed - if progressUpdates.ShouldProcess(timeutil.Now()) { + if progressUpdates.ShouldProcess(crtime.NowMono()) { // Periodically report fraction progressed and check that the job has // not been paused or canceled. var fractionCompleted float32 diff --git a/pkg/sql/unsafesql/BUILD.bazel b/pkg/sql/unsafesql/BUILD.bazel index 708a0a8862b1..f0734f81f177 100644 --- a/pkg/sql/unsafesql/BUILD.bazel +++ b/pkg/sql/unsafesql/BUILD.bazel @@ -13,7 +13,7 @@ go_library( "//pkg/util/log", "//pkg/util/log/eventpb", "//pkg/util/log/severity", - "//pkg/util/timeutil", + "@com_github_cockroachdb_crlib//crtime", "@com_github_cockroachdb_redact//:redact", ], ) diff --git a/pkg/sql/unsafesql/unsafesql.go b/pkg/sql/unsafesql/unsafesql.go index df973e82fba5..3c82c6429b70 100644 --- a/pkg/sql/unsafesql/unsafesql.go +++ b/pkg/sql/unsafesql/unsafesql.go @@ -16,7 +16,7 @@ import ( "github.com/cockroachdb/cockroach/pkg/util/log" "github.com/cockroachdb/cockroach/pkg/util/log/eventpb" "github.com/cockroachdb/cockroach/pkg/util/log/severity" - "github.com/cockroachdb/cockroach/pkg/util/timeutil" + "github.com/cockroachdb/crlib/crtime" "github.com/cockroachdb/redact" ) @@ -58,14 +58,14 @@ func CheckInternalsAccess( // If an override is set, allow access to this virtual table. if sd.AllowUnsafeInternals { // Log this access to the SENSITIVE_ACCESS channel since the override condition bypassed normal access controls. - if accessedLogLimiter.ShouldProcess(timeutil.Now()) { + if accessedLogLimiter.ShouldProcess(crtime.NowMono()) { log.StructuredEvent(ctx, severity.WARNING, &eventpb.UnsafeInternalsAccessed{Query: q}) } return nil } // Log this access to the SENSITIVE_ACCESS channel to show where failing internals accesses are happening. - if deniedLogLimiter.ShouldProcess(timeutil.Now()) { + if deniedLogLimiter.ShouldProcess(crtime.NowMono()) { log.StructuredEvent(ctx, severity.WARNING, &eventpb.UnsafeInternalsDenied{Query: q}) } return sqlerrors.ErrUnsafeTableAccess diff --git a/pkg/util/BUILD.bazel b/pkg/util/BUILD.bazel index 4c81cf2d9db0..eb9ff165b4ce 100644 --- a/pkg/util/BUILD.bazel +++ b/pkg/util/BUILD.bazel @@ -27,6 +27,7 @@ go_library( deps = [ "//pkg/util/netutil/addr", "//pkg/util/syncutil", + "@com_github_cockroachdb_crlib//crtime", "@com_github_cockroachdb_errors//:errors", "@com_github_cockroachdb_redact//:redact", ] + select({ @@ -56,6 +57,7 @@ go_test( deps = [ "//pkg/util/randutil", "//pkg/util/timeutil", + "@com_github_cockroachdb_crlib//crtime", "@com_github_cockroachdb_errors//:errors", "@com_github_stretchr_testify//require", ], diff --git a/pkg/util/admission/BUILD.bazel b/pkg/util/admission/BUILD.bazel index a594063a5f1e..7f684bda2573 100644 --- a/pkg/util/admission/BUILD.bazel +++ b/pkg/util/admission/BUILD.bazel @@ -47,6 +47,7 @@ go_library( "//pkg/util/syncutil", "//pkg/util/timeutil", "//pkg/util/tracing", + "@com_github_cockroachdb_crlib//crtime", "@com_github_cockroachdb_errors//:errors", "@com_github_cockroachdb_logtags//:logtags", "@com_github_cockroachdb_pebble//:pebble", diff --git a/pkg/util/admission/elastic_cpu_granter.go b/pkg/util/admission/elastic_cpu_granter.go index 6d2cda84400b..1159ac7a726d 100644 --- a/pkg/util/admission/elastic_cpu_granter.go +++ b/pkg/util/admission/elastic_cpu_granter.go @@ -17,6 +17,7 @@ import ( "github.com/cockroachdb/cockroach/pkg/util/metric" "github.com/cockroachdb/cockroach/pkg/util/syncutil" "github.com/cockroachdb/cockroach/pkg/util/timeutil" + "github.com/cockroachdb/crlib/crtime" "github.com/cockroachdb/tokenbucket" ) @@ -236,7 +237,7 @@ func (e *elasticCPUGranter) hasWaitingRequests() bool { // computeUtilizationMetric is part of the elasticCPULimiter interface. func (e *elasticCPUGranter) computeUtilizationMetric() { - if !e.metrics.everyInterval.ShouldProcess(timeutil.Now()) { + if !e.metrics.everyInterval.ShouldProcess(crtime.NowMono()) { return // nothing to do } @@ -343,7 +344,7 @@ type elasticCPUGranterMetrics struct { OverLimitDuration metric.IHistogram Utilization *metric.GaugeFloat64 // updated every elasticCPUUtilizationMetricInterval, using fields below - everyInterval util.EveryN + everyInterval util.EveryN[crtime.Mono] lastCumUsedNanos int64 } @@ -365,7 +366,7 @@ func makeElasticCPUGranterMetrics() *elasticCPUGranterMetrics { }), Utilization: metric.NewGaugeFloat64(elasticCPUGranterUtilization), UtilizationLimit: metric.NewGaugeFloat64(elasticCPUGranterUtilizationLimit), - everyInterval: util.Every(elasticCPUUtilizationMetricInterval), + everyInterval: util.EveryMono(elasticCPUUtilizationMetricInterval), } metrics.MaxAvailableNanos.Inc(int64(runtime.GOMAXPROCS(0)) * time.Second.Nanoseconds()) diff --git a/pkg/util/every_n.go b/pkg/util/every_n.go index 5bb02de5e3c3..a243ef69b05c 100644 --- a/pkg/util/every_n.go +++ b/pkg/util/every_n.go @@ -9,8 +9,14 @@ import ( "time" "github.com/cockroachdb/cockroach/pkg/util/syncutil" + "github.com/cockroachdb/crlib/crtime" ) +type clockReading[T any] interface { + comparable + Sub(T) time.Duration +} + // EveryN provides a way to rate limit spammy events. It tracks how recently a // given event has occurred so that it can determine whether it's worth // handling again. @@ -21,25 +27,32 @@ import ( // NOTE: If you specifically care about log messages, you should use the // version of this in the log package, as it integrates with the verbosity // flags. -type EveryN struct { +type EveryN[T clockReading[T]] struct { // N is the minimum duration of time between log messages. N time.Duration syncutil.Mutex - lastProcessed time.Time + lastProcessed T } // Every is a convenience constructor for an EveryN object that allows a log // message every n duration. -func Every(n time.Duration) EveryN { - return EveryN{N: n} +func Every(n time.Duration) EveryN[time.Time] { + return EveryN[time.Time]{N: n} +} + +// EveryMono is a convenience constructor for an EveryN object that allows a log +// message every n duration, expecting crtime.Mono as input. +func EveryMono(n time.Duration) EveryN[crtime.Mono] { + return EveryN[crtime.Mono]{N: n} } // ShouldProcess returns whether it's been more than N time since the last event. -func (e *EveryN) ShouldProcess(now time.Time) bool { +func (e *EveryN[T]) ShouldProcess(now T) bool { var shouldProcess bool + var zero T e.Lock() - if now.Sub(e.lastProcessed) >= e.N { + if e.lastProcessed == zero || now.Sub(e.lastProcessed) >= e.N { shouldProcess = true e.lastProcessed = now } diff --git a/pkg/util/every_n_test.go b/pkg/util/every_n_test.go index 820c7d6ada58..521c8b1398e7 100644 --- a/pkg/util/every_n_test.go +++ b/pkg/util/every_n_test.go @@ -10,11 +10,11 @@ import ( "time" "github.com/cockroachdb/cockroach/pkg/util/timeutil" + "github.com/cockroachdb/crlib/crtime" + "github.com/stretchr/testify/require" ) func TestEveryN(t *testing.T) { - start := timeutil.Now() - en := EveryN{N: time.Minute} testCases := []struct { t time.Duration // time since start expected bool @@ -31,9 +31,18 @@ func TestEveryN(t *testing.T) { {10*time.Minute + 59*time.Second, false}, {11 * time.Minute, true}, } - for _, tc := range testCases { - if a, e := en.ShouldProcess(start.Add(tc.t)), tc.expected; a != e { - t.Errorf("ShouldProcess(%v) got %v, want %v", tc.t, a, e) + t.Run("time.Time", func(t *testing.T) { + start := timeutil.Now() + en := Every(time.Minute) + for _, tc := range testCases { + require.Equal(t, tc.expected, en.ShouldProcess(start.Add(tc.t))) } - } + }) + t.Run("crtime.NowMono", func(t *testing.T) { + start := crtime.NowMono() + en := EveryMono(time.Minute) + for _, tc := range testCases { + require.Equal(t, tc.expected, en.ShouldProcess(start.Add(tc.t))) + } + }) } diff --git a/pkg/util/log/BUILD.bazel b/pkg/util/log/BUILD.bazel index 1b9c2e94c21f..0fca396ea4fa 100644 --- a/pkg/util/log/BUILD.bazel +++ b/pkg/util/log/BUILD.bazel @@ -82,6 +82,7 @@ go_library( "//pkg/util/sysutil", "//pkg/util/timeutil", "//pkg/util/tracing", + "@com_github_cockroachdb_crlib//crtime", "@com_github_cockroachdb_errors//:errors", "@com_github_cockroachdb_errors//oserror", "@com_github_cockroachdb_logtags//:logtags", diff --git a/pkg/util/log/every_n.go b/pkg/util/log/every_n.go index 586d7db23640..2544ea752943 100644 --- a/pkg/util/log/every_n.go +++ b/pkg/util/log/every_n.go @@ -9,28 +9,28 @@ import ( "time" "github.com/cockroachdb/cockroach/pkg/util" - "github.com/cockroachdb/cockroach/pkg/util/timeutil" + "github.com/cockroachdb/crlib/crtime" ) // EveryN provides a way to rate limit spammy log messages. It tracks how // recently a given log message has been emitted so that it can determine // whether it's worth logging again. type EveryN struct { - util.EveryN + util.EveryN[crtime.Mono] } // Every is a convenience constructor for an EveryN object that allows a log // message every n duration. func Every(n time.Duration) EveryN { - return EveryN{EveryN: util.Every(n)} + return EveryN{EveryN: util.EveryMono(n)} } // ShouldLog returns whether it's been more than N time since the last event. func (e *EveryN) ShouldLog() bool { - return e.shouldLog(timeutil.Now()) + return e.shouldLog(crtime.NowMono()) } -func (e *EveryN) shouldLog(now time.Time) bool { +func (e *EveryN) shouldLog(now crtime.Mono) bool { if VDepth(2 /* level */, 2 /* depth */) { // Always log when high verbosity is desired. return true