cloudflare/pint

Public

mirrored from https://github.com/cloudflare/pintAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
main

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

cmd/pint/parse.go

183lines · modecode

1package main
2
3import (
4 "context"
5 "errors"
6 "fmt"
7 "io"
8 "os"
9 "strings"
10
11 promParser "github.com/prometheus/prometheus/promql/parser"
12 "github.com/urfave/cli/v3"
13
14 "github.com/cloudflare/pint/internal/parser"
15)
16
17const levelStep = 2
18
19var parseCmd = &cli.Command{
20 Name: "parse",
21 Usage: "Parse a query and print AST, use it for debugging or understanding query details.",
22 Action: actionParse,
23}
24
25func printNode(w io.Writer, ident int, format string, a ...any) {
26 prefix := strings.Repeat(" ", ident)
27 _, _ = fmt.Fprintf(w, prefix+format+"\n", a...)
28}
29
30func parseNode(w io.Writer, node promParser.Node, level int) {
31 printNode(w, level, "++ node: %v", node)
32 level += levelStep
33
34 switch n := node.(type) {
35 case promParser.Expressions:
36 printNode(w, level, "Expressions:")
37 for _, e := range n {
38 parseNode(w, e, level+levelStep)
39 }
40 case *promParser.AggregateExpr:
41 printNode(w, level, "AggregateExpr:")
42 level += levelStep
43 printNode(w, level, "* Type: %v", n.Type())
44 printNode(w, level, "* Op: %v", n.Op)
45 printNode(w, level, "* Expr: %v", n.Expr)
46 printNode(w, level, "* Param: %v", n.Param)
47 printNode(w, level, "* Grouping: %v", n.Grouping)
48 printNode(w, level, "* Without: %v", n.Without)
49 parseNode(w, n.Expr, level+levelStep)
50 case *promParser.BinaryExpr:
51 printNode(w, level, "BinaryExpr:")
52 level += levelStep
53 printNode(w, level, "* Type: %v", n.Type())
54 printNode(w, level, "* Op: %v", n.Op)
55 printNode(w, level, "* LHS: %v", n.LHS)
56 printNode(w, level, "* RHS: %v", n.RHS)
57 printNode(w, level, "* VectorMatching:")
58 if n.VectorMatching != nil {
59 printNode(w, level+levelStep, "* Card: %v", n.VectorMatching.Card)
60 printNode(w, level+levelStep, "* MatchingLabels: %v", n.VectorMatching.MatchingLabels)
61 printNode(w, level+levelStep, "* On: %v", n.VectorMatching.On)
62 printNode(w, level+levelStep, "* Include: %v", n.VectorMatching.Include)
63 if n.VectorMatching.FillValues.LHS != nil {
64 printNode(w, level+levelStep, "* FillLHS: %v", *n.VectorMatching.FillValues.LHS)
65 }
66 if n.VectorMatching.FillValues.RHS != nil {
67 printNode(w, level+levelStep, "* FillRHS: %v", *n.VectorMatching.FillValues.RHS)
68 }
69 }
70 printNode(w, level, "* ReturnBool: %v", n.ReturnBool)
71 parseNode(w, n.LHS, level+levelStep)
72 parseNode(w, n.RHS, level+levelStep)
73 case *promParser.Call:
74 printNode(w, level, "Call:")
75 level += levelStep
76 printNode(w, level, "* Type: %v", n.Type())
77 printNode(w, level, "* Func: %v", n.Func.Name)
78 printNode(w, level, "* Args: %v", n.Args)
79 parseNode(w, n.Args, level+levelStep)
80 case *promParser.ParenExpr:
81 printNode(w, level, "ParenExpr:")
82 level += levelStep
83 printNode(w, level, "* Type: %v", n.Type())
84 printNode(w, level, "* Expr: %v", n.Expr)
85 parseNode(w, n.Expr, level+levelStep)
86 case *promParser.SubqueryExpr:
87 printNode(w, level, "SubqueryExpr:")
88 level += levelStep
89 printNode(w, level, "* Type: %v", n.Type())
90 printNode(w, level, "* Expr: %v", n.Expr)
91 printNode(w, level, "* Step: %v", n.Step)
92 if n.StepExpr != nil {
93 printNode(w, level, "* StepExpr: %v", n.StepExpr)
94 parseNode(w, n.StepExpr, level+levelStep)
95 }
96 printNode(w, level, "* Range: %v", n.Range)
97 if n.RangeExpr != nil {
98 printNode(w, level, "* RangeExpr: %v", n.RangeExpr)
99 parseNode(w, n.RangeExpr, level+levelStep)
100 }
101 printNode(w, level, "* Offset: %v", n.Offset)
102 if n.OriginalOffsetExpr != nil {
103 printNode(w, level, "* OriginalOffsetExpr: %v", n.OriginalOffsetExpr)
104 parseNode(w, n.OriginalOffsetExpr, level+levelStep)
105 }
106 parseNode(w, n.Expr, level+levelStep)
107 case *promParser.MatrixSelector:
108 printNode(w, level, "MatrixSelector:")
109 level += levelStep
110 printNode(w, level, "* Type: %v", n.Type())
111 printNode(w, level, "* VectorSelector: %v", n.VectorSelector)
112 printNode(w, level, "* Range: %v", n.Range)
113 if n.RangeExpr != nil {
114 printNode(w, level, "* RangeExpr: %v", n.RangeExpr)
115 parseNode(w, n.RangeExpr, level+levelStep)
116 }
117 case *promParser.VectorSelector:
118 printNode(w, level, "VectorSelector:")
119 level += levelStep
120 printNode(w, level, "* Type: %v", n.Type())
121 printNode(w, level, "* Name: %v", n.Name)
122 printNode(w, level, "* Offset: %v", n.Offset)
123 if n.OriginalOffsetExpr != nil {
124 printNode(w, level, "* OriginalOffsetExpr: %v", n.OriginalOffsetExpr)
125 parseNode(w, n.OriginalOffsetExpr, level+levelStep)
126 }
127 printNode(w, level, "* LabelMatchers: %v", n.LabelMatchers)
128 if n.Anchored {
129 printNode(w, level, "* Anchored: true")
130 }
131 if n.Smoothed {
132 printNode(w, level, "* Smoothed: true")
133 }
134 case *promParser.NumberLiteral:
135 printNode(w, level, "NumberLiteral:")
136 level += levelStep
137 printNode(w, level, "* Type: %v", n.Type())
138 case *promParser.StringLiteral:
139 printNode(w, level, "StringLiteral:")
140 level += levelStep
141 printNode(w, level, "* Type: %v", n.Type())
142 case *promParser.DurationExpr:
143 printNode(w, level, "DurationExpr:")
144 level += levelStep
145 printNode(w, level, "* Type: %v", n.Type())
146 printNode(w, level, "* Op: %v", n.Op)
147 printNode(w, level, "* LHS: %v", n.LHS)
148 printNode(w, level, "* RHS: %v", n.RHS)
149 printNode(w, level, "* Wrapped: %v", n.Wrapped)
150 case *promParser.UnaryExpr:
151 printNode(w, level, "UnaryExpr:")
152 level += levelStep
153 printNode(w, level, "* Type: %v", n.Type())
154 printNode(w, level, "* Op: %v", n.Op)
155 printNode(w, level, "* Expr: %v", n.Expr)
156 default:
157 printNode(w, level, "! Unsupported node")
158 }
159}
160
161func parseQuery(w io.Writer, query string) error {
162 expr, err := parser.PromQLParser.ParseExpr(query)
163 if err != nil {
164 return err
165 }
166 parseNode(w, expr, 0)
167 return nil
168}
169
170func actionParse(_ context.Context, c *cli.Command) (err error) {
171 err = initLogger(c.String(logLevelFlag), c.Bool(noColorFlag))
172 if err != nil {
173 return fmt.Errorf("failed to set log level: %w", err)
174 }
175
176 parts := c.Args().Slice()
177 if len(parts) == 0 {
178 return errors.New("a query string is required")
179 }
180
181 query := strings.Join(parts, " ")
182 return parseQuery(os.Stdout, query)
183}
184