Prometheus系列第八篇一核心一ClientLib源码分析-TextFormat协议输出

源码分析一TextFormat

  • TextFormat根据http请求头决定上报prometheus的数据报内容
  • “text/plain; version=0.0.4; charset=utf-8” 请求头时不上报采样点信息
  • “text/plain; version=0.0.4; charset=utf-8” 请求头时上报采样点信息exemplar

public class TextFormat {
 
  public final static String CONTENT_TYPE_004 = "text/plain; version=0.0.4; charset=utf-8";

  
  public final static String CONTENT_TYPE_OPENMETRICS_100 = "application/openmetrics-text; version=1.0.0; charset=utf-8";
  根据http请求头决定输出格式是否包含exemplar
  public static String chooseContentType(String acceptHeader) {
    if (acceptHeader == null) {
      return CONTENT_TYPE_004;
    }

    for (String accepts : acceptHeader.split(",")) {
      if ("application/openmetrics-text".equals(accepts.split(";")[0].trim())) {
        return CONTENT_TYPE_OPENMETRICS_100;
      }
    }

    return CONTENT_TYPE_OPENMETRICS_100;
  }


  public static void writeFormat(String contentType, Writer writer, Enumeration<Collector.MetricFamilySamples> mfs) throws IOException {
	0.0.4版本不会给prometheus等数据源提供exemplar信息
    if (CONTENT_TYPE_004.equals(contentType)) {
        write004(writer, mfs);
        return;
    }
    1.0.0版本会给prometheus等数据源提供exemplar信息
    if (CONTENT_TYPE_OPENMETRICS_100.equals(contentType)) {
        writeOpenMetrics100(writer, mfs);
        return;
    }
    throw new IllegalArgumentException("Unknown contentType " + contentType);
  }

 
  public static void write004(Writer writer, Enumeration<Collector.MetricFamilySamples> mfs) throws IOException {
    Map<String, Collector.MetricFamilySamples> omFamilies = new TreeMap<String, Collector.MetricFamilySamples>();
    while(mfs.hasMoreElements()) {

      Collector.MetricFamilySamples metricFamilySamples = mfs.nextElement();
      String name = metricFamilySamples.name;
      段文式协议 help帮助信息
      writer.write("# HELP ");
      writer.write(name);
      if (metricFamilySamples.type == Collector.Type.COUNTER) {
        writer.write("_total");
      }
      if (metricFamilySamples.type == Collector.Type.INFO) {
        writer.write("_info");
      }
      writer.write(' ');
      writeEscapedHelp(writer, metricFamilySamples.help);
      writer.write('\n');
      段文式协议 metrics类型 Counter summary等
      writer.write("# TYPE ");
      writer.write(name);

      if (metricFamilySamples.type == Collector.Type.COUNTER) {
        writer.write("_total");
      }
      if (metricFamilySamples.type == Collector.Type.INFO) {
        writer.write("_info");
      }
      writer.write(' ');
      writer.write(typeString(metricFamilySamples.type));
      writer.write('\n');

      String createdName = name + "_created";
      String gcountName = name + "_gcount";
      String gsumName = name + "_gsum";
      获取sample 进行输出
      for (Collector.MetricFamilySamples.Sample sample: metricFamilySamples.samples) {
        if (sample.name.equals(createdName)
            || sample.name.equals(gcountName)
            || sample.name.equals(gsumName)) {
          Collector.MetricFamilySamples omFamily = omFamilies.get(sample.name);
          if (omFamily == null) {
            omFamily = new Collector.MetricFamilySamples(sample.name, Collector.Type.GAUGE, metricFamilySamples.help, new ArrayList<Collector.MetricFamilySamples.Sample>());
            omFamilies.put(sample.name, omFamily);
          }
          omFamily.samples.add(sample);
          continue;
        }
        writer.write(sample.name);
        段文式协议 label键值对
        if (sample.labelNames.size() > 0) {
          writer.write('{');
          for (int i = 0; i < sample.labelNames.size(); ++i) {
            writer.write(sample.labelNames.get(i));
            writer.write("=\"");
            writeEscapedLabelValue(writer, sample.labelValues.get(i));
            writer.write("\",");
          }
          writer.write('}');
        }
        writer.write(' ');
        writer.write(Collector.doubleToGoString(sample.value));
        if (sample.timestampMs != null){
          writer.write(' ');
          writer.write(sample.timestampMs.toString());
        }
        writer.write('\n');
      }
    }
  }

 
  
  public static void writeOpenMetrics100(Writer writer, Enumeration<Collector.MetricFamilySamples> mfs) throws IOException {
    while(mfs.hasMoreElements()) {
      Collector.MetricFamilySamples metricFamilySamples = mfs.nextElement();
      String name = metricFamilySamples.name;
      书写类型
      writer.write("# TYPE ");
      writer.write(name);
      writer.write(' ');
      writer.write(omTypeString(metricFamilySamples.type));
      writer.write('\n');
      单位 counter 和 gauge一般没有
      if (!metricFamilySamples.unit.isEmpty()) {
        writer.write("# UNIT ");
        writer.write(name);
        writer.write(' ');
        writer.write(metricFamilySamples.unit);
        writer.write('\n');
      }

      writer.write("# HELP ");
      writer.write(name);
      writer.write(' ');
      writeEscapedLabelValue(writer, metricFamilySamples.help);
      writer.write('\n');
 
      for (Collector.MetricFamilySamples.Sample sample: metricFamilySamples.samples) {
        writer.write(sample.name);
        if (sample.labelNames.size() > 0) {
          writer.write('{');
          for (int i = 0; i < sample.labelNames.size(); ++i) {
            if (i > 0) {
              writer.write(",");
            }
            writer.write(sample.labelNames.get(i));
            writer.write("=\"");
            writeEscapedLabelValue(writer, sample.labelValues.get(i));
            writer.write("\"");
          }
          writer.write('}');
        }
        writer.write(' ');
        writer.write(Collector.doubleToGoString(sample.value));
        if (sample.timestampMs != null){
          writer.write(' ');
          omWriteTimestamp(writer, sample.timestampMs);
        }
		书写exemplar 信息
        例如: counter_total{label1=“val1”} 888.0 # {exemplar_key=“exemplar_val1”,exemplar_key2=“exemplar_val2”} 222.0 1663441608.646
        if (sample.exemplar != null) {
          writer.write(" # {");
          for (int i=0; i<sample.exemplar.getNumberOfLabels(); i++) {
            if (i > 0) {
              writer.write(",");
            }
            writer.write(sample.exemplar.getLabelName(i));
            writer.write("=\"");
            writeEscapedLabelValue(writer, sample.exemplar.getLabelValue(i));
            writer.write("\"");
          }
          writer.write("} ");
          writer.write(Collector.doubleToGoString(sample.exemplar.getValue()));
          if (sample.exemplar.getTimestampMs() != null) {
            writer.write(' ');
            omWriteTimestamp(writer, sample.exemplar.getTimestampMs());
          }
        }
        writer.write('\n');
      }
    }
    writer.write("# EOF\n");
  }
}

总结

  • TextFormat 在执行writeOpenMetrics100时,需要grafana7.4以上版本支持
  • 至此,prometheus类框架设计主体介绍完毕,但prometheus在java领域并没有支持许多常见的中间件,下文我们引入micrometer,介绍micrometer如何集成prometheus以及采集Java创建中间件的指标
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值