cloudflare/pint

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
e622a47c6fc350caabb3fe75c25cc3bfbd6feab6

Branches

Tags

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

Clone

HTTPS

Download ZIP

internal/parser/source/features.go

250lines · modecode

1package source
2
3import (
4 "fmt"
5 "strconv"
6 "strings"
7
8 promParser "github.com/prometheus/prometheus/promql/parser"
9)
10
11type PrometheusVersion struct {
12 Major int
13 Minor int
14 Patch int
15}
16
17func (v PrometheusVersion) String() string {
18 return fmt.Sprintf("%d.%d.%d", v.Major, v.Minor, v.Patch)
19}
20
21func (v PrometheusVersion) IsZero() bool {
22 return v.Major == 0 && v.Minor == 0 && v.Patch == 0
23}
24
25func (v PrometheusVersion) IsLessThan(other PrometheusVersion) bool {
26 if v.Major != other.Major {
27 return v.Major < other.Major
28 }
29 if v.Minor != other.Minor {
30 return v.Minor < other.Minor
31 }
32 return v.Patch < other.Patch
33}
34
35// ParseVersion parses a Prometheus version string like "2.49.0" or "3.5.0-rc.1"
36// into a PrometheusVersion.
37func ParseVersion(s string) (PrometheusVersion, error) {
38 raw := s
39 // Strip leading "v" if present (e.g. "v2.49.0").
40 s = strings.TrimPrefix(s, "v")
41 // Strip any pre-release suffix (e.g. "3.5.0-rc.1" -> "3.5.0").
42 if idx := strings.IndexByte(s, '-'); idx >= 0 {
43 s = s[:idx]
44 }
45 parts := strings.SplitN(s, ".", 3)
46 if len(parts) != 3 {
47 return PrometheusVersion{Major: 0, Minor: 0, Patch: 0},
48 fmt.Errorf("failed to parse Prometheus version %q: expected major.minor.patch format", raw)
49 }
50 major, err := strconv.Atoi(parts[0])
51 if err != nil {
52 return PrometheusVersion{Major: 0, Minor: 0, Patch: 0},
53 fmt.Errorf("failed to parse Prometheus version %q: %w", raw, err)
54 }
55 minor, err := strconv.Atoi(parts[1])
56 if err != nil {
57 return PrometheusVersion{Major: 0, Minor: 0, Patch: 0},
58 fmt.Errorf("failed to parse Prometheus version %q: %w", raw, err)
59 }
60 patch, err := strconv.Atoi(parts[2])
61 if err != nil {
62 return PrometheusVersion{Major: 0, Minor: 0, Patch: 0},
63 fmt.Errorf("failed to parse Prometheus version %q: %w", raw, err)
64 }
65 return PrometheusVersion{
66 Major: major,
67 Minor: minor,
68 Patch: patch,
69 }, nil
70}
71
72type FeatureVersion struct {
73 Flag string
74 MinVersion PrometheusVersion
75 StableVersion PrometheusVersion
76}
77
78func ver(major, minor, patch int) PrometheusVersion {
79 return PrometheusVersion{Major: major, Minor: minor, Patch: patch}
80}
81
82// Features is a registry of PromQL features that require feature flags.
83// It maps feature element names to their version and flag requirements.
84// Use the package-level default via LookupFeatureVersion, or create a
85// custom registry in tests via NewFeatures and SetFeatures.
86type Features struct {
87 entries map[string]FeatureVersion
88}
89
90// NewFeatures creates an empty feature registry.
91func NewFeatures() *Features {
92 return &Features{entries: map[string]FeatureVersion{}}
93}
94
95// Register adds a feature to the registry.
96func (f *Features) Register(name string, fv FeatureVersion) {
97 f.entries[name] = fv
98}
99
100// Lookup returns the FeatureVersion for a given feature element name, if registered.
101func (f *Features) Lookup(name string) (FeatureVersion, bool) {
102 v, ok := f.entries[name]
103 return v, ok
104}
105
106// defaultFeatures is the package-level feature registry used by
107// LookupFeatureVersion and requireFeature. Tests can replace it
108// via SetFeatures.
109var defaultFeatures = newDefaultFeatures()
110
111// newDefaultFeatures builds the standard feature registry with all
112// known experimental PromQL features.
113func newDefaultFeatures() *Features {
114 f := NewFeatures()
115
116 // Experimental functions behind promql-experimental-functions.
117 f.Register("mad_over_time", FeatureVersion{
118 Flag: FeatureExperimentalFunctions,
119 MinVersion: ver(2, 49, 0),
120 StableVersion: ver(0, 0, 0),
121 })
122 f.Register("sort_by_label", FeatureVersion{
123 Flag: FeatureExperimentalFunctions,
124 MinVersion: ver(2, 49, 0),
125 StableVersion: ver(0, 0, 0),
126 })
127 f.Register("sort_by_label_desc", FeatureVersion{
128 Flag: FeatureExperimentalFunctions,
129 MinVersion: ver(2, 49, 0),
130 StableVersion: ver(0, 0, 0),
131 })
132 f.Register("info", FeatureVersion{
133 Flag: FeatureExperimentalFunctions,
134 MinVersion: ver(2, 55, 0),
135 StableVersion: ver(0, 0, 0),
136 })
137 f.Register("double_exponential_smoothing", FeatureVersion{
138 Flag: FeatureExperimentalFunctions,
139 MinVersion: ver(3, 0, 0),
140 StableVersion: ver(0, 0, 0),
141 })
142 f.Register("ts_of_max_over_time", FeatureVersion{
143 Flag: FeatureExperimentalFunctions,
144 MinVersion: ver(3, 5, 0),
145 StableVersion: ver(0, 0, 0),
146 })
147 f.Register("ts_of_min_over_time", FeatureVersion{
148 Flag: FeatureExperimentalFunctions,
149 MinVersion: ver(3, 5, 0),
150 StableVersion: ver(0, 0, 0),
151 })
152 f.Register("ts_of_last_over_time", FeatureVersion{
153 Flag: FeatureExperimentalFunctions,
154 MinVersion: ver(3, 5, 0),
155 StableVersion: ver(0, 0, 0),
156 })
157 f.Register("first_over_time", FeatureVersion{
158 Flag: FeatureExperimentalFunctions,
159 MinVersion: ver(3, 7, 0),
160 StableVersion: ver(0, 0, 0),
161 })
162 f.Register("ts_of_first_over_time", FeatureVersion{
163 Flag: FeatureExperimentalFunctions,
164 MinVersion: ver(3, 7, 0),
165 StableVersion: ver(0, 0, 0),
166 })
167 f.Register("histogram_quantiles", FeatureVersion{
168 Flag: FeatureExperimentalFunctions,
169 MinVersion: ver(3, 11, 0),
170 StableVersion: ver(0, 0, 0),
171 })
172 f.Register("start", FeatureVersion{
173 Flag: FeatureExperimentalFunctions,
174 MinVersion: ver(3, 12, 0),
175 StableVersion: ver(0, 0, 0),
176 })
177 f.Register("end", FeatureVersion{
178 Flag: FeatureExperimentalFunctions,
179 MinVersion: ver(3, 12, 0),
180 StableVersion: ver(0, 0, 0),
181 })
182 f.Register("range", FeatureVersion{
183 Flag: FeatureExperimentalFunctions,
184 MinVersion: ver(3, 12, 0),
185 StableVersion: ver(0, 0, 0),
186 })
187 f.Register("step", FeatureVersion{
188 Flag: FeatureExperimentalFunctions,
189 MinVersion: ver(3, 12, 0),
190 StableVersion: ver(0, 0, 0),
191 })
192
193 // Experimental aggregation operators behind promql-experimental-functions.
194 f.Register(promParser.ItemTypeStr[promParser.LIMITK], FeatureVersion{
195 Flag: FeatureExperimentalFunctions,
196 MinVersion: ver(2, 54, 0),
197 StableVersion: ver(0, 0, 0),
198 })
199 f.Register(promParser.ItemTypeStr[promParser.LIMIT_RATIO], FeatureVersion{
200 Flag: FeatureExperimentalFunctions,
201 MinVersion: ver(2, 54, 0),
202 StableVersion: ver(0, 0, 0),
203 })
204
205 // Duration expressions behind promql-duration-expr.
206 f.Register("duration_expr", FeatureVersion{
207 Flag: FeatureDurationExpr,
208 MinVersion: ver(3, 4, 0),
209 StableVersion: ver(0, 0, 0),
210 })
211
212 // Extended range selectors behind promql-extended-range-selectors.
213 f.Register(promParser.ItemTypeStr[promParser.ANCHORED], FeatureVersion{
214 Flag: FeatureExtendedRangeSelectors,
215 MinVersion: ver(3, 7, 0),
216 StableVersion: ver(0, 0, 0),
217 })
218 f.Register(promParser.ItemTypeStr[promParser.SMOOTHED], FeatureVersion{
219 Flag: FeatureExtendedRangeSelectors,
220 MinVersion: ver(3, 7, 0),
221 StableVersion: ver(0, 0, 0),
222 })
223
224 // Fill modifiers behind promql-binop-fill-modifiers.
225 f.Register(promParser.ItemTypeStr[promParser.FILL], FeatureVersion{
226 Flag: FeatureBinopFillModifiers,
227 MinVersion: ver(3, 10, 0),
228 StableVersion: ver(0, 0, 0),
229 })
230
231 return f
232}
233
234// SetFeatures replaces the package-level feature registry.
235// Intended for use in tests to inject fake features.
236func SetFeatures(f *Features) {
237 defaultFeatures = f
238}
239
240// ResetFeatures restores the package-level feature registry to the
241// built-in defaults. Call this in test cleanup.
242func ResetFeatures() {
243 defaultFeatures = newDefaultFeatures()
244}
245
246// LookupFeatureVersion returns the FeatureVersion for a given feature
247// element name from the default registry, if it exists.
248func LookupFeatureVersion(name string) (FeatureVersion, bool) {
249 return defaultFeatures.Lookup(name)
250}
251