@@ -18,6 +18,7 @@ import (
18
18
"regexp"
19
19
"sort"
20
20
"strconv"
21
+ "strings"
21
22
"time"
22
23
23
24
"github.com/prometheus/common/model"
@@ -28,11 +29,11 @@ import (
28
29
// Function represents a function of the expression language and is
29
30
// used by function nodes.
30
31
type Function struct {
31
- Name string
32
- ArgTypes []model.ValueType
33
- OptionalArgs int
34
- ReturnType model.ValueType
35
- Call func (ev * evaluator , args Expressions ) model.Value
32
+ Name string
33
+ ArgTypes []model.ValueType
34
+ Variadic int
35
+ ReturnType model.ValueType
36
+ Call func (ev * evaluator , args Expressions ) model.Value
36
37
}
37
38
38
39
// === time() model.SampleValue ===
@@ -849,6 +850,50 @@ func funcLabelReplace(ev *evaluator, args Expressions) model.Value {
849
850
return vector
850
851
}
851
852
853
+ // === label_join(vector model.ValVector, dest_labelname, separator, src_labelname...) Vector ===
854
+ func funcLabelJoin (ev * evaluator , args Expressions ) model.Value {
855
+ var (
856
+ vector = ev .evalVector (args [0 ])
857
+ dst = model .LabelName (ev .evalString (args [1 ]).Value )
858
+ sep = ev .evalString (args [2 ]).Value
859
+ srcLabels = make ([]model.LabelName , len (args )- 3 )
860
+ )
861
+ for i := 3 ; i < len (args ); i ++ {
862
+ src := model .LabelName (ev .evalString (args [i ]).Value )
863
+ if ! model .LabelNameRE .MatchString (string (src )) {
864
+ ev .errorf ("invalid source label name in label_join(): %s" , src )
865
+ }
866
+ srcLabels [i - 3 ] = src
867
+ }
868
+
869
+ if ! model .LabelNameRE .MatchString (string (dst )) {
870
+ ev .errorf ("invalid destination label name in label_join(): %s" , dst )
871
+ }
872
+
873
+ outSet := make (map [model.Fingerprint ]struct {}, len (vector ))
874
+ for _ , el := range vector {
875
+ srcVals := make ([]string , len (srcLabels ))
876
+ for i , src := range srcLabels {
877
+ srcVals [i ] = string (el .Metric .Metric [src ])
878
+ }
879
+
880
+ strval := strings .Join (srcVals , sep )
881
+ if strval == "" {
882
+ el .Metric .Del (dst )
883
+ } else {
884
+ el .Metric .Set (dst , model .LabelValue (strval ))
885
+ }
886
+
887
+ fp := el .Metric .Metric .Fingerprint ()
888
+ if _ , exists := outSet [fp ]; exists {
889
+ ev .errorf ("duplicated label set in output of label_join(): %s" , el .Metric .Metric )
890
+ } else {
891
+ outSet [fp ] = struct {}{}
892
+ }
893
+ }
894
+ return vector
895
+ }
896
+
852
897
// === vector(s scalar) Vector ===
853
898
func funcVector (ev * evaluator , args Expressions ) model.Value {
854
899
return vector {
@@ -986,25 +1031,25 @@ var functions = map[string]*Function{
986
1031
Call : funcCountScalar ,
987
1032
},
988
1033
"days_in_month" : {
989
- Name : "days_in_month" ,
990
- ArgTypes : []model.ValueType {model .ValVector },
991
- OptionalArgs : 1 ,
992
- ReturnType : model .ValVector ,
993
- Call : funcDaysInMonth ,
1034
+ Name : "days_in_month" ,
1035
+ ArgTypes : []model.ValueType {model .ValVector },
1036
+ Variadic : 1 ,
1037
+ ReturnType : model .ValVector ,
1038
+ Call : funcDaysInMonth ,
994
1039
},
995
1040
"day_of_month" : {
996
- Name : "day_of_month" ,
997
- ArgTypes : []model.ValueType {model .ValVector },
998
- OptionalArgs : 1 ,
999
- ReturnType : model .ValVector ,
1000
- Call : funcDayOfMonth ,
1041
+ Name : "day_of_month" ,
1042
+ ArgTypes : []model.ValueType {model .ValVector },
1043
+ Variadic : 1 ,
1044
+ ReturnType : model .ValVector ,
1045
+ Call : funcDayOfMonth ,
1001
1046
},
1002
1047
"day_of_week" : {
1003
- Name : "day_of_week" ,
1004
- ArgTypes : []model.ValueType {model .ValVector },
1005
- OptionalArgs : 1 ,
1006
- ReturnType : model .ValVector ,
1007
- Call : funcDayOfWeek ,
1048
+ Name : "day_of_week" ,
1049
+ ArgTypes : []model.ValueType {model .ValVector },
1050
+ Variadic : 1 ,
1051
+ ReturnType : model .ValVector ,
1052
+ Call : funcDayOfWeek ,
1008
1053
},
1009
1054
"delta" : {
1010
1055
Name : "delta" ,
@@ -1049,11 +1094,11 @@ var functions = map[string]*Function{
1049
1094
Call : funcHoltWinters ,
1050
1095
},
1051
1096
"hour" : {
1052
- Name : "hour" ,
1053
- ArgTypes : []model.ValueType {model .ValVector },
1054
- OptionalArgs : 1 ,
1055
- ReturnType : model .ValVector ,
1056
- Call : funcHour ,
1097
+ Name : "hour" ,
1098
+ ArgTypes : []model.ValueType {model .ValVector },
1099
+ Variadic : 1 ,
1100
+ ReturnType : model .ValVector ,
1101
+ Call : funcHour ,
1057
1102
},
1058
1103
"idelta" : {
1059
1104
Name : "idelta" ,
@@ -1079,6 +1124,13 @@ var functions = map[string]*Function{
1079
1124
ReturnType : model .ValVector ,
1080
1125
Call : funcLabelReplace ,
1081
1126
},
1127
+ "label_join" : {
1128
+ Name : "label_join" ,
1129
+ ArgTypes : []model.ValueType {model .ValVector , model .ValString , model .ValString , model .ValString },
1130
+ Variadic : - 1 ,
1131
+ ReturnType : model .ValVector ,
1132
+ Call : funcLabelJoin ,
1133
+ },
1082
1134
"ln" : {
1083
1135
Name : "ln" ,
1084
1136
ArgTypes : []model.ValueType {model .ValVector },
@@ -1110,18 +1162,18 @@ var functions = map[string]*Function{
1110
1162
Call : funcMinOverTime ,
1111
1163
},
1112
1164
"minute" : {
1113
- Name : "minute" ,
1114
- ArgTypes : []model.ValueType {model .ValVector },
1115
- OptionalArgs : 1 ,
1116
- ReturnType : model .ValVector ,
1117
- Call : funcMinute ,
1165
+ Name : "minute" ,
1166
+ ArgTypes : []model.ValueType {model .ValVector },
1167
+ Variadic : 1 ,
1168
+ ReturnType : model .ValVector ,
1169
+ Call : funcMinute ,
1118
1170
},
1119
1171
"month" : {
1120
- Name : "month" ,
1121
- ArgTypes : []model.ValueType {model .ValVector },
1122
- OptionalArgs : 1 ,
1123
- ReturnType : model .ValVector ,
1124
- Call : funcMonth ,
1172
+ Name : "month" ,
1173
+ ArgTypes : []model.ValueType {model .ValVector },
1174
+ Variadic : 1 ,
1175
+ ReturnType : model .ValVector ,
1176
+ Call : funcMonth ,
1125
1177
},
1126
1178
"predict_linear" : {
1127
1179
Name : "predict_linear" ,
@@ -1148,11 +1200,11 @@ var functions = map[string]*Function{
1148
1200
Call : funcResets ,
1149
1201
},
1150
1202
"round" : {
1151
- Name : "round" ,
1152
- ArgTypes : []model.ValueType {model .ValVector , model .ValScalar },
1153
- OptionalArgs : 1 ,
1154
- ReturnType : model .ValVector ,
1155
- Call : funcRound ,
1203
+ Name : "round" ,
1204
+ ArgTypes : []model.ValueType {model .ValVector , model .ValScalar },
1205
+ Variadic : 1 ,
1206
+ ReturnType : model .ValVector ,
1207
+ Call : funcRound ,
1156
1208
},
1157
1209
"scalar" : {
1158
1210
Name : "scalar" ,
@@ -1209,11 +1261,11 @@ var functions = map[string]*Function{
1209
1261
Call : funcVector ,
1210
1262
},
1211
1263
"year" : {
1212
- Name : "year" ,
1213
- ArgTypes : []model.ValueType {model .ValVector },
1214
- OptionalArgs : 1 ,
1215
- ReturnType : model .ValVector ,
1216
- Call : funcYear ,
1264
+ Name : "year" ,
1265
+ ArgTypes : []model.ValueType {model .ValVector },
1266
+ Variadic : 1 ,
1267
+ ReturnType : model .ValVector ,
1268
+ Call : funcYear ,
1217
1269
},
1218
1270
}
1219
1271
0 commit comments