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