diff --git a/app/vmselect/main.go b/app/vmselect/main.go index 71c2c00b1e..af80bd4131 100644 --- a/app/vmselect/main.go +++ b/app/vmselect/main.go @@ -477,7 +477,6 @@ func RequestHandler(w http.ResponseWriter, r *http.Request) bool { return true case "/expand-with-exprs": expandWithExprsRequests.Inc() - httpserver.EnableCORS(w, r) prometheus.ExpandWithExprs(w, r) return true case "/api/v1/rules", "/rules": diff --git a/app/vmselect/prometheus/expand-with-exprs.qtpl b/app/vmselect/prometheus/expand-with-exprs.qtpl index 5e42d71a57..604f10fd0d 100644 --- a/app/vmselect/prometheus/expand-with-exprs.qtpl +++ b/app/vmselect/prometheus/expand-with-exprs.qtpl @@ -54,6 +54,28 @@ textarea { margin: 1em } {% endif %} {% endfunc %} +{% func ExpandWithExprsJSONResponse(q string) %} + {% if len(q) == 0 %} + { + "status": "error", + "error": "query string cannot be empty" + } + {% return %} + {% endif %} + +{ + {% code expr, err := metricsql.Parse(q) %} + {% if err != nil %} + "status": "error", + "error": {%q fmt.Sprintf("Cannot parse query: %s", err) %} + {% else %} + {% code expr = metricsql.Optimize(expr) %} + "status": "success", + "expr": {%qz expr.AppendString(nil) %} + {% endif %} +} +{% endfunc %} + {% endstripspace %} {% func withExprsTutorial() %} @@ -244,31 +266,3 @@ WITH ( </pre> {% endfunc %} - -{% stripspace %} -{% func ExpandWithExprsJSONResponse(q string) %} - {%= expandWithExprsJSON(q) %} -{% endfunc %} - -{% func expandWithExprsJSON(q string) %} - {% if len(q) == 0 %} - { - "status": "error", - "error": "query string cannot be empty" - } - {% return %} - {% endif %} - -{ - {% code expr, err := metricsql.Parse(q) %} - {% if err != nil %} - "status": "error", - "error": {%q= fmt.Sprintf("Cannot parse query: %s", err) %} - {% else %} - {% code expr = metricsql.Optimize(expr) %} - "status": "success", - "expr": {%q= string(expr.AppendString(nil)) %} - {% endif %} -} -{% endfunc %} -{% endstripspace %} diff --git a/app/vmselect/prometheus/expand-with-exprs.qtpl.go b/app/vmselect/prometheus/expand-with-exprs.qtpl.go index aa65c7fec0..2fd45395bc 100644 --- a/app/vmselect/prometheus/expand-with-exprs.qtpl.go +++ b/app/vmselect/prometheus/expand-with-exprs.qtpl.go @@ -125,9 +125,72 @@ func expandWithExprs(q string) string { //line app/vmselect/prometheus/expand-with-exprs.qtpl:55 } -//line app/vmselect/prometheus/expand-with-exprs.qtpl:59 +//line app/vmselect/prometheus/expand-with-exprs.qtpl:57 +func StreamExpandWithExprsJSONResponse(qw422016 *qt422016.Writer, q string) { +//line app/vmselect/prometheus/expand-with-exprs.qtpl:58 + if len(q) == 0 { +//line app/vmselect/prometheus/expand-with-exprs.qtpl:58 + qw422016.N().S(`{"status": "error","error": "query string cannot be empty"}`) +//line app/vmselect/prometheus/expand-with-exprs.qtpl:63 + return +//line app/vmselect/prometheus/expand-with-exprs.qtpl:64 + } +//line app/vmselect/prometheus/expand-with-exprs.qtpl:64 + qw422016.N().S(`{`) +//line app/vmselect/prometheus/expand-with-exprs.qtpl:67 + expr, err := metricsql.Parse(q) + +//line app/vmselect/prometheus/expand-with-exprs.qtpl:68 + if err != nil { +//line app/vmselect/prometheus/expand-with-exprs.qtpl:68 + qw422016.N().S(`"status": "error","error":`) +//line app/vmselect/prometheus/expand-with-exprs.qtpl:70 + qw422016.E().Q(fmt.Sprintf("Cannot parse query: %s", err)) +//line app/vmselect/prometheus/expand-with-exprs.qtpl:71 + } else { +//line app/vmselect/prometheus/expand-with-exprs.qtpl:72 + expr = metricsql.Optimize(expr) + +//line app/vmselect/prometheus/expand-with-exprs.qtpl:72 + qw422016.N().S(`"status": "success","expr":`) +//line app/vmselect/prometheus/expand-with-exprs.qtpl:74 + qw422016.E().QZ(expr.AppendString(nil)) +//line app/vmselect/prometheus/expand-with-exprs.qtpl:75 + } +//line app/vmselect/prometheus/expand-with-exprs.qtpl:75 + qw422016.N().S(`}`) +//line app/vmselect/prometheus/expand-with-exprs.qtpl:77 +} + +//line app/vmselect/prometheus/expand-with-exprs.qtpl:77 +func WriteExpandWithExprsJSONResponse(qq422016 qtio422016.Writer, q string) { +//line app/vmselect/prometheus/expand-with-exprs.qtpl:77 + qw422016 := qt422016.AcquireWriter(qq422016) +//line app/vmselect/prometheus/expand-with-exprs.qtpl:77 + StreamExpandWithExprsJSONResponse(qw422016, q) +//line app/vmselect/prometheus/expand-with-exprs.qtpl:77 + qt422016.ReleaseWriter(qw422016) +//line app/vmselect/prometheus/expand-with-exprs.qtpl:77 +} + +//line app/vmselect/prometheus/expand-with-exprs.qtpl:77 +func ExpandWithExprsJSONResponse(q string) string { +//line app/vmselect/prometheus/expand-with-exprs.qtpl:77 + qb422016 := qt422016.AcquireByteBuffer() +//line app/vmselect/prometheus/expand-with-exprs.qtpl:77 + WriteExpandWithExprsJSONResponse(qb422016, q) +//line app/vmselect/prometheus/expand-with-exprs.qtpl:77 + qs422016 := string(qb422016.B) +//line app/vmselect/prometheus/expand-with-exprs.qtpl:77 + qt422016.ReleaseByteBuffer(qb422016) +//line app/vmselect/prometheus/expand-with-exprs.qtpl:77 + return qs422016 +//line app/vmselect/prometheus/expand-with-exprs.qtpl:77 +} + +//line app/vmselect/prometheus/expand-with-exprs.qtpl:81 func streamwithExprsTutorial(qw422016 *qt422016.Writer) { -//line app/vmselect/prometheus/expand-with-exprs.qtpl:59 +//line app/vmselect/prometheus/expand-with-exprs.qtpl:81 qw422016.N().S(` <h3>Tutorial for WITH expressions in <a href="https://docs.victoriametrics.com/MetricsQL.html">MetricsQL</a></h3> @@ -316,127 +379,31 @@ WITH ( </pre> `) -//line app/vmselect/prometheus/expand-with-exprs.qtpl:246 +//line app/vmselect/prometheus/expand-with-exprs.qtpl:268 } -//line app/vmselect/prometheus/expand-with-exprs.qtpl:246 +//line app/vmselect/prometheus/expand-with-exprs.qtpl:268 func writewithExprsTutorial(qq422016 qtio422016.Writer) { -//line app/vmselect/prometheus/expand-with-exprs.qtpl:246 +//line app/vmselect/prometheus/expand-with-exprs.qtpl:268 qw422016 := qt422016.AcquireWriter(qq422016) -//line app/vmselect/prometheus/expand-with-exprs.qtpl:246 +//line app/vmselect/prometheus/expand-with-exprs.qtpl:268 streamwithExprsTutorial(qw422016) -//line app/vmselect/prometheus/expand-with-exprs.qtpl:246 +//line app/vmselect/prometheus/expand-with-exprs.qtpl:268 qt422016.ReleaseWriter(qw422016) -//line app/vmselect/prometheus/expand-with-exprs.qtpl:246 +//line app/vmselect/prometheus/expand-with-exprs.qtpl:268 } -//line app/vmselect/prometheus/expand-with-exprs.qtpl:246 +//line app/vmselect/prometheus/expand-with-exprs.qtpl:268 func withExprsTutorial() string { -//line app/vmselect/prometheus/expand-with-exprs.qtpl:246 +//line app/vmselect/prometheus/expand-with-exprs.qtpl:268 qb422016 := qt422016.AcquireByteBuffer() -//line app/vmselect/prometheus/expand-with-exprs.qtpl:246 +//line app/vmselect/prometheus/expand-with-exprs.qtpl:268 writewithExprsTutorial(qb422016) -//line app/vmselect/prometheus/expand-with-exprs.qtpl:246 - qs422016 := string(qb422016.B) -//line app/vmselect/prometheus/expand-with-exprs.qtpl:246 - qt422016.ReleaseByteBuffer(qb422016) -//line app/vmselect/prometheus/expand-with-exprs.qtpl:246 - return qs422016 -//line app/vmselect/prometheus/expand-with-exprs.qtpl:246 -} - -//line app/vmselect/prometheus/expand-with-exprs.qtpl:249 -func StreamExpandWithExprsJSONResponse(qw422016 *qt422016.Writer, q string) { -//line app/vmselect/prometheus/expand-with-exprs.qtpl:250 - streamexpandWithExprsJSON(qw422016, q) -//line app/vmselect/prometheus/expand-with-exprs.qtpl:251 -} - -//line app/vmselect/prometheus/expand-with-exprs.qtpl:251 -func WriteExpandWithExprsJSONResponse(qq422016 qtio422016.Writer, q string) { -//line app/vmselect/prometheus/expand-with-exprs.qtpl:251 - qw422016 := qt422016.AcquireWriter(qq422016) -//line app/vmselect/prometheus/expand-with-exprs.qtpl:251 - StreamExpandWithExprsJSONResponse(qw422016, q) -//line app/vmselect/prometheus/expand-with-exprs.qtpl:251 - qt422016.ReleaseWriter(qw422016) -//line app/vmselect/prometheus/expand-with-exprs.qtpl:251 -} - -//line app/vmselect/prometheus/expand-with-exprs.qtpl:251 -func ExpandWithExprsJSONResponse(q string) string { -//line app/vmselect/prometheus/expand-with-exprs.qtpl:251 - qb422016 := qt422016.AcquireByteBuffer() -//line app/vmselect/prometheus/expand-with-exprs.qtpl:251 - WriteExpandWithExprsJSONResponse(qb422016, q) -//line app/vmselect/prometheus/expand-with-exprs.qtpl:251 - qs422016 := string(qb422016.B) -//line app/vmselect/prometheus/expand-with-exprs.qtpl:251 - qt422016.ReleaseByteBuffer(qb422016) -//line app/vmselect/prometheus/expand-with-exprs.qtpl:251 - return qs422016 -//line app/vmselect/prometheus/expand-with-exprs.qtpl:251 -} - -//line app/vmselect/prometheus/expand-with-exprs.qtpl:253 -func streamexpandWithExprsJSON(qw422016 *qt422016.Writer, q string) { -//line app/vmselect/prometheus/expand-with-exprs.qtpl:254 - if len(q) == 0 { -//line app/vmselect/prometheus/expand-with-exprs.qtpl:254 - qw422016.N().S(`{"status": "error","error": "query string cannot be empty"}`) -//line app/vmselect/prometheus/expand-with-exprs.qtpl:259 - return -//line app/vmselect/prometheus/expand-with-exprs.qtpl:260 - } -//line app/vmselect/prometheus/expand-with-exprs.qtpl:260 - qw422016.N().S(`{`) -//line app/vmselect/prometheus/expand-with-exprs.qtpl:263 - expr, err := metricsql.Parse(q) - -//line app/vmselect/prometheus/expand-with-exprs.qtpl:264 - if err != nil { -//line app/vmselect/prometheus/expand-with-exprs.qtpl:264 - qw422016.N().S(`"status": "error","error":`) -//line app/vmselect/prometheus/expand-with-exprs.qtpl:266 - qw422016.N().Q(fmt.Sprintf("Cannot parse query: %s", err)) -//line app/vmselect/prometheus/expand-with-exprs.qtpl:267 - } else { //line app/vmselect/prometheus/expand-with-exprs.qtpl:268 - expr = metricsql.Optimize(expr) - -//line app/vmselect/prometheus/expand-with-exprs.qtpl:268 - qw422016.N().S(`"status": "success","expr":`) -//line app/vmselect/prometheus/expand-with-exprs.qtpl:270 - qw422016.N().Q(string(expr.AppendString(nil))) -//line app/vmselect/prometheus/expand-with-exprs.qtpl:271 - } -//line app/vmselect/prometheus/expand-with-exprs.qtpl:271 - qw422016.N().S(`}`) -//line app/vmselect/prometheus/expand-with-exprs.qtpl:273 -} - -//line app/vmselect/prometheus/expand-with-exprs.qtpl:273 -func writeexpandWithExprsJSON(qq422016 qtio422016.Writer, q string) { -//line app/vmselect/prometheus/expand-with-exprs.qtpl:273 - qw422016 := qt422016.AcquireWriter(qq422016) -//line app/vmselect/prometheus/expand-with-exprs.qtpl:273 - streamexpandWithExprsJSON(qw422016, q) -//line app/vmselect/prometheus/expand-with-exprs.qtpl:273 - qt422016.ReleaseWriter(qw422016) -//line app/vmselect/prometheus/expand-with-exprs.qtpl:273 -} - -//line app/vmselect/prometheus/expand-with-exprs.qtpl:273 -func expandWithExprsJSON(q string) string { -//line app/vmselect/prometheus/expand-with-exprs.qtpl:273 - qb422016 := qt422016.AcquireByteBuffer() -//line app/vmselect/prometheus/expand-with-exprs.qtpl:273 - writeexpandWithExprsJSON(qb422016, q) -//line app/vmselect/prometheus/expand-with-exprs.qtpl:273 qs422016 := string(qb422016.B) -//line app/vmselect/prometheus/expand-with-exprs.qtpl:273 +//line app/vmselect/prometheus/expand-with-exprs.qtpl:268 qt422016.ReleaseByteBuffer(qb422016) -//line app/vmselect/prometheus/expand-with-exprs.qtpl:273 +//line app/vmselect/prometheus/expand-with-exprs.qtpl:268 return qs422016 -//line app/vmselect/prometheus/expand-with-exprs.qtpl:273 +//line app/vmselect/prometheus/expand-with-exprs.qtpl:268 } diff --git a/app/vmselect/prometheus/prometheus.go b/app/vmselect/prometheus/prometheus.go index d74bbb9b64..a6a3f949e3 100644 --- a/app/vmselect/prometheus/prometheus.go +++ b/app/vmselect/prometheus/prometheus.go @@ -60,13 +60,13 @@ const defaultStep = 5 * 60 * 1000 // ExpandWithExprs handles the request to /expand-with-exprs func ExpandWithExprs(w http.ResponseWriter, r *http.Request) { - query := r.FormValue("query") format := r.FormValue("format") bw := bufferedwriter.Get(w) defer bufferedwriter.Put(bw) if format == "json" { w.Header().Set("Content-Type", "application/json") + httpserver.EnableCORS(w, r) WriteExpandWithExprsJSONResponse(bw, query) } else { WriteExpandWithExprsResponse(bw, query) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 7dfbca9efb..e7bbf804de 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -33,7 +33,7 @@ The following tip changes can be tested by building VictoriaMetrics components f * FEATURE: [vmagent](https://docs.victoriametrics.com/vmagent.html): support new filtering options `filter` and `node_filter` for [consul service discovery](https://docs.victoriametrics.com/sd_configs.html#consul_sd_configs). See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/4183) for details. * FEATURE: [vmagent](https://docs.victoriametrics.com/vmagent.html): support new [consulagent service discovery](https://docs.victoriametrics.com/sd_configs.html#consulagent_sd_configs). See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3953) for details. * FEATURE: [vmctl](https://docs.victoriametrics.com/vmctl.html): add support for [different time formats](https://docs.victoriametrics.com/Single-server-VictoriaMetrics.html#timestamp-formats) for `--vm-native-filter-time-start` and `--vm-native-filter-time-end` command-line flags. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/4091). -* FEATURE: [vmui](https://docs.victoriametrics.com/#vmui): integrate WITH template playground. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3811). +* FEATURE: [vmui](https://docs.victoriametrics.com/#vmui): add `WITH template` playground to `vmui`. See [this feature request](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3811). * FEATURE: [vmui](https://docs.victoriametrics.com/#vmui): add a comparison of data from the previous day with data from the current day to the `Cardinality Explorer`. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3967). * FEATURE: [vmui](https://docs.victoriametrics.com/#vmui): display histogram metrics as a heatmap in the `explore metrics` tab. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/4111). * FEATURE: [vmalert](https://docs.victoriametrics.com/vmalert.html): add support of recursive globs for `-rule` and `-rule.templates` by using `**` in the glob pattern. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/4041).