func()

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
}