-
Notifications
You must be signed in to change notification settings - Fork 3.7k
feat: Adds statistics to debug/vars for tag value cache size #27259
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master-1.x
Are you sure you want to change the base?
Changes from all commits
8cff713
f110968
ccdbdf4
29e4264
efff99c
f875ea3
6c1faf6
b98d18b
ec3f0b7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -159,6 +159,13 @@ type Index struct { | |
|
|
||
| // Number of partitions used by the index. | ||
| PartitionN uint64 | ||
|
|
||
| // Number of bytes cache is currently using. | ||
| // Updated periodically by CollectTagValueCacheMetrics goroutine. | ||
| cacheBytes int64 | ||
|
|
||
| // Closed when the index is closing, to signal background goroutines to stop. | ||
| closing chan struct{} | ||
| } | ||
|
|
||
| func (i *Index) UniqueReferenceID() uintptr { | ||
|
|
@@ -180,6 +187,7 @@ func NewIndex(sfile *tsdb.SeriesFile, database string, options ...IndexOption) * | |
| sSketch: hll.NewDefaultPlus(), | ||
| sTSketch: hll.NewDefaultPlus(), | ||
| PartitionN: DefaultPartitionN, | ||
| closing: make(chan struct{}), | ||
| } | ||
|
|
||
| for _, option := range options { | ||
|
|
@@ -260,6 +268,9 @@ func (i *Index) Open() (rErr error) { | |
| return errors.New("index already open") | ||
| } | ||
|
|
||
| // Re-initialize closing channel for reopen support. | ||
| i.closing = make(chan struct{}) | ||
|
|
||
| // Ensure root exists. | ||
| if err := os.MkdirAll(i.path, 0777); err != nil { | ||
| return err | ||
|
|
@@ -303,6 +314,10 @@ func (i *Index) Open() (rErr error) { | |
| // Mark opened. | ||
| i.opened = true | ||
| i.logger.Info(fmt.Sprintf("index opened with %d partitions", partitionN)) | ||
|
|
||
| // Start background goroutine to periodically collect cache metrics. | ||
| i.collectTagValueCacheMetrics() | ||
|
|
||
| return nil | ||
| } | ||
|
|
||
|
|
@@ -350,6 +365,14 @@ func (i *Index) Close() error { | |
|
|
||
| // close closes the index without locking | ||
| func (i *Index) close() (rErr error) { | ||
| // Signal background goroutines to stop. | ||
| select { | ||
| case <-i.closing: | ||
| // Already closed. | ||
| default: | ||
| close(i.closing) | ||
| } | ||
|
|
||
| for _, p := range i.partitions { | ||
| if (p != nil) && p.IsOpen() { | ||
| if pErr := p.Close(); pErr != nil { | ||
|
|
@@ -1062,6 +1085,34 @@ func (i *Index) TagKeySeriesIDIterator(name, key []byte) (tsdb.SeriesIDIterator, | |
| return tsdb.MergeSeriesIDIterators(a...), nil | ||
| } | ||
|
|
||
| // TagValueCacheBytes returns the most recently sampled heap size of the | ||
| // tag value series ID cache, in bytes. | ||
| func (i *Index) TagValueCacheBytes() int64 { | ||
| return atomic.LoadInt64(&i.cacheBytes) | ||
| } | ||
|
|
||
| // collectTagValueCacheMetrics starts a background goroutine that periodically | ||
| // samples the tag value cache heap size. It exits when the index is closed. | ||
| func (i *Index) collectTagValueCacheMetrics() { | ||
| // take an initial sample | ||
| atomic.StoreInt64(&i.cacheBytes, int64(i.tagValueCache.HeapSize())) | ||
|
|
||
| const cacheTrigger = 10 * time.Second | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 10 second updates should be fine 🤔
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why collect on a schedule other than Monitor? Run the code when there is a call to |
||
| closing := i.closing | ||
| go func(closing <-chan struct{}) { | ||
| ticker := time.NewTicker(cacheTrigger) | ||
| defer ticker.Stop() | ||
| for { | ||
| select { | ||
| case <-closing: | ||
| return | ||
| case <-ticker.C: | ||
| atomic.StoreInt64(&i.cacheBytes, int64(i.tagValueCache.HeapSize())) | ||
| } | ||
| } | ||
| }(closing) | ||
| } | ||
|
|
||
| // TagValueSeriesIDIterator returns a series iterator for a single tag value. | ||
| func (i *Index) TagValueSeriesIDIterator(name, key, value []byte) (tsdb.SeriesIDIterator, error) { | ||
| // Check series ID set cache... | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For strings like
key, islen(key)the size used, or is itunsafe.Sizeof(key) + len(key)