in pkg/export/export.go [452:497]
func (e *Exporter) ApplyConfig(cfg *config.Config, opts *ExporterOpts) (err error) {
// Note: We don't expect the NopExporter to call this. Only the config reloader calls it.
e.mtx.Lock()
defer e.mtx.Unlock()
// Don't recreate the metric client each time. If the metric client is recreated, it has to
// potentially redo the TCP handshake. With HTTP/2, TCP connections are kept alive for a small
// amount of time to reduce load when multiple requests are made to the same server in
// succession. In our case, we might send a CMP call every 50ms at the worst case, which is
// highly likely to benefit from the persistent TPC connection.
optsChanged := false
if opts != nil {
optsChanged = !reflect.DeepEqual(e.opts, opts)
if optsChanged {
e.opts = *opts
}
}
lset := createLabelSet(cfg, &e.opts)
labelsChanged := !labels.Equal(e.externalLabels, lset)
// We don't need to validate if there's no scrape configs or rules, i.e. at startup.
hasScrapeConfigs := len(cfg.ScrapeConfigs) != 0 || len(cfg.ScrapeConfigFiles) != 0
hasRules := len(cfg.RuleFiles) != 0
if hasScrapeConfigs || hasRules {
if err := validateLabelSet(lset); err != nil {
return err
}
}
// If changed, or we're calling this for the first time, we need to recreate the client.
if optsChanged {
e.metricClient, err = e.newMetricClient(e.ctx, e.opts)
if err != nil {
return fmt.Errorf("create metric client: %w", err)
}
}
if labelsChanged {
e.externalLabels = lset
// New external labels possibly invalidate the cached series conversions.
e.seriesCache.forceRefresh()
}
return nil
}