lib/promscrape: prevent from memory leaks on -promscrape.config reload when only a small part of scrape jobs is updated

This is a follow-up after 26b78ad707
This commit is contained in:
Aliaksandr Valialkin 2022-04-22 13:19:20 +03:00
parent 2c7f7799eb
commit 60f74dab56
No known key found for this signature in database
GPG Key ID: A72BEC6CD3D0DED1

View File

@ -166,6 +166,10 @@ func areEqualScrapeConfigs(a, b *ScrapeConfig) bool {
return string(sa) == string(sb) return string(sa) == string(sb)
} }
func (sc *ScrapeConfig) unmarshal(data []byte) error {
return yaml.UnmarshalStrict(data, sc)
}
func (sc *ScrapeConfig) marshal() []byte { func (sc *ScrapeConfig) marshal() []byte {
data, err := yaml.Marshal(sc) data, err := yaml.Marshal(sc)
if err != nil { if err != nil {
@ -411,15 +415,29 @@ func (cfg *Config) parseData(data []byte, path string) ([]byte, error) {
// Initialize cfg.ScrapeConfigs // Initialize cfg.ScrapeConfigs
for i, sc := range cfg.ScrapeConfigs { for i, sc := range cfg.ScrapeConfigs {
// Make a copy of sc in order to remove references to `data` memory.
// This should prevent from memory leaks on config reload.
sc = sc.clone()
cfg.ScrapeConfigs[i] = sc
swc, err := getScrapeWorkConfig(sc, cfg.baseDir, &cfg.Global) swc, err := getScrapeWorkConfig(sc, cfg.baseDir, &cfg.Global)
if err != nil { if err != nil {
return nil, fmt.Errorf("cannot parse `scrape_config` #%d: %w", i+1, err) return nil, fmt.Errorf("cannot parse `scrape_config`: %w", err)
} }
sc.swc = swc sc.swc = swc
} }
return dataNew, nil return dataNew, nil
} }
func (sc *ScrapeConfig) clone() *ScrapeConfig {
data := sc.marshal()
var scCopy ScrapeConfig
if err := scCopy.unmarshal(data); err != nil {
logger.Panicf("BUG: cannot unmarshal scrape config: %s", err)
}
return &scCopy
}
func getSWSByJob(sws []*ScrapeWork) map[string][]*ScrapeWork { func getSWSByJob(sws []*ScrapeWork) map[string][]*ScrapeWork {
m := make(map[string][]*ScrapeWork) m := make(map[string][]*ScrapeWork)
for _, sw := range sws { for _, sw := range sws {