001package io.prometheus.metrics.config;
002
003import javax.annotation.Nullable;
004
005public enum EscapingScheme {
006  /** NO_ESCAPING indicates that a name will not be escaped. */
007  ALLOW_UTF8("allow-utf-8"),
008
009  /** UNDERSCORE_ESCAPING replaces all legacy-invalid characters with underscores. */
010  UNDERSCORE_ESCAPING("underscores"),
011
012  /**
013   * DOTS_ESCAPING is similar to UNDERSCORE_ESCAPING, except that dots are converted to `_dot_` and
014   * pre-existing underscores are converted to `__`.
015   */
016  DOTS_ESCAPING("dots"),
017
018  /**
019   * VALUE_ENCODING_ESCAPING prepends the name with `U__` and replaces all invalid characters with
020   * the Unicode value, surrounded by underscores. Single underscores are replaced with double
021   * underscores.
022   */
023  VALUE_ENCODING_ESCAPING("values");
024
025  private static final String ESCAPING_KEY = "escaping";
026
027  /** Default escaping scheme for names when not specified. */
028  public static final EscapingScheme DEFAULT = UNDERSCORE_ESCAPING;
029
030  public final String getValue() {
031    return value;
032  }
033
034  private final String value;
035
036  EscapingScheme(String value) {
037    this.value = value;
038  }
039
040  /**
041   * fromAcceptHeader returns an EscapingScheme depending on the Accept header. Iff the header
042   * contains an escaping=allow-utf-8 term, it will select NO_ESCAPING. If a valid "escaping" term
043   * exists, that will be used. Otherwise, the global default will be returned.
044   */
045  public static EscapingScheme fromAcceptHeader(@Nullable String acceptHeader) {
046    if (acceptHeader != null) {
047      for (String p : acceptHeader.split(";")) {
048        String[] toks = p.split("=");
049        if (toks.length != 2) {
050          continue;
051        }
052        String key = toks[0].trim();
053        String value = toks[1].trim();
054        if (key.equals(ESCAPING_KEY)) {
055          try {
056            return EscapingScheme.forString(value);
057          } catch (IllegalArgumentException e) {
058            // If the escaping parameter is unknown, ignore it.
059            return DEFAULT;
060          }
061        }
062      }
063    }
064    return DEFAULT;
065  }
066
067  static EscapingScheme forString(String value) {
068    switch (value) {
069      case "allow-utf-8":
070        return ALLOW_UTF8;
071      case "underscores":
072        return UNDERSCORE_ESCAPING;
073      case "dots":
074        return DOTS_ESCAPING;
075      case "values":
076        return VALUE_ENCODING_ESCAPING;
077      default:
078        throw new IllegalArgumentException("Unknown escaping scheme: " + value);
079    }
080  }
081
082  public String toHeaderFormat() {
083    return "; " + ESCAPING_KEY + "=" + value;
084  }
085}