checkMetricConsistency checks if the provided Metric is consistent with the provided MetricFamily. It also hashes the Metric labels and the MetricFamily name. If the resulting hash is already in the provided metricHashes, an error is returned. If not, it is added to metricHashes.
(
metricFamily *dto.MetricFamily,
dtoMetric *dto.Metric,
metricHashes map[uint64]struct{},
)
| 867 | // name. If the resulting hash is already in the provided metricHashes, an error |
| 868 | // is returned. If not, it is added to metricHashes. |
| 869 | func checkMetricConsistency( |
| 870 | metricFamily *dto.MetricFamily, |
| 871 | dtoMetric *dto.Metric, |
| 872 | metricHashes map[uint64]struct{}, |
| 873 | ) error { |
| 874 | name := metricFamily.GetName() |
| 875 | |
| 876 | // Type consistency with metric family. |
| 877 | if metricFamily.GetType() == dto.MetricType_GAUGE && dtoMetric.Gauge == nil || |
| 878 | metricFamily.GetType() == dto.MetricType_COUNTER && dtoMetric.Counter == nil || |
| 879 | metricFamily.GetType() == dto.MetricType_SUMMARY && dtoMetric.Summary == nil || |
| 880 | metricFamily.GetType() == dto.MetricType_HISTOGRAM && dtoMetric.Histogram == nil || |
| 881 | metricFamily.GetType() == dto.MetricType_UNTYPED && dtoMetric.Untyped == nil { |
| 882 | return fmt.Errorf( |
| 883 | "collected metric %q { %s} is not a %s", |
| 884 | name, dtoMetric, metricFamily.GetType(), |
| 885 | ) |
| 886 | } |
| 887 | |
| 888 | previousLabelName := "" |
| 889 | for _, labelPair := range dtoMetric.GetLabel() { |
| 890 | labelName := labelPair.GetName() |
| 891 | if labelName == previousLabelName { |
| 892 | return fmt.Errorf( |
| 893 | "collected metric %q { %s} has two or more labels with the same name: %s", |
| 894 | name, dtoMetric, labelName, |
| 895 | ) |
| 896 | } |
| 897 | if !checkLabelName(labelName) { |
| 898 | return fmt.Errorf( |
| 899 | "collected metric %q { %s} has a label with an invalid name: %s", |
| 900 | name, dtoMetric, labelName, |
| 901 | ) |
| 902 | } |
| 903 | if dtoMetric.Summary != nil && labelName == quantileLabel { |
| 904 | return fmt.Errorf( |
| 905 | "collected metric %q { %s} must not have an explicit %q label", |
| 906 | name, dtoMetric, quantileLabel, |
| 907 | ) |
| 908 | } |
| 909 | if !utf8.ValidString(labelPair.GetValue()) { |
| 910 | return fmt.Errorf( |
| 911 | "collected metric %q { %s} has a label named %q whose value is not utf8: %#v", |
| 912 | name, dtoMetric, labelName, labelPair.GetValue()) |
| 913 | } |
| 914 | previousLabelName = labelName |
| 915 | } |
| 916 | |
| 917 | // Is the metric unique (i.e. no other metric with the same name and the same labels)? |
| 918 | h := xxhash.New() |
| 919 | h.WriteString(name) |
| 920 | h.Write(separatorByteSlice) |
| 921 | // Make sure label pairs are sorted. We depend on it for the consistency |
| 922 | // check. |
| 923 | if !sort.IsSorted(internal.LabelPairSorter(dtoMetric.Label)) { |
| 924 | // We cannot sort dtoMetric.Label in place as it is immutable by contract. |
| 925 | copiedLabels := make([]*dto.LabelPair, len(dtoMetric.Label)) |
| 926 | copy(copiedLabels, dtoMetric.Label) |
no test coverage detected