001package io.prometheus.client.exporter.common;
002
003import java.io.IOException;
004import java.io.Writer;
005import java.util.Collections;
006import java.util.Enumeration;
007
008import io.prometheus.client.Collector;
009
010public class TextFormat {
011  /**
012   * Content-type for text version 0.0.4.
013   */
014  public final static String CONTENT_TYPE_004 = "text/plain; version=0.0.4; charset=utf-8";
015
016  /**
017   * Write out the text version 0.0.4 of the given MetricFamilySamples.
018   */
019  public static void write004(Writer writer, Enumeration<Collector.MetricFamilySamples> mfs) throws IOException {
020    /* See http://prometheus.io/docs/instrumenting/exposition_formats/
021     * for the output format specification. */
022    for (Collector.MetricFamilySamples metricFamilySamples: Collections.list(mfs)) {
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        writer.write('\n');
050      }
051    }
052  }
053
054  private static void writeEscapedHelp(Writer writer, String s) throws IOException {
055    for (int i = 0; i < s.length(); i++) {
056      char c = s.charAt(i);
057      switch (c) {
058        case '\\':
059          writer.append("\\\\");
060          break;
061        case '\n':
062          writer.append("\\n");
063          break;
064        default:
065          writer.append(c);
066      }
067    }
068  }
069
070  private static void writeEscapedLabelValue(Writer writer, String s) throws IOException {
071    for (int i = 0; i < s.length(); i++) {
072      char c = s.charAt(i);
073      switch (c) {
074        case '\\':
075          writer.append("\\\\");
076          break;
077        case '\"':
078          writer.append("\\\"");
079          break;
080        case '\n':
081          writer.append("\\n");
082          break;
083        default:
084          writer.append(c);
085      }
086    }
087  }
088
089  private static String typeString(Collector.Type t) {
090    switch (t) {
091      case GAUGE:
092        return "gauge";
093      case COUNTER:
094        return "counter";
095      case SUMMARY:
096        return "summary";
097      case HISTOGRAM:
098        return "histogram";
099      default:
100        return "untyped";
101    }
102  }
103}