package util import ( "math" "sort" "strings" "time" "unsafe" "github.com/cortexproject/cortex/pkg/ingester/client" "github.com/prometheus/common/model" "github.com/prometheus/prometheus/pkg/labels" "github.com/grafana/loki/pkg/logql" ) type byLabel []client.LabelAdapter func (s byLabel) Len() int { return len(s) } func (s byLabel) Less(i, j int) bool { return strings.Compare(s[i].Name, s[j].Name) < 0 } func (s byLabel) Swap(i, j int) { s[i], s[j] = s[j], s[i] } // ToClientLabels parses the labels and converts them to the Cortex type. func ToClientLabels(labels string) ([]client.LabelAdapter, error) { matchers, err := logql.ParseMatchers(labels) if err != nil { return nil, err } result := make([]client.LabelAdapter, 0, len(matchers)) for _, m := range matchers { result = append(result, client.LabelAdapter{ Name: m.Name, Value: m.Value, }) } sort.Sort(byLabel(result)) return result, nil } // ParseLabels parses labels from a string using logql parser. func ParseLabels(lbs string) (labels.Labels, error) { matchers, err := logql.ParseMatchers(lbs) if err != nil { return nil, err } result := make(labels.Labels, 0, len(matchers)) for _, m := range matchers { result = append(result, labels.Label{ Name: m.Name, Value: m.Value, }) } sort.Sort(result) return result, nil } // ModelLabelSetToMap convert a model.LabelSet to a map[string]string func ModelLabelSetToMap(m model.LabelSet) map[string]string { if len(m) == 0 { return map[string]string{} } return *(*map[string]string)(unsafe.Pointer(&m)) } // MapToModelLabelSet converts a map into a model.LabelSet func MapToModelLabelSet(m map[string]string) model.LabelSet { if len(m) == 0 { return model.LabelSet{} } return *(*map[model.LabelName]model.LabelValue)(unsafe.Pointer(&m)) } // RoundToMilliseconds returns milliseconds precision time from nanoseconds. // from will be rounded down to the nearest milliseconds while through is rounded up. func RoundToMilliseconds(from, through time.Time) (model.Time, model.Time) { return model.Time(int64(math.Floor(float64(from.UnixNano()) / float64(time.Millisecond)))), model.Time(int64(math.Ceil(float64(through.UnixNano()) / float64(time.Millisecond)))) } // LabelsToMetric converts a Labels to Metric // Don't do this on any performance sensitive paths. func LabelsToMetric(ls labels.Labels) model.Metric { m := make(model.Metric, len(ls)) for _, l := range ls { m[model.LabelName(l.Name)] = model.LabelValue(l.Value) } return m }