cubefs
144 строки · 4.3 Кб
1// Copyright 2014 The Prometheus Authors
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14package model15
16import (17"sort"18)
19
20// SeparatorByte is a byte that cannot occur in valid UTF-8 sequences and is
21// used to separate label names, label values, and other strings from each other
22// when calculating their combined hash value (aka signature aka fingerprint).
23const SeparatorByte byte = 25524
25var (26// cache the signature of an empty label set.27emptyLabelSignature = hashNew()28)
29
30// LabelsToSignature returns a quasi-unique signature (i.e., fingerprint) for a
31// given label set. (Collisions are possible but unlikely if the number of label
32// sets the function is applied to is small.)
33func LabelsToSignature(labels map[string]string) uint64 {34if len(labels) == 0 {35return emptyLabelSignature36}37
38labelNames := make([]string, 0, len(labels))39for labelName := range labels {40labelNames = append(labelNames, labelName)41}42sort.Strings(labelNames)43
44sum := hashNew()45for _, labelName := range labelNames {46sum = hashAdd(sum, labelName)47sum = hashAddByte(sum, SeparatorByte)48sum = hashAdd(sum, labels[labelName])49sum = hashAddByte(sum, SeparatorByte)50}51return sum52}
53
54// labelSetToFingerprint works exactly as LabelsToSignature but takes a LabelSet as
55// parameter (rather than a label map) and returns a Fingerprint.
56func labelSetToFingerprint(ls LabelSet) Fingerprint {57if len(ls) == 0 {58return Fingerprint(emptyLabelSignature)59}60
61labelNames := make(LabelNames, 0, len(ls))62for labelName := range ls {63labelNames = append(labelNames, labelName)64}65sort.Sort(labelNames)66
67sum := hashNew()68for _, labelName := range labelNames {69sum = hashAdd(sum, string(labelName))70sum = hashAddByte(sum, SeparatorByte)71sum = hashAdd(sum, string(ls[labelName]))72sum = hashAddByte(sum, SeparatorByte)73}74return Fingerprint(sum)75}
76
77// labelSetToFastFingerprint works similar to labelSetToFingerprint but uses a
78// faster and less allocation-heavy hash function, which is more susceptible to
79// create hash collisions. Therefore, collision detection should be applied.
80func labelSetToFastFingerprint(ls LabelSet) Fingerprint {81if len(ls) == 0 {82return Fingerprint(emptyLabelSignature)83}84
85var result uint6486for labelName, labelValue := range ls {87sum := hashNew()88sum = hashAdd(sum, string(labelName))89sum = hashAddByte(sum, SeparatorByte)90sum = hashAdd(sum, string(labelValue))91result ^= sum92}93return Fingerprint(result)94}
95
96// SignatureForLabels works like LabelsToSignature but takes a Metric as
97// parameter (rather than a label map) and only includes the labels with the
98// specified LabelNames into the signature calculation. The labels passed in
99// will be sorted by this function.
100func SignatureForLabels(m Metric, labels ...LabelName) uint64 {101if len(labels) == 0 {102return emptyLabelSignature103}104
105sort.Sort(LabelNames(labels))106
107sum := hashNew()108for _, label := range labels {109sum = hashAdd(sum, string(label))110sum = hashAddByte(sum, SeparatorByte)111sum = hashAdd(sum, string(m[label]))112sum = hashAddByte(sum, SeparatorByte)113}114return sum115}
116
117// SignatureWithoutLabels works like LabelsToSignature but takes a Metric as
118// parameter (rather than a label map) and excludes the labels with any of the
119// specified LabelNames from the signature calculation.
120func SignatureWithoutLabels(m Metric, labels map[LabelName]struct{}) uint64 {121if len(m) == 0 {122return emptyLabelSignature123}124
125labelNames := make(LabelNames, 0, len(m))126for labelName := range m {127if _, exclude := labels[labelName]; !exclude {128labelNames = append(labelNames, labelName)129}130}131if len(labelNames) == 0 {132return emptyLabelSignature133}134sort.Sort(labelNames)135
136sum := hashNew()137for _, labelName := range labelNames {138sum = hashAdd(sum, string(labelName))139sum = hashAddByte(sum, SeparatorByte)140sum = hashAdd(sum, string(m[labelName]))141sum = hashAddByte(sum, SeparatorByte)142}143return sum144}
145