本节重点介绍 :

  • 多实例探针型采集配置解读
  • relabel源码阅读
  • __address__标签和target的关系
  • 采集http请求时获取target最终参数

多实例探针型采集配置

- job_name: 'blackbox-http'
    # metrics的path 注意不都是/metrics
    metrics_path: /probe
    # 传入的参数
    params:
      module: [http_2xx]  # Look for a HTTP 200 response.
    static_configs:
      - targets:
        - http://prometheus.io    # Target to probe with http.
        - https://www.baidu.com   # Target to probe with https.
    relabel_configs:
      - source_labels: [__address__]
        target_label: __param_target
      - source_labels: [__param_target]
        target_label: instance
      - target_label: __address__
        replacement: 127.0.0.1:9115  # The blackbox exporter's real hostname:port.
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.

进行一下解读

  1. prometheus首先读取job中的targets,把target赋值给 __address__标签 ,此标签代表采集的地址
  2. __address__标签 赋值给__param_target标签,因为prometheus 访问blackbox需要传参, __param_target代表target参数
  3. __param_target标签 赋值给instance标签,因为后面监控数据需要instance标签做 被探测实例的标记
  4. __address__标签 替换成真实的blackbox地址,因为prometheus是请求blackbox地址而不是 探测的目标地址

relabel源码阅读

  • 位置在D:\go_path\pkg\mod\github.com\prometheus\prometheus\scrape\target.go+ 328
  • populateLabels函数 ,处理标签relabel流程
  • 先设置job级别的 3个标签 job、__metrics_path__、 __scheme__
scrapeLabels := []labels.Label{
		{Name: model.JobLabel, Value: cfg.JobName},
		{Name: model.MetricsPathLabel, Value: cfg.MetricsPath},
		{Name: model.SchemeLabel, Value: cfg.Scheme},
	}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 再根据job配置中的 params设置所有参数标签 __param_
//  再根据job配置中的 params设置所有参数标签 `__param_`
    	for k, v := range cfg.Params {
		if len(v) > 0 {
			lb.Set(model.ParamLabelPrefix+k, v[0])
		}
	}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 调用 relabel.Process处理relabel config
  • relabel.Process中会根据配置的action 进行处理
switch cfg.Action {
	case Drop:
		if cfg.Regex.MatchString(val) {
			return nil
		}
	case Keep:
		if !cfg.Regex.MatchString(val) {
			return nil
		}
	case Replace:
		lb.Set(string(target), string(res))
    }
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 默认的action就是 replace
DefaultRelabelConfig = Config{
		Action:      Replace,
		Separator:   ";",
		Regex:       MustNewRegexp("(.*)"),
		Replacement: "$1",
	}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 对于我们上面的例子中就是 source赋值给target
  • 再回到populateLabels函数, 处理__address__标签,如果没有端口 则设置端口和scheme
lb.Set(model.AddressLabel, addr)
  • 1.
  • 删掉 __meta_开头的标签
for _, l := range lset {
    if strings.HasPrefix(l.Name, model.MetaLabelPrefix) {
        lb.Del(l.Name)
    }
  • 1.
  • 2.
  • 3.
  • 4.
  • populateLabels最后一步 ,把将 instance标签设置为addr的值
if v := lset.Get(model.InstanceLabel); v == "" {
    lb.Set(model.InstanceLabel, addr)
}
  • 1.
  • 2.
  • 3.
  • addr 就是 __address__的值

__address__标签和target的关系

  • __address__标签来自于 各个服务发现给出的,比如常规的yaml解析的时候
  • D:\go_path\pkg\mod\github.com\prometheus\prometheus@v1.8.2-0.20210321183757-31a518faab18\discovery\targetgroup\targetgroup.go
func (tg *Group) UnmarshalYAML(unmarshal func(interface{}) error) error {
	g := struct {
		Targets []string       `yaml:"targets"`
		Labels  model.LabelSet `yaml:"labels"`
	}{}
	if err := unmarshal(&g); err != nil {
		return err
	}
	tg.Targets = make([]model.LabelSet, 0, len(g.Targets))
	for _, t := range g.Targets {
		tg.Targets = append(tg.Targets, model.LabelSet{
			model.AddressLabel: model.LabelValue(t),
		})
	}
	tg.Labels = g.Labels
	return nil
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.

采集http请求时获取target最终参数

  • 这些参数后面会加在请求目标地址的时候,代码位置 D:\go_path\src\github.com\prometheus\prometheus\scrape\target.go
  • 在target的URL方法中可以看到 几个重要的参数 Schema、host、path、params
func (t *Target) URL() *url.URL {
	params := url.Values{}

	for k, v := range t.params {
		params[k] = make([]string, len(v))
		copy(params[k], v)
	}
	for _, l := range t.labels {
		if !strings.HasPrefix(l.Name, model.ParamLabelPrefix) {
			continue
		}
		ks := l.Name[len(model.ParamLabelPrefix):]

		if len(params[ks]) > 0 {
			params[ks][0] = l.Value
		} else {
			params[ks] = []string{l.Value}
		}
	}

	return &url.URL{
		Scheme:   t.labels.Get(model.SchemeLabel),
		Host:     t.labels.Get(model.AddressLabel),
		Path:     t.labels.Get(model.MetricsPathLabel),
		RawQuery: params.Encode(),
	}
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 在最终的采集动作中,会获取target的URL方法获取 地址和参数,位置 D:\go_path\src\github.com\prometheus\prometheus\scrape\scrape.go
func (s *targetScraper) scrape(ctx context.Context, w io.Writer) (string, error) {
	if s.req == nil {
		req, err := http.NewRequest("GET", s.URL().String(), nil)
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

本节重点总结:

  • 多实例探针型采集配置解读
  • relabel源码阅读
  • __address__标签和target的关系
  • 采集http请求时获取target最终参数