001package io.prometheus.metrics.model.snapshots; 002 003/** 004 * Immutable container for metric metadata: name, help, unit. 005 */ 006public final class MetricMetadata { 007 008 /** 009 * Name without suffix. 010 * <p> 011 * For example, the name for a counter "http_requests_total" is "http_requests". 012 * The name of an info called "jvm_info" is "jvm". 013 * <p> 014 * We allow dots in label names. Dots are automatically replaced with underscores in Prometheus 015 * exposition formats. However, if metrics from this library are exposed in OpenTelemetry 016 * format dots are retained. 017 * <p> 018 * See {@link #MetricMetadata(String, String, Unit)} for more info on naming conventions. 019 */ 020 private final String name; 021 022 /** 023 * Same as name, except if name contains dots, then the prometheusName is {@code name.replace(".", "_")}. 024 */ 025 private final String prometheusName; 026 027 /** 028 * optional, may be {@code null}. 029 */ 030 private final String help; 031 032 /** 033 * optional, may be {@code null}. 034 */ 035 private final Unit unit; 036 037 /** 038 * See {@link #MetricMetadata(String, String, Unit)} 039 */ 040 public MetricMetadata(String name) { 041 this(name, null, null); 042 } 043 044 /** 045 * See {@link #MetricMetadata(String, String, Unit)} 046 */ 047 public MetricMetadata(String name, String help) { 048 this(name, help, null); 049 } 050 051 /** 052 * Constructor. 053 * @param name must not be {@code null}. {@link PrometheusNaming#isValidMetricName(String) isValidMetricName(name)} 054 * must be {@code true}. Use {@link PrometheusNaming#sanitizeMetricName(String)} to convert arbitrary 055 * strings into valid names. 056 * @param help optional. May be {@code null}. 057 * @param unit optional. May be {@code null}. 058 */ 059 public MetricMetadata(String name, String help, Unit unit) { 060 this.name = name; 061 this.help = help; 062 this.unit = unit; 063 validate(); 064 this.prometheusName = name.contains(".") ? PrometheusNaming.prometheusName(name) : name; 065 } 066 067 /** 068 * The name does not include the {@code _total} suffix for counter metrics 069 * or the {@code _info} suffix for Info metrics. 070 * <p> 071 * The name may contain dots. Use {@link #getPrometheusName()} to get the name in Prometheus format, 072 * i.e. with dots replaced by underscores. 073 */ 074 public String getName() { 075 return name; 076 } 077 078 /** 079 * Same as {@link #getName()} but with dots replaced by underscores. 080 * <p> 081 * This is used by Prometheus exposition formats. 082 */ 083 public String getPrometheusName() { 084 return prometheusName; 085 } 086 087 public String getHelp() { 088 return help; 089 } 090 091 public boolean hasUnit() { 092 return unit != null; 093 } 094 095 public Unit getUnit() { 096 return unit; 097 } 098 099 private void validate() { 100 if (name == null) { 101 throw new IllegalArgumentException("Missing required field: name is null"); 102 } 103 String error = PrometheusNaming.validateMetricName(name); 104 if (error != null) { 105 throw new IllegalArgumentException("'" + name + "': Illegal metric name. " + error 106 + " Call " + PrometheusNaming.class.getSimpleName() + ".sanitizeMetricName(name) to avoid this error."); 107 } 108 } 109}