|
|
|
|
@ -18,6 +18,7 @@ import ( |
|
|
|
|
"regexp" |
|
|
|
|
"sort" |
|
|
|
|
"strconv" |
|
|
|
|
"strings" |
|
|
|
|
"time" |
|
|
|
|
|
|
|
|
|
"github.com/prometheus/common/model" |
|
|
|
|
@ -28,11 +29,11 @@ import ( |
|
|
|
|
// Function represents a function of the expression language and is
|
|
|
|
|
// used by function nodes.
|
|
|
|
|
type Function struct { |
|
|
|
|
Name string |
|
|
|
|
ArgTypes []model.ValueType |
|
|
|
|
OptionalArgs int |
|
|
|
|
ReturnType model.ValueType |
|
|
|
|
Call func(ev *evaluator, args Expressions) model.Value |
|
|
|
|
Name string |
|
|
|
|
ArgTypes []model.ValueType |
|
|
|
|
Variadic int |
|
|
|
|
ReturnType model.ValueType |
|
|
|
|
Call func(ev *evaluator, args Expressions) model.Value |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// === time() model.SampleValue ===
|
|
|
|
|
@ -849,6 +850,50 @@ func funcLabelReplace(ev *evaluator, args Expressions) model.Value { |
|
|
|
|
return vector |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// === label_join(vector model.ValVector, dest_labelname, separator, src_labelname...) Vector ===
|
|
|
|
|
func funcLabelJoin(ev *evaluator, args Expressions) model.Value { |
|
|
|
|
var ( |
|
|
|
|
vector = ev.evalVector(args[0]) |
|
|
|
|
dst = model.LabelName(ev.evalString(args[1]).Value) |
|
|
|
|
sep = ev.evalString(args[2]).Value |
|
|
|
|
srcLabels = make([]model.LabelName, len(args)-3) |
|
|
|
|
) |
|
|
|
|
for i := 3; i < len(args); i++ { |
|
|
|
|
src := model.LabelName(ev.evalString(args[i]).Value) |
|
|
|
|
if !model.LabelNameRE.MatchString(string(src)) { |
|
|
|
|
ev.errorf("invalid source label name in label_join(): %s", src) |
|
|
|
|
} |
|
|
|
|
srcLabels[i-3] = src |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if !model.LabelNameRE.MatchString(string(dst)) { |
|
|
|
|
ev.errorf("invalid destination label name in label_join(): %s", dst) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
outSet := make(map[model.Fingerprint]struct{}, len(vector)) |
|
|
|
|
for _, el := range vector { |
|
|
|
|
srcVals := make([]string, len(srcLabels)) |
|
|
|
|
for i, src := range srcLabels { |
|
|
|
|
srcVals[i] = string(el.Metric.Metric[src]) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
strval := strings.Join(srcVals, sep) |
|
|
|
|
if strval == "" { |
|
|
|
|
el.Metric.Del(dst) |
|
|
|
|
} else { |
|
|
|
|
el.Metric.Set(dst, model.LabelValue(strval)) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fp := el.Metric.Metric.Fingerprint() |
|
|
|
|
if _, exists := outSet[fp]; exists { |
|
|
|
|
ev.errorf("duplicated label set in output of label_join(): %s", el.Metric.Metric) |
|
|
|
|
} else { |
|
|
|
|
outSet[fp] = struct{}{} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return vector |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// === vector(s scalar) Vector ===
|
|
|
|
|
func funcVector(ev *evaluator, args Expressions) model.Value { |
|
|
|
|
return vector{ |
|
|
|
|
@ -986,25 +1031,25 @@ var functions = map[string]*Function{ |
|
|
|
|
Call: funcCountScalar, |
|
|
|
|
}, |
|
|
|
|
"days_in_month": { |
|
|
|
|
Name: "days_in_month", |
|
|
|
|
ArgTypes: []model.ValueType{model.ValVector}, |
|
|
|
|
OptionalArgs: 1, |
|
|
|
|
ReturnType: model.ValVector, |
|
|
|
|
Call: funcDaysInMonth, |
|
|
|
|
Name: "days_in_month", |
|
|
|
|
ArgTypes: []model.ValueType{model.ValVector}, |
|
|
|
|
Variadic: 1, |
|
|
|
|
ReturnType: model.ValVector, |
|
|
|
|
Call: funcDaysInMonth, |
|
|
|
|
}, |
|
|
|
|
"day_of_month": { |
|
|
|
|
Name: "day_of_month", |
|
|
|
|
ArgTypes: []model.ValueType{model.ValVector}, |
|
|
|
|
OptionalArgs: 1, |
|
|
|
|
ReturnType: model.ValVector, |
|
|
|
|
Call: funcDayOfMonth, |
|
|
|
|
Name: "day_of_month", |
|
|
|
|
ArgTypes: []model.ValueType{model.ValVector}, |
|
|
|
|
Variadic: 1, |
|
|
|
|
ReturnType: model.ValVector, |
|
|
|
|
Call: funcDayOfMonth, |
|
|
|
|
}, |
|
|
|
|
"day_of_week": { |
|
|
|
|
Name: "day_of_week", |
|
|
|
|
ArgTypes: []model.ValueType{model.ValVector}, |
|
|
|
|
OptionalArgs: 1, |
|
|
|
|
ReturnType: model.ValVector, |
|
|
|
|
Call: funcDayOfWeek, |
|
|
|
|
Name: "day_of_week", |
|
|
|
|
ArgTypes: []model.ValueType{model.ValVector}, |
|
|
|
|
Variadic: 1, |
|
|
|
|
ReturnType: model.ValVector, |
|
|
|
|
Call: funcDayOfWeek, |
|
|
|
|
}, |
|
|
|
|
"delta": { |
|
|
|
|
Name: "delta", |
|
|
|
|
@ -1049,11 +1094,11 @@ var functions = map[string]*Function{ |
|
|
|
|
Call: funcHoltWinters, |
|
|
|
|
}, |
|
|
|
|
"hour": { |
|
|
|
|
Name: "hour", |
|
|
|
|
ArgTypes: []model.ValueType{model.ValVector}, |
|
|
|
|
OptionalArgs: 1, |
|
|
|
|
ReturnType: model.ValVector, |
|
|
|
|
Call: funcHour, |
|
|
|
|
Name: "hour", |
|
|
|
|
ArgTypes: []model.ValueType{model.ValVector}, |
|
|
|
|
Variadic: 1, |
|
|
|
|
ReturnType: model.ValVector, |
|
|
|
|
Call: funcHour, |
|
|
|
|
}, |
|
|
|
|
"idelta": { |
|
|
|
|
Name: "idelta", |
|
|
|
|
@ -1079,6 +1124,13 @@ var functions = map[string]*Function{ |
|
|
|
|
ReturnType: model.ValVector, |
|
|
|
|
Call: funcLabelReplace, |
|
|
|
|
}, |
|
|
|
|
"label_join": { |
|
|
|
|
Name: "label_join", |
|
|
|
|
ArgTypes: []model.ValueType{model.ValVector, model.ValString, model.ValString, model.ValString}, |
|
|
|
|
Variadic: -1, |
|
|
|
|
ReturnType: model.ValVector, |
|
|
|
|
Call: funcLabelJoin, |
|
|
|
|
}, |
|
|
|
|
"ln": { |
|
|
|
|
Name: "ln", |
|
|
|
|
ArgTypes: []model.ValueType{model.ValVector}, |
|
|
|
|
@ -1110,18 +1162,18 @@ var functions = map[string]*Function{ |
|
|
|
|
Call: funcMinOverTime, |
|
|
|
|
}, |
|
|
|
|
"minute": { |
|
|
|
|
Name: "minute", |
|
|
|
|
ArgTypes: []model.ValueType{model.ValVector}, |
|
|
|
|
OptionalArgs: 1, |
|
|
|
|
ReturnType: model.ValVector, |
|
|
|
|
Call: funcMinute, |
|
|
|
|
Name: "minute", |
|
|
|
|
ArgTypes: []model.ValueType{model.ValVector}, |
|
|
|
|
Variadic: 1, |
|
|
|
|
ReturnType: model.ValVector, |
|
|
|
|
Call: funcMinute, |
|
|
|
|
}, |
|
|
|
|
"month": { |
|
|
|
|
Name: "month", |
|
|
|
|
ArgTypes: []model.ValueType{model.ValVector}, |
|
|
|
|
OptionalArgs: 1, |
|
|
|
|
ReturnType: model.ValVector, |
|
|
|
|
Call: funcMonth, |
|
|
|
|
Name: "month", |
|
|
|
|
ArgTypes: []model.ValueType{model.ValVector}, |
|
|
|
|
Variadic: 1, |
|
|
|
|
ReturnType: model.ValVector, |
|
|
|
|
Call: funcMonth, |
|
|
|
|
}, |
|
|
|
|
"predict_linear": { |
|
|
|
|
Name: "predict_linear", |
|
|
|
|
@ -1148,11 +1200,11 @@ var functions = map[string]*Function{ |
|
|
|
|
Call: funcResets, |
|
|
|
|
}, |
|
|
|
|
"round": { |
|
|
|
|
Name: "round", |
|
|
|
|
ArgTypes: []model.ValueType{model.ValVector, model.ValScalar}, |
|
|
|
|
OptionalArgs: 1, |
|
|
|
|
ReturnType: model.ValVector, |
|
|
|
|
Call: funcRound, |
|
|
|
|
Name: "round", |
|
|
|
|
ArgTypes: []model.ValueType{model.ValVector, model.ValScalar}, |
|
|
|
|
Variadic: 1, |
|
|
|
|
ReturnType: model.ValVector, |
|
|
|
|
Call: funcRound, |
|
|
|
|
}, |
|
|
|
|
"scalar": { |
|
|
|
|
Name: "scalar", |
|
|
|
|
@ -1209,11 +1261,11 @@ var functions = map[string]*Function{ |
|
|
|
|
Call: funcVector, |
|
|
|
|
}, |
|
|
|
|
"year": { |
|
|
|
|
Name: "year", |
|
|
|
|
ArgTypes: []model.ValueType{model.ValVector}, |
|
|
|
|
OptionalArgs: 1, |
|
|
|
|
ReturnType: model.ValVector, |
|
|
|
|
Call: funcYear, |
|
|
|
|
Name: "year", |
|
|
|
|
ArgTypes: []model.ValueType{model.ValVector}, |
|
|
|
|
Variadic: 1, |
|
|
|
|
ReturnType: model.ValVector, |
|
|
|
|
Call: funcYear, |
|
|
|
|
}, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|