| 951 | } |
| 952 | |
| 953 | func (c *scrapeCache) iterDone(flushCache bool) { |
| 954 | c.metaMtx.Lock() |
| 955 | count := len(c.series) + len(c.droppedSeries) + len(c.metadata) |
| 956 | c.metaMtx.Unlock() |
| 957 | |
| 958 | switch { |
| 959 | case flushCache: |
| 960 | c.successfulCount = count |
| 961 | case count > c.successfulCount*2+1000: |
| 962 | // If a target had varying labels in scrapes that ultimately failed, |
| 963 | // the caches would grow indefinitely. Force a flush when this happens. |
| 964 | // We use the heuristic that this is a doubling of the cache size |
| 965 | // since the last scrape, and allow an additional 1000 in case |
| 966 | // initial scrapes all fail. |
| 967 | flushCache = true |
| 968 | c.metrics.targetScrapeCacheFlushForced.Inc() |
| 969 | } |
| 970 | |
| 971 | if flushCache { |
| 972 | // All caches may grow over time through series churn |
| 973 | // or multiple string representations of the same metric. Clean up entries |
| 974 | // that haven't appeared in the last scrape. |
| 975 | for s, e := range c.series { |
| 976 | if c.iter != e.lastIter { |
| 977 | delete(c.series, s) |
| 978 | } |
| 979 | } |
| 980 | for s, iter := range c.droppedSeries { |
| 981 | if c.iter != *iter { |
| 982 | delete(c.droppedSeries, s) |
| 983 | } |
| 984 | } |
| 985 | c.metaMtx.Lock() |
| 986 | for m, e := range c.metadata { |
| 987 | // Keep metadata around for 10 scrapes after its metric disappeared. |
| 988 | if c.iter-e.lastIter > 10 { |
| 989 | delete(c.metadata, m) |
| 990 | } |
| 991 | } |
| 992 | c.metaMtx.Unlock() |
| 993 | } |
| 994 | |
| 995 | // Swap current and previous series then clear the new current, to save allocations. |
| 996 | c.seriesPrev, c.seriesCur = c.seriesCur, c.seriesPrev |
| 997 | clear(c.seriesCur) |
| 998 | |
| 999 | c.iter++ |
| 1000 | } |
| 1001 | |
| 1002 | func (c *scrapeCache) get(met []byte) (*cacheEntry, bool, bool) { |
| 1003 | e, ok := c.series[string(met)] |