001package io.prometheus.client.exporter.common;
002
003import java.io.IOException;
004import java.io.Writer;
005import java.util.Enumeration;
006
007import io.prometheus.client.Collector;
008
009public class TextFormat {
010  /**
011   * Content-type for text version 0.0.4.
012   */
013  public final static String CONTENT_TYPE_004 = "text/plain; version=0.0.4; charset=utf-8";
014
015  /**
016   * Write out the text version 0.0.4 of the given MetricFamilySamples.
017   */
018  public static void write004(Writer writer, Enumeration<Collector.MetricFamilySamples> mfs) throws IOException {
019    /* See http://prometheus.io/docs/instrumenting/exposition_formats/
020     * for the output format specification. */
021    while(mfs.hasMoreElements()) {
022      Collector.MetricFamilySamples metricFamilySamples = mfs.nextElement();
023      writer.write("# HELP ");
024      writer.write(metricFamilySamples.name);
025      writer.write(' ');
026      writeEscapedHelp(writer, metricFamilySamples.help);
027      writer.write('\n');
028
029      writer.write("# TYPE ");
030      writer.write(metricFamilySamples.name);
031      writer.write(' ');
032      writer.write(typeString(metricFamilySamples.type));
033      writer.write('\n');
034
035      for (Collector.MetricFamilySamples.Sample sample: metricFamilySamples.samples) {
036        writer.write(sample.name);
037        if (sample.labelNames.size() > 0) {
038          writer.write('{');
039          for (int i = 0; i < sample.labelNames.size(); ++i) {
040            writer.write(sample.labelNames.get(i));
041            writer.write("=\"");
042            writeEscapedLabelValue(writer, sample.labelValues.get(i));
043            writer.write("\",");
044          }
045          writer.write('}');
046        }
047        writer.write(' ');
048        writer.write(Collector.doubleToGoString(sample.value));
049        if (sample.timestampMs != null){
050          writer.write(' ');
051          writer.write(sample.timestampMs.toString());
052        }
053        writer.write('\n');
054      }
055    }
056  }
057
058  private static void writeEscapedHelp(Writer writer, String s) throws IOException {
059    for (int i = 0; i < s.length(); i++) {
060      char c = s.charAt(i);
061      switch (c) {
062        case '\\':
063          writer.append("\\\\");
064          break;
065        case '\n':
066          writer.append("\\n");
067          break;
068        default:
069          writer.append(c);
070      }
071    }
072  }
073
074  private static void writeEscapedLabelValue(Writer writer, String s) throws IOException {
075    for (int i = 0; i < s.length(); i++) {
076      char c = s.charAt(i);
077      switch (c) {
078        case '\\':
079          writer.append("\\\\");
080          break;
081        case '\"':
082          writer.append("\\\"");
083          break;
084        case '\n':
085          writer.append("\\n");
086          break;
087        default:
088          writer.append(c);
089      }
090    }
091  }
092
093  private static String typeString(Collector.Type t) {
094    switch (t) {
095      case GAUGE:
096        return "gauge";
097      case COUNTER:
098        return "counter";
099      case SUMMARY:
100        return "summary";
101      case HISTOGRAM:
102        return "histogram";
103      default:
104        return "untyped";
105    }
106  }
107}