{"record":{"id":"10151d4785101421","repo":"vitessio/vitess","slug":"interval-too-small","errorCode":null,"errorMessage":"interval too small","messagePattern":"interval too small","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/stats/gauges.go","lineNumber":45,"sourceCode":"// Gauges tracks gauge values over time by sampling them at regular intervals.\n// Unlike Rates which tracks operation rates, Gauges tracks actual values.\ntype Gauges struct {\n\tmu         sync.Mutex\n\ttimeStamps *RingInt64\n\thistory    map[string]*RingInt64    // Historical sampled values\n\tcurrent    map[string]*atomic.Int64 // Current gauge values\n\tsamples    int\n\tinterval   time.Duration\n\tctx        context.Context\n\tcancel     context.CancelFunc\n}\n\n// NewGauges creates a new Gauges object that samples gauge values at regular intervals.\n// samples: number of historical samples to keep\n// interval: how often to sample the current gauge values\nfunc NewGauges(samples int, interval time.Duration) *Gauges {\n\tif interval < 1*time.Second && interval != -1*time.Second {\n\t\tpanic(\"interval too small\")\n\t}\n\tctx, cancel := context.WithCancel(context.Background())\n\tg := &Gauges{\n\t\ttimeStamps: NewRingInt64(samples + 1),\n\t\thistory:    make(map[string]*RingInt64),\n\t\tcurrent:    make(map[string]*atomic.Int64),\n\t\tsamples:    samples + 1,\n\t\tinterval:   interval,\n\t\tctx:        ctx,\n\t\tcancel:     cancel,\n\t}\n\n\t// Start background sampling goroutine\n\tif interval > 0 {\n\t\tgo g.track()\n\t}\n\n\treturn g","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/stats/gauges.go#L27-L63","documentation":"NewGauges samples gauge values on a background timer, so the sampling interval must be at least 1 second (the -1s sentinel disables snapshotting, mainly for tests). Any smaller positive interval is rejected with a panic because the sampler cannot run reliably below one second.","triggerScenarios":"Calling stats.NewGauges(samples, d) where d is 0, or any duration in (0, 1s), e.g. NewGauges(5, 100*time.Millisecond).","commonSituations":"Copy-pasting an interval from a fast unit test; passing time.Duration(0) as a 'default' without realizing 0 means an unusable sampler; converting from milliseconds to time.Duration incorrectly (e.g. 500 instead of 500*time.Millisecond).","solutions":["Pass an interval of at least 1*time.Second to NewGauges.","Use -1*time.Second if you intentionally want no snapshotting (test mode).","If you need sub-second sampling, this API does not support it — aggregate more frequently elsewhere or change the call site's cadence."],"exampleFix":"// before\ng := stats.NewGauges(5, 100*time.Millisecond) // panics: interval too small\n// after\ng := stats.NewGauges(5, 1*time.Second)","handlingStrategy":"validation","validationCode":"const minInterval = 1 * time.Second\nif interval != -1*time.Second && interval < minInterval {\n    interval = minInterval // clamp before calling NewGauges\n}\ng := stats.NewGauges(samples, interval)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Centralize sampling intervals as named constants >= 1s.","Always write durations with units (time.Millisecond), never bare integers.","Remember the -1s sentinel means 'no snapshot' (tests only)."],"tags":["go","stats","panic","invalid-interval"],"backgroundTag":"interval-below-minimum","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}