github.com/muhammadn/cortex@v1.9.1-0.20220510110439-46bb7000d03d/pkg/configs/legacy_promql/printer.go (about) 1 // Copyright 2015 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 14 package promql 15 16 import ( 17 "fmt" 18 "sort" 19 "strings" 20 "time" 21 22 "github.com/prometheus/common/model" 23 "github.com/prometheus/prometheus/pkg/labels" 24 ) 25 26 // Tree returns a string of the tree structure of the given node. 27 func Tree(node Node) string { 28 return tree(node, "") 29 } 30 31 func tree(node Node, level string) string { 32 if node == nil { 33 return fmt.Sprintf("%s |---- %T\n", level, node) 34 } 35 typs := strings.Split(fmt.Sprintf("%T", node), ".")[1] 36 37 var t string 38 // Only print the number of statements for readability. 39 if stmts, ok := node.(Statements); ok { 40 t = fmt.Sprintf("%s |---- %s :: %d\n", level, typs, len(stmts)) 41 } else { 42 t = fmt.Sprintf("%s |---- %s :: %s\n", level, typs, node) 43 } 44 45 level += " · · ·" 46 47 switch n := node.(type) { 48 case Statements: 49 for _, s := range n { 50 t += tree(s, level) 51 } 52 case *AlertStmt: 53 t += tree(n.Expr, level) 54 55 case *EvalStmt: 56 t += tree(n.Expr, level) 57 58 case *RecordStmt: 59 t += tree(n.Expr, level) 60 61 case Expressions: 62 for _, e := range n { 63 t += tree(e, level) 64 } 65 case *AggregateExpr: 66 t += tree(n.Expr, level) 67 68 case *BinaryExpr: 69 t += tree(n.LHS, level) 70 t += tree(n.RHS, level) 71 72 case *Call: 73 t += tree(n.Args, level) 74 75 case *ParenExpr: 76 t += tree(n.Expr, level) 77 78 case *UnaryExpr: 79 t += tree(n.Expr, level) 80 81 case *MatrixSelector, *NumberLiteral, *StringLiteral, *VectorSelector: 82 // nothing to do 83 84 default: 85 panic("promql.Tree: not all node types covered") 86 } 87 return t 88 } 89 90 func (stmts Statements) String() (s string) { 91 if len(stmts) == 0 { 92 return "" 93 } 94 for _, stmt := range stmts { 95 s += stmt.String() 96 s += "\n\n" 97 } 98 return s[:len(s)-2] 99 } 100 101 func (node *AlertStmt) String() string { 102 s := fmt.Sprintf("ALERT %s", node.Name) 103 s += fmt.Sprintf("\n\tIF %s", node.Expr) 104 if node.Duration > 0 { 105 s += fmt.Sprintf("\n\tFOR %s", model.Duration(node.Duration)) 106 } 107 if len(node.Labels) > 0 { 108 s += fmt.Sprintf("\n\tLABELS %s", node.Labels) 109 } 110 if len(node.Annotations) > 0 { 111 s += fmt.Sprintf("\n\tANNOTATIONS %s", node.Annotations) 112 } 113 return s 114 } 115 116 func (node *EvalStmt) String() string { 117 return "EVAL " + node.Expr.String() 118 } 119 120 func (node *RecordStmt) String() string { 121 s := fmt.Sprintf("%s%s = %s", node.Name, node.Labels, node.Expr) 122 return s 123 } 124 125 func (es Expressions) String() (s string) { 126 if len(es) == 0 { 127 return "" 128 } 129 for _, e := range es { 130 s += e.String() 131 s += ", " 132 } 133 return s[:len(s)-2] 134 } 135 136 func (node *AggregateExpr) String() string { 137 aggrString := node.Op.String() 138 139 if node.Without { 140 aggrString += fmt.Sprintf(" without(%s) ", strings.Join(node.Grouping, ", ")) 141 } else { 142 if len(node.Grouping) > 0 { 143 aggrString += fmt.Sprintf(" by(%s) ", strings.Join(node.Grouping, ", ")) 144 } 145 } 146 147 aggrString += "(" 148 if node.Op.isAggregatorWithParam() { 149 aggrString += fmt.Sprintf("%s, ", node.Param) 150 } 151 aggrString += fmt.Sprintf("%s)", node.Expr) 152 153 return aggrString 154 } 155 156 func (node *BinaryExpr) String() string { 157 returnBool := "" 158 if node.ReturnBool { 159 returnBool = " bool" 160 } 161 162 matching := "" 163 vm := node.VectorMatching 164 if vm != nil && (len(vm.MatchingLabels) > 0 || vm.On) { 165 if vm.On { 166 matching = fmt.Sprintf(" on(%s)", strings.Join(vm.MatchingLabels, ", ")) 167 } else { 168 matching = fmt.Sprintf(" ignoring(%s)", strings.Join(vm.MatchingLabels, ", ")) 169 } 170 if vm.Card == CardManyToOne || vm.Card == CardOneToMany { 171 matching += " group_" 172 if vm.Card == CardManyToOne { 173 matching += "left" 174 } else { 175 matching += "right" 176 } 177 matching += fmt.Sprintf("(%s)", strings.Join(vm.Include, ", ")) 178 } 179 } 180 return fmt.Sprintf("%s %s%s%s %s", node.LHS, node.Op, returnBool, matching, node.RHS) 181 } 182 183 func (node *Call) String() string { 184 return fmt.Sprintf("%s(%s)", node.Func.Name, node.Args) 185 } 186 187 func (node *MatrixSelector) String() string { 188 vecSelector := &VectorSelector{ 189 Name: node.Name, 190 LabelMatchers: node.LabelMatchers, 191 } 192 offset := "" 193 if node.Offset != time.Duration(0) { 194 offset = fmt.Sprintf(" offset %s", model.Duration(node.Offset)) 195 } 196 return fmt.Sprintf("%s[%s]%s", vecSelector.String(), model.Duration(node.Range), offset) 197 } 198 199 func (node *NumberLiteral) String() string { 200 return fmt.Sprint(node.Val) 201 } 202 203 func (node *ParenExpr) String() string { 204 return fmt.Sprintf("(%s)", node.Expr) 205 } 206 207 func (node *StringLiteral) String() string { 208 return fmt.Sprintf("%q", node.Val) 209 } 210 211 func (node *UnaryExpr) String() string { 212 return fmt.Sprintf("%s%s", node.Op, node.Expr) 213 } 214 215 func (node *VectorSelector) String() string { 216 labelStrings := make([]string, 0, len(node.LabelMatchers)-1) 217 for _, matcher := range node.LabelMatchers { 218 // Only include the __name__ label if its no equality matching. 219 if matcher.Name == labels.MetricName && matcher.Type == labels.MatchEqual { 220 continue 221 } 222 labelStrings = append(labelStrings, matcher.String()) 223 } 224 offset := "" 225 if node.Offset != time.Duration(0) { 226 offset = fmt.Sprintf(" offset %s", model.Duration(node.Offset)) 227 } 228 229 if len(labelStrings) == 0 { 230 return fmt.Sprintf("%s%s", node.Name, offset) 231 } 232 sort.Strings(labelStrings) 233 return fmt.Sprintf("%s{%s}%s", node.Name, strings.Join(labelStrings, ","), offset) 234 }