Browse Source

Merge pull request #258 from grafana/update-prometheus

Update prometheus
owilliams/utf8-02-mimir
Peter Štibraný 2 years ago committed by GitHub
parent
commit
f2aba4af80
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      CHANGELOG.md
  2. 2
      Makefile
  3. 75
      Makefile.common
  4. 17
      README.md
  5. 2
      VERSION
  6. 4
      discovery/http/http.go
  7. 8
      discovery/http/http_test.go
  8. 34
      discovery/manager.go
  9. 4
      go.mod
  10. 9
      go.sum
  11. 17
      model/relabel/relabel.go
  12. 2
      model/relabel/relabel_test.go
  13. 2
      tsdb/head_wal.go
  14. 7
      web/api/v1/api.go
  15. 12
      web/api/v1/api_test.go
  16. 236
      web/api/v1/errors_test.go
  17. 16
      web/ui/build_ui.sh
  18. 4
      web/ui/module/codemirror-promql/jest.config.cjs
  19. 33
      web/ui/module/codemirror-promql/package.json
  20. 94
      web/ui/module/codemirror-promql/src/complete/hybrid.test.ts
  21. 4
      web/ui/module/codemirror-promql/src/complete/hybrid.ts
  22. 2
      web/ui/module/codemirror-promql/src/parser/matcher.test.ts
  23. 4
      web/ui/module/codemirror-promql/src/parser/matcher.ts
  24. 2
      web/ui/module/codemirror-promql/src/parser/parser.ts
  25. 2
      web/ui/module/codemirror-promql/src/parser/path-finder.test.ts
  26. 8
      web/ui/module/codemirror-promql/src/parser/path-finder.ts
  27. 2
      web/ui/module/codemirror-promql/src/parser/type.ts
  28. 2
      web/ui/module/codemirror-promql/src/parser/vector.test.ts
  29. 2
      web/ui/module/codemirror-promql/src/parser/vector.ts
  30. 23
      web/ui/module/codemirror-promql/src/promql.ts
  31. 2
      web/ui/module/codemirror-promql/src/test/utils-test.ts
  32. 2
      web/ui/module/codemirror-promql/src/types/function.ts
  33. 2
      web/ui/module/codemirror-promql/src/types/matcher.ts
  34. 10
      web/ui/module/lezer-promql/package.json
  35. 33
      web/ui/module/lezer-promql/src/highlight.js
  36. 2
      web/ui/module/lezer-promql/src/promql.grammar
  37. 9502
      web/ui/package-lock.json
  38. 2
      web/ui/package.json
  39. 32
      web/ui/react-app/package.json
  40. 3
      web/ui/react-app/src/pages/graph/CMTheme.tsx
  41. 36
      web/ui/react-app/src/pages/graph/ExpressionInput.tsx

4
CHANGELOG.md

@ -1,5 +1,9 @@
# Changelog # Changelog
## 2.36.1 / 2022-06-09
* [BUGFIX] promtool: Add --lint-fatal option #10840
## 2.36.0 / 2022-05-30 ## 2.36.0 / 2022-05-30
* [FEATURE] Add lowercase and uppercase relabel action. #10641 * [FEATURE] Add lowercase and uppercase relabel action. #10641

2
Makefile

@ -45,7 +45,7 @@ ui-install:
.PHONY: ui-build .PHONY: ui-build
ui-build: ui-build:
cd $(UI_PATH) && npm run build cd $(UI_PATH) && CI="" npm run build
.PHONY: ui-build-module .PHONY: ui-build-module
ui-build-module: ui-build-module:

75
Makefile.common

@ -36,29 +36,6 @@ GO_VERSION ?= $(shell $(GO) version)
GO_VERSION_NUMBER ?= $(word 3, $(GO_VERSION)) GO_VERSION_NUMBER ?= $(word 3, $(GO_VERSION))
PRE_GO_111 ?= $(shell echo $(GO_VERSION_NUMBER) | grep -E 'go1\.(10|[0-9])\.') PRE_GO_111 ?= $(shell echo $(GO_VERSION_NUMBER) | grep -E 'go1\.(10|[0-9])\.')
GOVENDOR :=
GO111MODULE :=
ifeq (, $(PRE_GO_111))
ifneq (,$(wildcard go.mod))
# Enforce Go modules support just in case the directory is inside GOPATH (and for Travis CI).
GO111MODULE := on
ifneq (,$(wildcard vendor))
# Always use the local vendor/ directory to satisfy the dependencies.
GOOPTS := $(GOOPTS) -mod=vendor
endif
endif
else
ifneq (,$(wildcard go.mod))
ifneq (,$(wildcard vendor))
$(warning This repository requires Go >= 1.11 because of Go modules)
$(warning Some recipes may not work as expected as the current Go runtime is '$(GO_VERSION_NUMBER)')
endif
else
# This repository isn't using Go modules (yet).
GOVENDOR := $(FIRST_GOPATH)/bin/govendor
endif
endif
PROMU := $(FIRST_GOPATH)/bin/promu PROMU := $(FIRST_GOPATH)/bin/promu
pkgs = ./... pkgs = ./...
@ -152,11 +129,7 @@ common-check_license:
.PHONY: common-deps .PHONY: common-deps
common-deps: common-deps:
@echo ">> getting dependencies" @echo ">> getting dependencies"
ifdef GO111MODULE $(GO) mod download
GO111MODULE=$(GO111MODULE) $(GO) mod download
else
$(GO) get $(GOOPTS) -t ./...
endif
.PHONY: update-go-deps .PHONY: update-go-deps
update-go-deps: update-go-deps:
@ -164,20 +137,17 @@ update-go-deps:
@for m in $$($(GO) list -mod=readonly -m -f '{{ if and (not .Indirect) (not .Main)}}{{.Path}}{{end}}' all); do \ @for m in $$($(GO) list -mod=readonly -m -f '{{ if and (not .Indirect) (not .Main)}}{{.Path}}{{end}}' all); do \
$(GO) get -d $$m; \ $(GO) get -d $$m; \
done done
GO111MODULE=$(GO111MODULE) $(GO) mod tidy $(GO) mod tidy
ifneq (,$(wildcard vendor))
GO111MODULE=$(GO111MODULE) $(GO) mod vendor
endif
.PHONY: common-test-short .PHONY: common-test-short
common-test-short: $(GOTEST_DIR) common-test-short: $(GOTEST_DIR)
@echo ">> running short tests" @echo ">> running short tests"
GO111MODULE=$(GO111MODULE) $(GOTEST) -short $(GOOPTS) $(pkgs) $(GOTEST) -short $(GOOPTS) $(pkgs)
.PHONY: common-test .PHONY: common-test
common-test: $(GOTEST_DIR) common-test: $(GOTEST_DIR)
@echo ">> running all tests" @echo ">> running all tests"
GO111MODULE=$(GO111MODULE) $(GOTEST) $(test-flags) $(GOOPTS) $(pkgs) $(GOTEST) $(test-flags) $(GOOPTS) $(pkgs)
$(GOTEST_DIR): $(GOTEST_DIR):
@mkdir -p $@ @mkdir -p $@
@ -185,25 +155,21 @@ $(GOTEST_DIR):
.PHONY: common-format .PHONY: common-format
common-format: common-format:
@echo ">> formatting code" @echo ">> formatting code"
GO111MODULE=$(GO111MODULE) $(GO) fmt $(pkgs) $(GO) fmt $(pkgs)
.PHONY: common-vet .PHONY: common-vet
common-vet: common-vet:
@echo ">> vetting code" @echo ">> vetting code"
GO111MODULE=$(GO111MODULE) $(GO) vet $(GOOPTS) $(pkgs) $(GO) vet $(GOOPTS) $(pkgs)
.PHONY: common-lint .PHONY: common-lint
common-lint: $(GOLANGCI_LINT) common-lint: $(GOLANGCI_LINT)
ifdef GOLANGCI_LINT ifdef GOLANGCI_LINT
@echo ">> running golangci-lint" @echo ">> running golangci-lint"
ifdef GO111MODULE
# 'go list' needs to be executed before staticcheck to prepopulate the modules cache. # 'go list' needs to be executed before staticcheck to prepopulate the modules cache.
# Otherwise staticcheck might fail randomly for some reason not yet explained. # Otherwise staticcheck might fail randomly for some reason not yet explained.
GO111MODULE=$(GO111MODULE) $(GO) list -e -compiled -test=true -export=false -deps=true -find=false -tags= -- ./... > /dev/null $(GO) list -e -compiled -test=true -export=false -deps=true -find=false -tags= -- ./... > /dev/null
GO111MODULE=$(GO111MODULE) $(GOLANGCI_LINT) run $(GOLANGCI_LINT_OPTS) $(pkgs) $(GOLANGCI_LINT) run $(GOLANGCI_LINT_OPTS) $(pkgs)
else
$(GOLANGCI_LINT) run $(pkgs)
endif
endif endif
.PHONY: common-yamllint .PHONY: common-yamllint
@ -220,28 +186,15 @@ endif
common-staticcheck: lint common-staticcheck: lint
.PHONY: common-unused .PHONY: common-unused
common-unused: $(GOVENDOR) common-unused:
ifdef GOVENDOR
@echo ">> running check for unused packages"
@$(GOVENDOR) list +unused | grep . && exit 1 || echo 'No unused packages'
else
ifdef GO111MODULE
@echo ">> running check for unused/missing packages in go.mod" @echo ">> running check for unused/missing packages in go.mod"
GO111MODULE=$(GO111MODULE) $(GO) mod tidy $(GO) mod tidy
ifeq (,$(wildcard vendor))
@git diff --exit-code -- go.sum go.mod @git diff --exit-code -- go.sum go.mod
else
@echo ">> running check for unused packages in vendor/"
GO111MODULE=$(GO111MODULE) $(GO) mod vendor
@git diff --exit-code -- go.sum go.mod vendor/
endif
endif
endif
.PHONY: common-build .PHONY: common-build
common-build: promu common-build: promu
@echo ">> building binaries" @echo ">> building binaries"
GO111MODULE=$(GO111MODULE) $(PROMU) build --prefix $(PREFIX) $(PROMU_BINARIES) $(PROMU) build --prefix $(PREFIX) $(PROMU_BINARIES)
.PHONY: common-tarball .PHONY: common-tarball
common-tarball: promu common-tarball: promu
@ -297,12 +250,6 @@ $(GOLANGCI_LINT):
| sh -s -- -b $(FIRST_GOPATH)/bin $(GOLANGCI_LINT_VERSION) | sh -s -- -b $(FIRST_GOPATH)/bin $(GOLANGCI_LINT_VERSION)
endif endif
ifdef GOVENDOR
.PHONY: $(GOVENDOR)
$(GOVENDOR):
GOOS= GOARCH= $(GO) get -u github.com/kardianos/govendor
endif
.PHONY: precheck .PHONY: precheck
precheck:: precheck::

17
README.md

@ -63,7 +63,14 @@ To build Prometheus from source code, You need:
* NodeJS [version 16 or greater](https://nodejs.org/). * NodeJS [version 16 or greater](https://nodejs.org/).
* npm [version 7 or greater](https://www.npmjs.com/). * npm [version 7 or greater](https://www.npmjs.com/).
You can directly use the `go` tool to download and install the `prometheus` Start by cloning the repository:
```bash
git clone https://github.com/prometheus/prometheus.git
cd prometheus
```
You can use the `go` tool to build and install the `prometheus`
and `promtool` binaries into your `GOPATH`: and `promtool` binaries into your `GOPATH`:
```bash ```bash
@ -79,14 +86,10 @@ React UI unless it has been built explicitly using `make assets` or `make build`
An example of the above configuration file can be found [here.](https://github.com/prometheus/prometheus/blob/main/documentation/examples/prometheus.yml) An example of the above configuration file can be found [here.](https://github.com/prometheus/prometheus/blob/main/documentation/examples/prometheus.yml)
You can also clone the repository yourself and build using `make build`, which will compile in You can also build using `make build`, which will compile in the web assets so that
the web assets so that Prometheus can be run from anywhere: Prometheus can be run from anywhere:
```bash ```bash
mkdir -p $GOPATH/src/github.com/prometheus
cd $GOPATH/src/github.com/prometheus
git clone https://github.com/prometheus/prometheus.git
cd prometheus
make build make build
./prometheus --config.file=your_config.yml ./prometheus --config.file=your_config.yml
``` ```

2
VERSION

@ -1 +1 @@
2.36.0 2.36.1

4
discovery/http/http.go

@ -136,12 +136,12 @@ func NewDiscovery(conf *SDConfig, logger log.Logger, clientOpts []config.HTTPCli
logger, logger,
"http", "http",
time.Duration(conf.RefreshInterval), time.Duration(conf.RefreshInterval),
d.refresh, d.Refresh,
) )
return d, nil return d, nil
} }
func (d *Discovery) refresh(ctx context.Context) ([]*targetgroup.Group, error) { func (d *Discovery) Refresh(ctx context.Context) ([]*targetgroup.Group, error) {
req, err := http.NewRequest("GET", d.url, nil) req, err := http.NewRequest("GET", d.url, nil)
if err != nil { if err != nil {
return nil, err return nil, err

8
discovery/http/http_test.go

@ -45,7 +45,7 @@ func TestHTTPValidRefresh(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
ctx := context.Background() ctx := context.Background()
tgs, err := d.refresh(ctx) tgs, err := d.Refresh(ctx)
require.NoError(t, err) require.NoError(t, err)
expectedTargets := []*targetgroup.Group{ expectedTargets := []*targetgroup.Group{
@ -83,7 +83,7 @@ func TestHTTPInvalidCode(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
ctx := context.Background() ctx := context.Background()
_, err = d.refresh(ctx) _, err = d.Refresh(ctx)
require.EqualError(t, err, "server returned HTTP status 400 Bad Request") require.EqualError(t, err, "server returned HTTP status 400 Bad Request")
require.Equal(t, 1.0, getFailureCount()) require.Equal(t, 1.0, getFailureCount())
} }
@ -105,7 +105,7 @@ func TestHTTPInvalidFormat(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
ctx := context.Background() ctx := context.Background()
_, err = d.refresh(ctx) _, err = d.Refresh(ctx)
require.EqualError(t, err, `unsupported content type "text/plain; charset=utf-8"`) require.EqualError(t, err, `unsupported content type "text/plain; charset=utf-8"`)
require.Equal(t, 1.0, getFailureCount()) require.Equal(t, 1.0, getFailureCount())
} }
@ -423,7 +423,7 @@ func TestSourceDisappeared(t *testing.T) {
ctx := context.Background() ctx := context.Background()
for i, res := range test.responses { for i, res := range test.responses {
stubResponse = res stubResponse = res
tgs, err := d.refresh(ctx) tgs, err := d.Refresh(ctx)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, test.expectedTargets[i], tgs) require.Equal(t, test.expectedTargets[i], tgs)
} }

34
discovery/manager.go

@ -75,8 +75,8 @@ type poolKey struct {
provider string provider string
} }
// provider holds a Discoverer instance, its configuration, cancel func and its subscribers. // Provider holds a Discoverer instance, its configuration, cancel func and its subscribers.
type provider struct { type Provider struct {
name string name string
d Discoverer d Discoverer
config interface{} config interface{}
@ -92,11 +92,20 @@ type provider struct {
newSubs map[string]struct{} newSubs map[string]struct{}
} }
// Discoverer return the Discoverer of the provider
func (p *Provider) Discoverer() Discoverer {
return p.d
}
// IsStarted return true if Discoverer is started. // IsStarted return true if Discoverer is started.
func (p *provider) IsStarted() bool { func (p *Provider) IsStarted() bool {
return p.cancel != nil return p.cancel != nil
} }
func (p *Provider) Config() interface{} {
return p.config
}
// NewManager is the Discovery Manager constructor. // NewManager is the Discovery Manager constructor.
func NewManager(ctx context.Context, logger log.Logger, options ...func(*Manager)) *Manager { func NewManager(ctx context.Context, logger log.Logger, options ...func(*Manager)) *Manager {
if logger == nil { if logger == nil {
@ -148,7 +157,7 @@ type Manager struct {
targetsMtx sync.Mutex targetsMtx sync.Mutex
// providers keeps track of SD providers. // providers keeps track of SD providers.
providers []*provider providers []*Provider
// The sync channel sends the updates as a map where the key is the job value from the scrape config. // The sync channel sends the updates as a map where the key is the job value from the scrape config.
syncCh chan map[string][]*targetgroup.Group syncCh chan map[string][]*targetgroup.Group
@ -163,6 +172,11 @@ type Manager struct {
lastProvider uint lastProvider uint
} }
// Providers returns the currently configured SD providers.
func (m *Manager) Providers() []*Provider {
return m.providers
}
// Run starts the background processing. // Run starts the background processing.
func (m *Manager) Run() error { func (m *Manager) Run() error {
go m.sender() go m.sender()
@ -194,7 +208,7 @@ func (m *Manager) ApplyConfig(cfg map[string]Configs) error {
wg sync.WaitGroup wg sync.WaitGroup
// keep shows if we keep any providers after reload. // keep shows if we keep any providers after reload.
keep bool keep bool
newProviders []*provider newProviders []*Provider
) )
for _, prov := range m.providers { for _, prov := range m.providers {
// Cancel obsolete providers. // Cancel obsolete providers.
@ -260,7 +274,7 @@ func (m *Manager) ApplyConfig(cfg map[string]Configs) error {
// StartCustomProvider is used for sdtool. Only use this if you know what you're doing. // StartCustomProvider is used for sdtool. Only use this if you know what you're doing.
func (m *Manager) StartCustomProvider(ctx context.Context, name string, worker Discoverer) { func (m *Manager) StartCustomProvider(ctx context.Context, name string, worker Discoverer) {
p := &provider{ p := &Provider{
name: name, name: name,
d: worker, d: worker,
subs: map[string]struct{}{ subs: map[string]struct{}{
@ -271,7 +285,7 @@ func (m *Manager) StartCustomProvider(ctx context.Context, name string, worker D
m.startProvider(ctx, p) m.startProvider(ctx, p)
} }
func (m *Manager) startProvider(ctx context.Context, p *provider) { func (m *Manager) startProvider(ctx context.Context, p *Provider) {
level.Debug(m.logger).Log("msg", "Starting provider", "provider", p.name, "subs", fmt.Sprintf("%v", p.subs)) level.Debug(m.logger).Log("msg", "Starting provider", "provider", p.name, "subs", fmt.Sprintf("%v", p.subs))
ctx, cancel := context.WithCancel(ctx) ctx, cancel := context.WithCancel(ctx)
updates := make(chan []*targetgroup.Group) updates := make(chan []*targetgroup.Group)
@ -283,7 +297,7 @@ func (m *Manager) startProvider(ctx context.Context, p *provider) {
} }
// cleaner cleans resources associated with provider. // cleaner cleans resources associated with provider.
func (m *Manager) cleaner(p *provider) { func (m *Manager) cleaner(p *Provider) {
m.targetsMtx.Lock() m.targetsMtx.Lock()
p.mu.RLock() p.mu.RLock()
for s := range p.subs { for s := range p.subs {
@ -296,7 +310,7 @@ func (m *Manager) cleaner(p *provider) {
} }
} }
func (m *Manager) updater(ctx context.Context, p *provider, updates chan []*targetgroup.Group) { func (m *Manager) updater(ctx context.Context, p *Provider, updates chan []*targetgroup.Group) {
// Ensure targets from this provider are cleaned up. // Ensure targets from this provider are cleaned up.
defer m.cleaner(p) defer m.cleaner(p)
for { for {
@ -422,7 +436,7 @@ func (m *Manager) registerProviders(cfgs Configs, setName string) int {
failed++ failed++
return return
} }
m.providers = append(m.providers, &provider{ m.providers = append(m.providers, &Provider{
name: fmt.Sprintf("%s/%d", typ, m.lastProvider), name: fmt.Sprintf("%s/%d", typ, m.lastProvider),
d: d, d: d,
config: cfg, config: cfg,

4
go.mod

@ -47,7 +47,7 @@ require (
github.com/prometheus/exporter-toolkit v0.7.1 github.com/prometheus/exporter-toolkit v0.7.1
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.9 github.com/scaleway/scaleway-sdk-go v1.0.0-beta.9
github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749
github.com/stretchr/testify v1.7.1 github.com/stretchr/testify v1.7.2
github.com/vultr/govultr/v2 v2.17.1 github.com/vultr/govultr/v2 v2.17.1
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.32.0 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.32.0
go.opentelemetry.io/otel v1.7.0 go.opentelemetry.io/otel v1.7.0
@ -74,7 +74,7 @@ require (
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
k8s.io/api v0.24.1 k8s.io/api v0.24.1
k8s.io/apimachinery v0.24.1 k8s.io/apimachinery v0.24.1
k8s.io/client-go v0.24.0 k8s.io/client-go v0.24.1
k8s.io/klog v1.0.0 k8s.io/klog v1.0.0
k8s.io/klog/v2 v2.60.1 k8s.io/klog/v2 v2.60.1
) )

9
go.sum

@ -817,8 +817,9 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s=
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
@ -1457,14 +1458,12 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
k8s.io/api v0.24.0/go.mod h1:5Jl90IUrJHUJYEMANRURMiVvJ0g7Ax7r3R1bqO8zx8I=
k8s.io/api v0.24.1 h1:BjCMRDcyEYz03joa3K1+rbshwh1Ay6oB53+iUx2H8UY= k8s.io/api v0.24.1 h1:BjCMRDcyEYz03joa3K1+rbshwh1Ay6oB53+iUx2H8UY=
k8s.io/api v0.24.1/go.mod h1:JhoOvNiLXKTPQ60zh2g0ewpA+bnEYf5q44Flhquh4vQ= k8s.io/api v0.24.1/go.mod h1:JhoOvNiLXKTPQ60zh2g0ewpA+bnEYf5q44Flhquh4vQ=
k8s.io/apimachinery v0.24.0/go.mod h1:82Bi4sCzVBdpYjyI4jY6aHX+YCUchUIrZrXKedjd2UM=
k8s.io/apimachinery v0.24.1 h1:ShD4aDxTQKN5zNf8K1RQ2u98ELLdIW7jEnlO9uAMX/I= k8s.io/apimachinery v0.24.1 h1:ShD4aDxTQKN5zNf8K1RQ2u98ELLdIW7jEnlO9uAMX/I=
k8s.io/apimachinery v0.24.1/go.mod h1:82Bi4sCzVBdpYjyI4jY6aHX+YCUchUIrZrXKedjd2UM= k8s.io/apimachinery v0.24.1/go.mod h1:82Bi4sCzVBdpYjyI4jY6aHX+YCUchUIrZrXKedjd2UM=
k8s.io/client-go v0.24.0 h1:lbE4aB1gTHvYFSwm6eD3OF14NhFDKCejlnsGYlSJe5U= k8s.io/client-go v0.24.1 h1:w1hNdI9PFrzu3OlovVeTnf4oHDt+FJLd9Ndluvnb42E=
k8s.io/client-go v0.24.0/go.mod h1:VFPQET+cAFpYxh6Bq6f4xyMY80G6jKKktU6G0m00VDw= k8s.io/client-go v0.24.1/go.mod h1:f1kIDqcEYmwXS/vTbbhopMUbhKp2JhOeVTfxgaCIlF8=
k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42 h1:Gii5eqf+GmIEwGNKQYQClCayuJCe2/4fZUvF7VG99sU= k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42 h1:Gii5eqf+GmIEwGNKQYQClCayuJCe2/4fZUvF7VG99sU=
k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42/go.mod h1:Z/45zLw8lUo4wdiUkI+v/ImEGAvu3WatcZl3lPMR4Rk= k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42/go.mod h1:Z/45zLw8lUo4wdiUkI+v/ImEGAvu3WatcZl3lPMR4Rk=

17
model/relabel/relabel.go

@ -142,17 +142,13 @@ func (c *Config) UnmarshalYAML(unmarshal func(interface{}) error) error {
// Regexp encapsulates a regexp.Regexp and makes it YAML marshalable. // Regexp encapsulates a regexp.Regexp and makes it YAML marshalable.
type Regexp struct { type Regexp struct {
*regexp.Regexp *regexp.Regexp
original string
} }
// NewRegexp creates a new anchored Regexp and returns an error if the // NewRegexp creates a new anchored Regexp and returns an error if the
// passed-in regular expression does not compile. // passed-in regular expression does not compile.
func NewRegexp(s string) (Regexp, error) { func NewRegexp(s string) (Regexp, error) {
regex, err := regexp.Compile("^(?:" + s + ")$") regex, err := regexp.Compile("^(?:" + s + ")$")
return Regexp{ return Regexp{Regexp: regex}, err
Regexp: regex,
original: s,
}, err
} }
// MustNewRegexp works like NewRegexp, but panics if the regular expression does not compile. // MustNewRegexp works like NewRegexp, but panics if the regular expression does not compile.
@ -180,12 +176,19 @@ func (re *Regexp) UnmarshalYAML(unmarshal func(interface{}) error) error {
// MarshalYAML implements the yaml.Marshaler interface. // MarshalYAML implements the yaml.Marshaler interface.
func (re Regexp) MarshalYAML() (interface{}, error) { func (re Regexp) MarshalYAML() (interface{}, error) {
if re.original != "" { if re.String() != "" {
return re.original, nil return re.String(), nil
} }
return nil, nil return nil, nil
} }
// String returns the original string used to compile the regular expression.
func (re Regexp) String() string {
str := re.Regexp.String()
// Trim the anchor `^(?:` prefix and `)$` suffix.
return str[4 : len(str)-2]
}
// Process returns a relabeled copy of the given label set. The relabel configurations // Process returns a relabeled copy of the given label set. The relabel configurations
// are applied in order of input. // are applied in order of input.
// If a label set is dropped, nil is returned. // If a label set is dropped, nil is returned.

2
model/relabel/relabel_test.go

@ -461,7 +461,7 @@ func TestRelabel(t *testing.T) {
if cfg.Separator == "" { if cfg.Separator == "" {
cfg.Separator = DefaultRelabelConfig.Separator cfg.Separator = DefaultRelabelConfig.Separator
} }
if cfg.Regex.original == "" { if cfg.Regex.Regexp == nil || cfg.Regex.String() == "" {
cfg.Regex = DefaultRelabelConfig.Regex cfg.Regex = DefaultRelabelConfig.Regex
} }
if cfg.Replacement == "" { if cfg.Replacement == "" {

2
tsdb/head_wal.go

@ -438,7 +438,7 @@ func (wp *walSubsetProcessor) waitUntilIdle() {
} }
wp.input <- []record.RefSample{} wp.input <- []record.RefSample{}
for len(wp.input) != 0 { for len(wp.input) != 0 {
time.Sleep(1 * time.Millisecond) time.Sleep(10 * time.Microsecond)
select { select {
case <-wp.output: // Allow output side to drain to avoid deadlock. case <-wp.output: // Allow output side to drain to avoid deadlock.
default: default:

7
web/api/v1/api.go

@ -553,7 +553,12 @@ func returnAPIError(err error) *apiError {
return nil return nil
} }
switch errors.Cause(err).(type) { cause := errors.Unwrap(err)
if cause == nil {
cause = err
}
switch cause.(type) {
case promql.ErrQueryCanceled: case promql.ErrQueryCanceled:
return &apiError{errorCanceled, err} return &apiError{errorCanceled, err}
case promql.ErrQueryTimeout: case promql.ErrQueryTimeout:

12
web/api/v1/api_test.go

@ -2948,19 +2948,19 @@ func TestReturnAPIError(t *testing.T) {
err: promql.ErrStorage{Err: errors.New("storage error")}, err: promql.ErrStorage{Err: errors.New("storage error")},
expected: errorInternal, expected: errorInternal,
}, { }, {
err: errors.Wrap(promql.ErrStorage{Err: errors.New("storage error")}, "wrapped"), err: fmt.Errorf("wrapped: %w", promql.ErrStorage{Err: errors.New("storage error")}),
expected: errorInternal, expected: errorInternal,
}, { }, {
err: promql.ErrQueryTimeout("timeout error"), err: promql.ErrQueryTimeout("timeout error"),
expected: errorTimeout, expected: errorTimeout,
}, { }, {
err: errors.Wrap(promql.ErrQueryTimeout("timeout error"), "wrapped"), err: fmt.Errorf("wrapped: %w", promql.ErrQueryTimeout("timeout error")),
expected: errorTimeout, expected: errorTimeout,
}, { }, {
err: promql.ErrQueryCanceled("canceled error"), err: promql.ErrQueryCanceled("canceled error"),
expected: errorCanceled, expected: errorCanceled,
}, { }, {
err: errors.Wrap(promql.ErrQueryCanceled("canceled error"), "wrapped"), err: fmt.Errorf("wrapped: %w", promql.ErrQueryCanceled("canceled error")),
expected: errorCanceled, expected: errorCanceled,
}, { }, {
err: errors.New("exec error"), err: errors.New("exec error"),
@ -2968,10 +2968,10 @@ func TestReturnAPIError(t *testing.T) {
}, },
} }
for _, c := range cases { for ix, c := range cases {
actual := returnAPIError(c.err) actual := returnAPIError(c.err)
require.Error(t, actual) require.Error(t, actual, ix)
require.Equal(t, c.expected, actual.typ) require.Equal(t, c.expected, actual.typ, ix)
} }
} }

236
web/api/v1/errors_test.go

@ -0,0 +1,236 @@
// Copyright 2022 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package v1
import (
"context"
"fmt"
"net/http"
"net/http/httptest"
"net/url"
"testing"
"time"
"github.com/go-kit/log"
"github.com/grafana/regexp"
"github.com/pkg/errors"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/route"
"github.com/stretchr/testify/require"
"github.com/prometheus/prometheus/config"
"github.com/prometheus/prometheus/model/labels"
"github.com/prometheus/prometheus/promql"
"github.com/prometheus/prometheus/rules"
"github.com/prometheus/prometheus/scrape"
"github.com/prometheus/prometheus/storage"
)
func TestApiStatusCodes(t *testing.T) {
for name, tc := range map[string]struct {
err error
expectedString string
expectedCode int
}{
"random error": {
err: errors.New("some random error"),
expectedString: "some random error",
expectedCode: http.StatusUnprocessableEntity,
},
"promql.ErrTooManySamples": {
err: promql.ErrTooManySamples("some error"),
expectedString: "too many samples",
expectedCode: http.StatusUnprocessableEntity,
},
"promql.ErrQueryCanceled": {
err: promql.ErrQueryCanceled("some error"),
expectedString: "query was canceled",
expectedCode: http.StatusServiceUnavailable,
},
"promql.ErrQueryTimeout": {
err: promql.ErrQueryTimeout("some error"),
expectedString: "query timed out",
expectedCode: http.StatusServiceUnavailable,
},
"context.DeadlineExceeded": {
err: context.DeadlineExceeded,
expectedString: "context deadline exceeded",
expectedCode: http.StatusUnprocessableEntity,
},
"context.Canceled": {
err: context.Canceled,
expectedString: "context canceled",
expectedCode: http.StatusUnprocessableEntity,
},
} {
for k, q := range map[string]storage.SampleAndChunkQueryable{
"error from queryable": errorTestQueryable{err: tc.err},
"error from querier": errorTestQueryable{q: errorTestQuerier{err: tc.err}},
"error from seriesset": errorTestQueryable{q: errorTestQuerier{s: errorTestSeriesSet{err: tc.err}}},
} {
t.Run(fmt.Sprintf("%s/%s", name, k), func(t *testing.T) {
r := createPrometheusAPI(q)
rec := httptest.NewRecorder()
req := httptest.NewRequest("GET", "/api/v1/query?query=up", nil)
r.ServeHTTP(rec, req)
require.Equal(t, tc.expectedCode, rec.Code)
require.Contains(t, rec.Body.String(), tc.expectedString)
})
}
}
}
func createPrometheusAPI(q storage.SampleAndChunkQueryable) *route.Router {
engine := promql.NewEngine(promql.EngineOpts{
Logger: log.NewNopLogger(),
Reg: nil,
ActiveQueryTracker: nil,
MaxSamples: 100,
Timeout: 5 * time.Second,
})
api := NewAPI(
engine,
q,
nil,
nil,
func(context.Context) TargetRetriever { return &DummyTargetRetriever{} },
func(context.Context) AlertmanagerRetriever { return &DummyAlertmanagerRetriever{} },
func() config.Config { return config.Config{} },
map[string]string{}, // TODO: include configuration flags
GlobalURLOptions{},
func(f http.HandlerFunc) http.HandlerFunc { return f },
nil, // Only needed for admin APIs.
"", // This is for snapshots, which is disabled when admin APIs are disabled. Hence empty.
false, // Disable admin APIs.
log.NewNopLogger(),
func(context.Context) RulesRetriever { return &DummyRulesRetriever{} },
0, 0, 0, // Remote read samples and concurrency limit.
false, // Not an agent.
regexp.MustCompile(".*"),
func() (RuntimeInfo, error) { return RuntimeInfo{}, errors.New("not implemented") },
&PrometheusVersion{},
prometheus.DefaultGatherer,
nil,
nil,
)
promRouter := route.New().WithPrefix("/api/v1")
api.Register(promRouter)
return promRouter
}
type errorTestQueryable struct {
q storage.Querier
err error
}
func (t errorTestQueryable) ChunkQuerier(ctx context.Context, mint, maxt int64) (storage.ChunkQuerier, error) {
return nil, t.err
}
func (t errorTestQueryable) Querier(ctx context.Context, mint, maxt int64) (storage.Querier, error) {
if t.q != nil {
return t.q, nil
}
return nil, t.err
}
type errorTestQuerier struct {
s storage.SeriesSet
err error
}
func (t errorTestQuerier) LabelValues(name string, matchers ...*labels.Matcher) ([]string, storage.Warnings, error) {
return nil, nil, t.err
}
func (t errorTestQuerier) LabelNames(matchers ...*labels.Matcher) ([]string, storage.Warnings, error) {
return nil, nil, t.err
}
func (t errorTestQuerier) Close() error {
return nil
}
func (t errorTestQuerier) Select(sortSeries bool, hints *storage.SelectHints, matchers ...*labels.Matcher) storage.SeriesSet {
if t.s != nil {
return t.s
}
return storage.ErrSeriesSet(t.err)
}
type errorTestSeriesSet struct {
err error
}
func (t errorTestSeriesSet) Next() bool {
return false
}
func (t errorTestSeriesSet) At() storage.Series {
return nil
}
func (t errorTestSeriesSet) Err() error {
return t.err
}
func (t errorTestSeriesSet) Warnings() storage.Warnings {
return nil
}
// DummyTargetRetriever implements github.com/prometheus/prometheus/web/api/v1.targetRetriever.
type DummyTargetRetriever struct{}
// TargetsActive implements targetRetriever.
func (DummyTargetRetriever) TargetsActive() map[string][]*scrape.Target {
return map[string][]*scrape.Target{}
}
// TargetsDropped implements targetRetriever.
func (DummyTargetRetriever) TargetsDropped() map[string][]*scrape.Target {
return map[string][]*scrape.Target{}
}
// DummyAlertmanagerRetriever implements AlertmanagerRetriever.
type DummyAlertmanagerRetriever struct{}
// Alertmanagers implements AlertmanagerRetriever.
func (DummyAlertmanagerRetriever) Alertmanagers() []*url.URL { return nil }
// DroppedAlertmanagers implements AlertmanagerRetriever.
func (DummyAlertmanagerRetriever) DroppedAlertmanagers() []*url.URL { return nil }
// DummyRulesRetriever implements RulesRetriever.
type DummyRulesRetriever struct{}
// RuleGroups implements RulesRetriever.
func (DummyRulesRetriever) RuleGroups() []*rules.Group {
return nil
}
// AlertingRules implements RulesRetriever.
func (DummyRulesRetriever) AlertingRules() []*rules.AlertingRule {
return nil
}

16
web/ui/build_ui.sh

@ -14,24 +14,24 @@
# limitations under the License. # limitations under the License.
set -e set -e
current=$(pwd)
buildOrder=(module/lezer-promql module/codemirror-promql) if ! [[ -w $HOME ]]
then
export npm_config_cache=$(mktemp -d)
fi
buildOrder=(lezer-promql codemirror-promql)
function buildModule() { function buildModule() {
for module in "${buildOrder[@]}"; do for module in "${buildOrder[@]}"; do
cd "${module}"
echo "build ${module}" echo "build ${module}"
npm run build npm run build -w "@prometheus-io/${module}"
cd "${current}"
done done
} }
function buildReactApp() { function buildReactApp() {
cd react-app
echo "build react-app" echo "build react-app"
npm run build npm run build -w @prometheus-io/app
cd "${current}"
rm -rf ./static/react rm -rf ./static/react
mv ./react-app/build ./static/react mv ./react-app/build ./static/react
} }

4
web/ui/module/codemirror-promql/jest.config.cjs

@ -12,7 +12,7 @@ module.exports = {
}, },
}, },
moduleNameMapper: { moduleNameMapper: {
'lezer-promql': '<rootDir>/../../node_modules/lezer-promql/dist/index.es.js' 'lezer-promql': '<rootDir>/../../node_modules/@prometheus-io/lezer-promql/dist/index.cjs'
}, },
transformIgnorePatterns: ["<rootDir>/../../node_modules/(?!lezer-promql)/"] transformIgnorePatterns: ["<rootDir>/../../node_modules/(?!@prometheus-io/lezer-promql)/"]
}; };

33
web/ui/module/codemirror-promql/package.json

@ -1,5 +1,5 @@
{ {
"name": "codemirror-promql", "name": "@prometheus-io/codemirror-promql",
"version": "0.19.0", "version": "0.19.0",
"description": "a CodeMirror mode for the PromQL language", "description": "a CodeMirror mode for the PromQL language",
"types": "dist/esm/index.d.ts", "types": "dist/esm/index.d.ts",
@ -29,30 +29,29 @@
}, },
"homepage": "https://github.com/prometheus/prometheus/blob/main/web/ui/module/codemirror-promql/README.md", "homepage": "https://github.com/prometheus/prometheus/blob/main/web/ui/module/codemirror-promql/README.md",
"dependencies": { "dependencies": {
"lezer-promql": "0.23.0", "@prometheus-io/lezer-promql": "0.23.0",
"lru-cache": "^6.0.0" "lru-cache": "^6.0.0"
}, },
"devDependencies": { "devDependencies": {
"@codemirror/autocomplete": "^0.19.15", "@codemirror/autocomplete": "^6.0.0",
"@codemirror/highlight": "^0.19.8", "@codemirror/language": "^6.0.0",
"@codemirror/language": "^0.19.10", "@codemirror/lint": "^6.0.0",
"@codemirror/lint": "^0.19.6", "@codemirror/state": "^6.0.0",
"@codemirror/state": "^0.19.9", "@codemirror/view": "^6.0.0",
"@codemirror/view": "^0.19.48", "@lezer/common": "^1.0.0",
"@lezer/common": "^0.15.12", "@lezer/lr": "^1.0.0",
"@lezer/lr": "^0.15.8", "@lezer/highlight": "^1.0.0",
"@types/lru-cache": "^5.1.1", "@types/lru-cache": "^5.1.1",
"isomorphic-fetch": "^3.0.0", "isomorphic-fetch": "^3.0.0",
"nock": "^13.2.4" "nock": "^13.2.4"
}, },
"peerDependencies": { "peerDependencies": {
"@codemirror/autocomplete": "^0.19.15", "@codemirror/autocomplete": "^6.0.0",
"@codemirror/highlight": "^0.19.8", "@codemirror/language": "^6.0.0",
"@codemirror/language": "^0.19.10", "@codemirror/lint": "^6.0.0",
"@codemirror/lint": "^0.19.6", "@codemirror/state": "^6.0.0",
"@codemirror/state": "^0.19.9", "@codemirror/view": "^6.0.0",
"@codemirror/view": "^0.19.48", "@lezer/common": "^1.0.0"
"@lezer/common": "^0.15.12"
}, },
"prettier": { "prettier": {
"singleQuote": true, "singleQuote": true,

94
web/ui/module/codemirror-promql/src/complete/hybrid.test.ts

@ -26,7 +26,7 @@ import {
numberTerms, numberTerms,
snippets, snippets,
} from './promql.terms'; } from './promql.terms';
import { EqlSingle, Neq } from 'lezer-promql'; import { EqlSingle, Neq } from '@prometheus-io/lezer-promql';
import { syntaxTree } from '@codemirror/language'; import { syntaxTree } from '@codemirror/language';
import { newCompleteStrategy } from './index'; import { newCompleteStrategy } from './index';
@ -734,7 +734,7 @@ describe('autocomplete promQL test', () => {
options: ([] as Completion[]).concat(functionIdentifierTerms, aggregateOpTerms, numberTerms, snippets), options: ([] as Completion[]).concat(functionIdentifierTerms, aggregateOpTerms, numberTerms, snippets),
from: 0, from: 0,
to: 0, to: 0,
span: /^[a-zA-Z0-9_:]+$/, validFor: /^[a-zA-Z0-9_:]+$/,
}, },
}, },
{ {
@ -745,7 +745,7 @@ describe('autocomplete promQL test', () => {
options: ([] as Completion[]).concat(functionIdentifierTerms, aggregateOpTerms, numberTerms, snippets), options: ([] as Completion[]).concat(functionIdentifierTerms, aggregateOpTerms, numberTerms, snippets),
from: 0, from: 0,
to: 3, to: 3,
span: /^[a-zA-Z0-9_:]+$/, validFor: /^[a-zA-Z0-9_:]+$/,
}, },
}, },
{ {
@ -756,7 +756,7 @@ describe('autocomplete promQL test', () => {
options: ([] as Completion[]).concat(functionIdentifierTerms, aggregateOpTerms, snippets), options: ([] as Completion[]).concat(functionIdentifierTerms, aggregateOpTerms, snippets),
from: 4, from: 4,
to: 4, to: 4,
span: /^[a-zA-Z0-9_:]+$/, validFor: /^[a-zA-Z0-9_:]+$/,
}, },
}, },
{ {
@ -767,7 +767,7 @@ describe('autocomplete promQL test', () => {
options: ([] as Completion[]).concat(functionIdentifierTerms, aggregateOpTerms, snippets), options: ([] as Completion[]).concat(functionIdentifierTerms, aggregateOpTerms, snippets),
from: 4, from: 4,
to: 6, to: 6,
span: /^[a-zA-Z0-9_:]+$/, validFor: /^[a-zA-Z0-9_:]+$/,
}, },
}, },
{ {
@ -778,7 +778,7 @@ describe('autocomplete promQL test', () => {
options: ([] as Completion[]).concat(functionIdentifierTerms, aggregateOpTerms, snippets), options: ([] as Completion[]).concat(functionIdentifierTerms, aggregateOpTerms, snippets),
from: 9, from: 9,
to: 9, to: 9,
span: /^[a-zA-Z0-9_:]+$/, validFor: /^[a-zA-Z0-9_:]+$/,
}, },
}, },
{ {
@ -789,7 +789,7 @@ describe('autocomplete promQL test', () => {
options: ([] as Completion[]).concat(functionIdentifierTerms, aggregateOpTerms, snippets), options: ([] as Completion[]).concat(functionIdentifierTerms, aggregateOpTerms, snippets),
from: 25, from: 25,
to: 33, to: 33,
span: /^[a-zA-Z0-9_:]+$/, validFor: /^[a-zA-Z0-9_:]+$/,
}, },
}, },
{ {
@ -800,7 +800,7 @@ describe('autocomplete promQL test', () => {
options: ([] as Completion[]).concat(functionIdentifierTerms, aggregateOpTerms, binOpModifierTerms, numberTerms, snippets), options: ([] as Completion[]).concat(functionIdentifierTerms, aggregateOpTerms, binOpModifierTerms, numberTerms, snippets),
from: 14, from: 14,
to: 19, to: 19,
span: /^[a-zA-Z0-9_:]+$/, validFor: /^[a-zA-Z0-9_:]+$/,
}, },
}, },
{ {
@ -811,7 +811,7 @@ describe('autocomplete promQL test', () => {
options: ([] as Completion[]).concat(functionIdentifierTerms, aggregateOpTerms, binOpModifierTerms, numberTerms, snippets), options: ([] as Completion[]).concat(functionIdentifierTerms, aggregateOpTerms, binOpModifierTerms, numberTerms, snippets),
from: 40, from: 40,
to: 41, to: 41,
span: /^[a-zA-Z0-9_:]+$/, validFor: /^[a-zA-Z0-9_:]+$/,
}, },
}, },
{ {
@ -822,7 +822,7 @@ describe('autocomplete promQL test', () => {
options: [], options: [],
from: 8, from: 8,
to: 8, to: 8,
span: /^[a-zA-Z0-9_:]+$/, validFor: /^[a-zA-Z0-9_:]+$/,
}, },
}, },
{ {
@ -833,7 +833,7 @@ describe('autocomplete promQL test', () => {
options: [], options: [],
from: 8, from: 8,
to: 11, to: 11,
span: /^[a-zA-Z0-9_:]+$/, validFor: /^[a-zA-Z0-9_:]+$/,
}, },
}, },
{ {
@ -844,7 +844,7 @@ describe('autocomplete promQL test', () => {
options: [], options: [],
from: 18, from: 18,
to: 23, to: 23,
span: /^[a-zA-Z0-9_:]+$/, validFor: /^[a-zA-Z0-9_:]+$/,
}, },
}, },
{ {
@ -855,7 +855,7 @@ describe('autocomplete promQL test', () => {
options: [], options: [],
from: 12, from: 12,
to: 12, to: 12,
span: /^[a-zA-Z0-9_:]+$/, validFor: /^[a-zA-Z0-9_:]+$/,
}, },
}, },
{ {
@ -866,7 +866,7 @@ describe('autocomplete promQL test', () => {
options: [], options: [],
from: 1, from: 1,
to: 1, to: 1,
span: /^[a-zA-Z0-9_:]+$/, validFor: /^[a-zA-Z0-9_:]+$/,
}, },
}, },
{ {
@ -877,7 +877,7 @@ describe('autocomplete promQL test', () => {
options: [], options: [],
from: 12, from: 12,
to: 15, to: 15,
span: /^[a-zA-Z0-9_:]+$/, validFor: /^[a-zA-Z0-9_:]+$/,
}, },
}, },
{ {
@ -888,7 +888,7 @@ describe('autocomplete promQL test', () => {
options: [], options: [],
from: 1, from: 1,
to: 4, to: 4,
span: /^[a-zA-Z0-9_:]+$/, validFor: /^[a-zA-Z0-9_:]+$/,
}, },
}, },
{ {
@ -899,7 +899,7 @@ describe('autocomplete promQL test', () => {
options: [], options: [],
from: 23, from: 23,
to: 23, to: 23,
span: /^[a-zA-Z0-9_:]+$/, validFor: /^[a-zA-Z0-9_:]+$/,
}, },
}, },
{ {
@ -910,7 +910,7 @@ describe('autocomplete promQL test', () => {
options: [], options: [],
from: 12, from: 12,
to: 12, to: 12,
span: /^[a-zA-Z0-9_:]+$/, validFor: /^[a-zA-Z0-9_:]+$/,
}, },
}, },
{ {
@ -921,7 +921,7 @@ describe('autocomplete promQL test', () => {
options: ([] as Completion[]).concat(aggregateOpModifierTerms, binOpTerms), options: ([] as Completion[]).concat(aggregateOpModifierTerms, binOpTerms),
from: 6, from: 6,
to: 7, to: 7,
span: /^[a-zA-Z0-9_:]+$/, validFor: /^[a-zA-Z0-9_:]+$/,
}, },
}, },
{ {
@ -932,7 +932,7 @@ describe('autocomplete promQL test', () => {
options: ([] as Completion[]).concat(aggregateOpModifierTerms, binOpTerms), options: ([] as Completion[]).concat(aggregateOpModifierTerms, binOpTerms),
from: 19, from: 19,
to: 21, to: 21,
span: /^[a-zA-Z0-9_:]+$/, validFor: /^[a-zA-Z0-9_:]+$/,
}, },
}, },
{ {
@ -943,7 +943,7 @@ describe('autocomplete promQL test', () => {
options: ([] as Completion[]).concat(aggregateOpModifierTerms, binOpTerms, [{ label: 'offset' }]), options: ([] as Completion[]).concat(aggregateOpModifierTerms, binOpTerms, [{ label: 'offset' }]),
from: 4, from: 4,
to: 5, to: 5,
span: /^[a-zA-Z0-9_:]+$/, validFor: /^[a-zA-Z0-9_:]+$/,
}, },
}, },
{ {
@ -954,7 +954,7 @@ describe('autocomplete promQL test', () => {
options: binOpTerms, options: binOpTerms,
from: 12, from: 12,
to: 13, to: 13,
span: /^[a-zA-Z0-9_:]+$/, validFor: /^[a-zA-Z0-9_:]+$/,
}, },
}, },
{ {
@ -965,7 +965,7 @@ describe('autocomplete promQL test', () => {
options: binOpTerms, options: binOpTerms,
from: 12, from: 12,
to: 13, to: 13,
span: /^[a-zA-Z0-9_:]+$/, validFor: /^[a-zA-Z0-9_:]+$/,
}, },
}, },
{ {
@ -976,7 +976,7 @@ describe('autocomplete promQL test', () => {
options: matchOpTerms, options: matchOpTerms,
from: 11, from: 11,
to: 12, to: 12,
span: /^[a-zA-Z0-9_:]+$/, validFor: /^[a-zA-Z0-9_:]+$/,
}, },
}, },
{ {
@ -987,7 +987,7 @@ describe('autocomplete promQL test', () => {
options: matchOpTerms, options: matchOpTerms,
from: 21, from: 21,
to: 22, to: 22,
span: /^[a-zA-Z0-9_:]+$/, validFor: /^[a-zA-Z0-9_:]+$/,
}, },
}, },
{ {
@ -998,7 +998,7 @@ describe('autocomplete promQL test', () => {
options: durationTerms, options: durationTerms,
from: 28, from: 28,
to: 28, to: 28,
span: undefined, validFor: undefined,
}, },
}, },
{ {
@ -1009,7 +1009,7 @@ describe('autocomplete promQL test', () => {
options: durationTerms, options: durationTerms,
from: 46, from: 46,
to: 46, to: 46,
span: undefined, validFor: undefined,
}, },
}, },
{ {
@ -1020,7 +1020,7 @@ describe('autocomplete promQL test', () => {
options: ([] as Completion[]).concat(binOpTerms, [{ label: 'offset' }]), options: ([] as Completion[]).concat(binOpTerms, [{ label: 'offset' }]),
from: 20, from: 20,
to: 23, to: 23,
span: /^[a-zA-Z0-9_:]+$/, validFor: /^[a-zA-Z0-9_:]+$/,
}, },
}, },
{ {
@ -1031,7 +1031,7 @@ describe('autocomplete promQL test', () => {
options: ([] as Completion[]).concat(binOpTerms, [{ label: 'offset' }]), options: ([] as Completion[]).concat(binOpTerms, [{ label: 'offset' }]),
from: 12, from: 12,
to: 16, to: 16,
span: /^[a-zA-Z0-9_:]+$/, validFor: /^[a-zA-Z0-9_:]+$/,
}, },
}, },
{ {
@ -1042,7 +1042,7 @@ describe('autocomplete promQL test', () => {
options: ([] as Completion[]).concat(binOpTerms, [{ label: 'offset' }]), options: ([] as Completion[]).concat(binOpTerms, [{ label: 'offset' }]),
from: 34, from: 34,
to: 37, to: 37,
span: /^[a-zA-Z0-9_:]+$/, validFor: /^[a-zA-Z0-9_:]+$/,
}, },
}, },
{ {
@ -1053,7 +1053,7 @@ describe('autocomplete promQL test', () => {
options: ([] as Completion[]).concat(binOpTerms, [{ label: 'offset' }]), options: ([] as Completion[]).concat(binOpTerms, [{ label: 'offset' }]),
from: 14, from: 14,
to: 16, to: 16,
span: /^[a-zA-Z0-9_:]+$/, validFor: /^[a-zA-Z0-9_:]+$/,
}, },
}, },
{ {
@ -1064,7 +1064,7 @@ describe('autocomplete promQL test', () => {
options: ([] as Completion[]).concat(binOpTerms, [{ label: 'offset' }]), options: ([] as Completion[]).concat(binOpTerms, [{ label: 'offset' }]),
from: 38, from: 38,
to: 41, to: 41,
span: /^[a-zA-Z0-9_:]+$/, validFor: /^[a-zA-Z0-9_:]+$/,
}, },
}, },
{ {
@ -1075,7 +1075,7 @@ describe('autocomplete promQL test', () => {
options: [], options: [],
from: 0, from: 0,
to: 3, to: 3,
span: /^[a-zA-Z0-9_:]+$/, validFor: /^[a-zA-Z0-9_:]+$/,
}, },
}, },
{ {
@ -1086,7 +1086,7 @@ describe('autocomplete promQL test', () => {
options: [], options: [],
from: 0, from: 0,
to: 12, to: 12,
span: /^[a-zA-Z0-9_:]+$/, validFor: /^[a-zA-Z0-9_:]+$/,
}, },
}, },
{ {
@ -1097,7 +1097,7 @@ describe('autocomplete promQL test', () => {
options: durationTerms, options: durationTerms,
from: 4, from: 4,
to: 4, to: 4,
span: undefined, validFor: undefined,
}, },
}, },
{ {
@ -1108,7 +1108,7 @@ describe('autocomplete promQL test', () => {
options: durationTerms, options: durationTerms,
from: 6, from: 6,
to: 6, to: 6,
span: undefined, validFor: undefined,
}, },
}, },
{ {
@ -1119,7 +1119,7 @@ describe('autocomplete promQL test', () => {
options: durationTerms, options: durationTerms,
from: 26, from: 26,
to: 26, to: 26,
span: undefined, validFor: undefined,
}, },
}, },
{ {
@ -1130,7 +1130,7 @@ describe('autocomplete promQL test', () => {
options: durationTerms, options: durationTerms,
from: 28, from: 28,
to: 28, to: 28,
span: undefined, validFor: undefined,
}, },
}, },
{ {
@ -1141,7 +1141,7 @@ describe('autocomplete promQL test', () => {
options: durationTerms, options: durationTerms,
from: 7, from: 7,
to: 7, to: 7,
span: undefined, validFor: undefined,
}, },
}, },
{ {
@ -1152,7 +1152,7 @@ describe('autocomplete promQL test', () => {
options: durationTerms, options: durationTerms,
from: 9, from: 9,
to: 9, to: 9,
span: undefined, validFor: undefined,
}, },
}, },
{ {
@ -1163,7 +1163,7 @@ describe('autocomplete promQL test', () => {
options: durationTerms, options: durationTerms,
from: 29, from: 29,
to: 29, to: 29,
span: undefined, validFor: undefined,
}, },
}, },
{ {
@ -1174,7 +1174,7 @@ describe('autocomplete promQL test', () => {
options: durationTerms, options: durationTerms,
from: 31, from: 31,
to: 31, to: 31,
span: undefined, validFor: undefined,
}, },
}, },
{ {
@ -1185,7 +1185,7 @@ describe('autocomplete promQL test', () => {
options: atModifierTerms, options: atModifierTerms,
from: 4, from: 4,
to: 5, to: 5,
span: /^[a-zA-Z0-9_:]+$/, validFor: /^[a-zA-Z0-9_:]+$/,
}, },
}, },
{ {
@ -1197,7 +1197,7 @@ describe('autocomplete promQL test', () => {
options: ([] as Completion[]).concat(mockedMetricsTerms, functionIdentifierTerms, aggregateOpTerms, numberTerms, snippets), options: ([] as Completion[]).concat(mockedMetricsTerms, functionIdentifierTerms, aggregateOpTerms, numberTerms, snippets),
from: 0, from: 0,
to: 5, to: 5,
span: /^[a-zA-Z0-9_:]+$/, validFor: /^[a-zA-Z0-9_:]+$/,
}, },
}, },
{ {
@ -1226,7 +1226,7 @@ describe('autocomplete promQL test', () => {
], ],
from: 20, from: 20,
to: 20, to: 20,
span: /^[a-zA-Z0-9_:]+$/, validFor: /^[a-zA-Z0-9_:]+$/,
}, },
}, },
{ {
@ -1243,7 +1243,7 @@ describe('autocomplete promQL test', () => {
], ],
from: 25, from: 25,
to: 25, to: 25,
span: /^[a-zA-Z0-9_:]+$/, validFor: /^[a-zA-Z0-9_:]+$/,
}, },
}, },
{ {
@ -1274,7 +1274,7 @@ describe('autocomplete promQL test', () => {
), ),
from: 0, from: 0,
to: 3, to: 3,
span: /^[a-zA-Z0-9_:]+$/, validFor: /^[a-zA-Z0-9_:]+$/,
}, },
}, },
]; ];

4
web/ui/module/codemirror-promql/src/complete/hybrid.ts

@ -58,7 +58,7 @@ import {
SubqueryExpr, SubqueryExpr,
Unless, Unless,
VectorSelector, VectorSelector,
} from 'lezer-promql'; } from '@prometheus-io/lezer-promql';
import { Completion, CompletionContext, CompletionResult } from '@codemirror/autocomplete'; import { Completion, CompletionContext, CompletionResult } from '@codemirror/autocomplete';
import { EditorState } from '@codemirror/state'; import { EditorState } from '@codemirror/state';
import { buildLabelMatchers, containsAtLeastOneChild, containsChild, retrieveAllRecursiveNodes, walkBackward, walkThrough } from '../parser'; import { buildLabelMatchers, containsAtLeastOneChild, containsChild, retrieveAllRecursiveNodes, walkBackward, walkThrough } from '../parser';
@ -140,7 +140,7 @@ function arrayToCompletionResult(data: Completion[], from: number, to: number, i
from: from, from: from,
to: to, to: to,
options: options, options: options,
span: span ? /^[a-zA-Z0-9_:]+$/ : undefined, validFor: span ? /^[a-zA-Z0-9_:]+$/ : undefined,
} as CompletionResult; } as CompletionResult;
} }

2
web/ui/module/codemirror-promql/src/parser/matcher.test.ts

@ -11,7 +11,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
import { EqlRegex, EqlSingle, Neq, NeqRegex } from 'lezer-promql'; import { EqlRegex, EqlSingle, Neq, NeqRegex } from '@prometheus-io/lezer-promql';
import { labelMatchersToString } from './matcher'; import { labelMatchersToString } from './matcher';
import { Matcher } from '../types'; import { Matcher } from '../types';

4
web/ui/module/codemirror-promql/src/parser/matcher.ts

@ -12,13 +12,13 @@
// limitations under the License. // limitations under the License.
import { SyntaxNode } from '@lezer/common'; import { SyntaxNode } from '@lezer/common';
import { EqlRegex, EqlSingle, LabelName, MatchOp, Neq, NeqRegex, StringLiteral } from 'lezer-promql'; import { EqlRegex, EqlSingle, LabelName, MatchOp, Neq, NeqRegex, StringLiteral } from '@prometheus-io/lezer-promql';
import { EditorState } from '@codemirror/state'; import { EditorState } from '@codemirror/state';
import { Matcher } from '../types'; import { Matcher } from '../types';
function createMatcher(labelMatcher: SyntaxNode, state: EditorState): Matcher { function createMatcher(labelMatcher: SyntaxNode, state: EditorState): Matcher {
const matcher = new Matcher(0, '', ''); const matcher = new Matcher(0, '', '');
const cursor = labelMatcher.cursor; const cursor = labelMatcher.cursor();
if (!cursor.next()) { if (!cursor.next()) {
// weird case, that would mean the labelMatcher doesn't have any child. // weird case, that would mean the labelMatcher doesn't have any child.
return matcher; return matcher;

2
web/ui/module/codemirror-promql/src/parser/parser.ts

@ -47,7 +47,7 @@ import {
UnaryExpr, UnaryExpr,
Unless, Unless,
VectorSelector, VectorSelector,
} from 'lezer-promql'; } from '@prometheus-io/lezer-promql';
import { containsAtLeastOneChild, retrieveAllRecursiveNodes, walkThrough } from './path-finder'; import { containsAtLeastOneChild, retrieveAllRecursiveNodes, walkThrough } from './path-finder';
import { getType } from './type'; import { getType } from './type';
import { buildLabelMatchers } from './matcher'; import { buildLabelMatchers } from './matcher';

2
web/ui/module/codemirror-promql/src/parser/path-finder.test.ts

@ -31,7 +31,7 @@ import {
NumberLiteral, NumberLiteral,
Sub, Sub,
VectorSelector, VectorSelector,
} from 'lezer-promql'; } from '@prometheus-io/lezer-promql';
import { createEditorState } from '../test/utils-test'; import { createEditorState } from '../test/utils-test';
import { containsAtLeastOneChild, containsChild, retrieveAllRecursiveNodes, walkBackward, walkThrough } from './path-finder'; import { containsAtLeastOneChild, containsChild, retrieveAllRecursiveNodes, walkBackward, walkThrough } from './path-finder';
import { SyntaxNode } from '@lezer/common'; import { SyntaxNode } from '@lezer/common';

8
web/ui/module/codemirror-promql/src/parser/path-finder.ts

@ -16,7 +16,7 @@ import { SyntaxNode } from '@lezer/common';
// walkBackward will iterate other the tree from the leaf to the root until it founds the given `exit` node. // walkBackward will iterate other the tree from the leaf to the root until it founds the given `exit` node.
// It returns null if the exit is not found. // It returns null if the exit is not found.
export function walkBackward(node: SyntaxNode, exit: number): SyntaxNode | null { export function walkBackward(node: SyntaxNode, exit: number): SyntaxNode | null {
const cursor = node.cursor; const cursor = node.cursor();
let cursorIsMoving = true; let cursorIsMoving = true;
while (cursorIsMoving && cursor.type.id !== exit) { while (cursorIsMoving && cursor.type.id !== exit) {
cursorIsMoving = cursor.parent(); cursorIsMoving = cursor.parent();
@ -29,7 +29,7 @@ export function walkBackward(node: SyntaxNode, exit: number): SyntaxNode | null
// Otherwise if it's not possible to reach the last id/name of the path, it will return `null` // Otherwise if it's not possible to reach the last id/name of the path, it will return `null`
// Note: the way followed during the iteration of the tree to find the given path, is only from the root to the leaf. // Note: the way followed during the iteration of the tree to find the given path, is only from the root to the leaf.
export function walkThrough(node: SyntaxNode, ...path: (number | string)[]): SyntaxNode | null { export function walkThrough(node: SyntaxNode, ...path: (number | string)[]): SyntaxNode | null {
const cursor = node.cursor; const cursor = node.cursor();
let i = 0; let i = 0;
let cursorIsMoving = true; let cursorIsMoving = true;
path.unshift(cursor.type.id); path.unshift(cursor.type.id);
@ -50,7 +50,7 @@ export function walkThrough(node: SyntaxNode, ...path: (number | string)[]): Syn
} }
export function containsAtLeastOneChild(node: SyntaxNode, ...child: (number | string)[]): boolean { export function containsAtLeastOneChild(node: SyntaxNode, ...child: (number | string)[]): boolean {
const cursor = node.cursor; const cursor = node.cursor();
if (!cursor.next()) { if (!cursor.next()) {
// let's try to move directly to the children level and // let's try to move directly to the children level and
// return false immediately if the current node doesn't have any child // return false immediately if the current node doesn't have any child
@ -64,7 +64,7 @@ export function containsAtLeastOneChild(node: SyntaxNode, ...child: (number | st
} }
export function containsChild(node: SyntaxNode, ...child: (number | string)[]): boolean { export function containsChild(node: SyntaxNode, ...child: (number | string)[]): boolean {
const cursor = node.cursor; const cursor = node.cursor();
if (!cursor.next()) { if (!cursor.next()) {
// let's try to move directly to the children level and // let's try to move directly to the children level and
// return false immediately if the current node doesn't have any child // return false immediately if the current node doesn't have any child

2
web/ui/module/codemirror-promql/src/parser/type.ts

@ -26,7 +26,7 @@ import {
SubqueryExpr, SubqueryExpr,
UnaryExpr, UnaryExpr,
VectorSelector, VectorSelector,
} from 'lezer-promql'; } from '@prometheus-io/lezer-promql';
import { walkThrough } from './path-finder'; import { walkThrough } from './path-finder';
import { getFunction, ValueType } from '../types'; import { getFunction, ValueType } from '../types';

2
web/ui/module/codemirror-promql/src/parser/vector.test.ts

@ -14,7 +14,7 @@
import { buildVectorMatching } from './vector'; import { buildVectorMatching } from './vector';
import { createEditorState } from '../test/utils-test'; import { createEditorState } from '../test/utils-test';
import { walkThrough } from './path-finder'; import { walkThrough } from './path-finder';
import { BinaryExpr, Expr } from 'lezer-promql'; import { BinaryExpr, Expr } from '@prometheus-io/lezer-promql';
import { syntaxTree } from '@codemirror/language'; import { syntaxTree } from '@codemirror/language';
import { VectorMatchCardinality } from '../types'; import { VectorMatchCardinality } from '../types';

2
web/ui/module/codemirror-promql/src/parser/vector.ts

@ -26,7 +26,7 @@ import {
OnOrIgnoring, OnOrIgnoring,
Or, Or,
Unless, Unless,
} from 'lezer-promql'; } from '@prometheus-io/lezer-promql';
import { VectorMatchCardinality, VectorMatching } from '../types'; import { VectorMatchCardinality, VectorMatching } from '../types';
import { containsAtLeastOneChild, retrieveAllRecursiveNodes } from './path-finder'; import { containsAtLeastOneChild, retrieveAllRecursiveNodes } from './path-finder';

23
web/ui/module/codemirror-promql/src/promql.ts

@ -11,8 +11,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
import { parser } from 'lezer-promql'; import { parser } from '@prometheus-io/lezer-promql';
import { styleTags, tags } from '@codemirror/highlight';
import { Extension } from '@codemirror/state'; import { Extension } from '@codemirror/state';
import { CompleteConfiguration, CompleteStrategy, newCompleteStrategy } from './complete'; import { CompleteConfiguration, CompleteStrategy, newCompleteStrategy } from './complete';
import { LintStrategy, newLintStrategy, promQLLinter } from './lint'; import { LintStrategy, newLintStrategy, promQLLinter } from './lint';
@ -28,26 +27,6 @@ export function promQLLanguage(top: LanguageType): LRLanguage {
return LRLanguage.define({ return LRLanguage.define({
parser: parser.configure({ parser: parser.configure({
top: top, top: top,
props: [
styleTags({
LineComment: tags.comment,
LabelName: tags.labelName,
StringLiteral: tags.string,
NumberLiteral: tags.number,
Duration: tags.number,
'Abs Absent AbsentOverTime Acos Acosh Asin Asinh Atan Atanh AvgOverTime Ceil Changes Clamp ClampMax ClampMin Cos Cosh CountOverTime DaysInMonth DayOfMonth DayOfWeek DayOfYear Deg Delta Deriv Exp Floor HistogramQuantile HoltWinters Hour Idelta Increase Irate LabelReplace LabelJoin LastOverTime Ln Log10 Log2 MaxOverTime MinOverTime Minute Month Pi PredictLinear PresentOverTime QuantileOverTime Rad Rate Resets Round Scalar Sgn Sin Sinh Sort SortDesc Sqrt StddevOverTime StdvarOverTime SumOverTime Tan Tanh Time Timestamp Vector Year':
tags.function(tags.variableName),
'Avg Bottomk Count Count_values Group Max Min Quantile Stddev Stdvar Sum Topk': tags.operatorKeyword,
'By Without Bool On Ignoring GroupLeft GroupRight Offset Start End': tags.modifier,
'And Unless Or': tags.logicOperator,
'Sub Add Mul Mod Div Atan2 Eql Neq Lte Lss Gte Gtr EqlRegex EqlSingle NeqRegex Pow At': tags.operator,
UnaryOp: tags.arithmeticOperator,
'( )': tags.paren,
'[ ]': tags.squareBracket,
'{ }': tags.brace,
'⚠': tags.invalid,
}),
],
}), }),
languageData: { languageData: {
closeBrackets: { brackets: ['(', '[', '{', "'", '"', '`'] }, closeBrackets: { brackets: ['(', '[', '{', "'", '"', '`'] },

2
web/ui/module/codemirror-promql/src/test/utils-test.ts

@ -11,7 +11,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
import { parser } from 'lezer-promql'; import { parser } from '@prometheus-io/lezer-promql';
import { EditorState } from '@codemirror/state'; import { EditorState } from '@codemirror/state';
import { LRLanguage } from '@codemirror/language'; import { LRLanguage } from '@codemirror/language';
import nock from 'nock'; import nock from 'nock';

2
web/ui/module/codemirror-promql/src/types/function.ts

@ -79,7 +79,7 @@ import {
Timestamp, Timestamp,
Vector, Vector,
Year, Year,
} from 'lezer-promql'; } from '@prometheus-io/lezer-promql';
export enum ValueType { export enum ValueType {
none = 'none', none = 'none',

2
web/ui/module/codemirror-promql/src/types/matcher.ts

@ -11,7 +11,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
import { EqlSingle, Neq } from 'lezer-promql'; import { EqlSingle, Neq } from '@prometheus-io/lezer-promql';
export class Matcher { export class Matcher {
type: number; type: number;

10
web/ui/module/lezer-promql/package.json

@ -1,5 +1,5 @@
{ {
"name": "lezer-promql", "name": "@prometheus-io/lezer-promql",
"version": "0.23.0", "version": "0.23.0",
"description": "lezer-based PromQL grammar", "description": "lezer-based PromQL grammar",
"main": "index.cjs", "main": "index.cjs",
@ -30,10 +30,12 @@
"test": "NODE_OPTIONS=--experimental-vm-modules jest" "test": "NODE_OPTIONS=--experimental-vm-modules jest"
}, },
"devDependencies": { "devDependencies": {
"@lezer/generator": "^0.15.4", "@lezer/generator": "^1.0.0",
"@lezer/lr": "^0.15.8" "@lezer/lr": "^1.0.0",
"@lezer/highlight": "^1.0.0"
}, },
"peerDependencies": { "peerDependencies": {
"@lezer/lr": "^0.15.8" "@lezer/lr": "^1.0.0",
"@lezer/highlight": "^1.0.0"
} }
} }

33
web/ui/module/lezer-promql/src/highlight.js

@ -0,0 +1,33 @@
// Copyright 2022 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import {styleTags, tags} from "@lezer/highlight";
export const promQLHighLight = styleTags({
LineComment: tags.comment,
LabelName: tags.labelName,
StringLiteral: tags.string,
NumberLiteral: tags.number,
Duration: tags.number,
'Abs Absent AbsentOverTime Acos Acosh Asin Asinh Atan Atanh AvgOverTime Ceil Changes Clamp ClampMax ClampMin Cos Cosh CountOverTime DaysInMonth DayOfMonth DayOfWeek DayOfYear Deg Delta Deriv Exp Floor HistogramQuantile HoltWinters Hour Idelta Increase Irate LabelReplace LabelJoin LastOverTime Ln Log10 Log2 MaxOverTime MinOverTime Minute Month Pi PredictLinear PresentOverTime QuantileOverTime Rad Rate Resets Round Scalar Sgn Sin Sinh Sort SortDesc Sqrt StddevOverTime StdvarOverTime SumOverTime Tan Tanh Time Timestamp Vector Year':
tags.function(tags.variableName),
'Avg Bottomk Count Count_values Group Max Min Quantile Stddev Stdvar Sum Topk': tags.operatorKeyword,
'By Without Bool On Ignoring GroupLeft GroupRight Offset Start End': tags.modifier,
'And Unless Or': tags.logicOperator,
'Sub Add Mul Mod Div Atan2 Eql Neq Lte Lss Gte Gtr EqlRegex EqlSingle NeqRegex Pow At': tags.operator,
UnaryOp: tags.arithmeticOperator,
'( )': tags.paren,
'[ ]': tags.squareBracket,
'{ }': tags.brace,
'⚠': tags.invalid,
})

2
web/ui/module/lezer-promql/src/promql.grammar

@ -357,6 +357,8 @@ NumberLiteral {
End End
} }
@external propSource promQLHighLight from "./highlight"
// FunctionIdentifier definitions // FunctionIdentifier definitions
Abs { condFn<"abs"> } Abs { condFn<"abs"> }
Absent { condFn<"absent"> } Absent { condFn<"absent"> }

9502
web/ui/package-lock.json generated

File diff suppressed because it is too large Load Diff

2
web/ui/package.json

@ -1,5 +1,5 @@
{ {
"name": "prometheus", "name": "prometheus-io",
"private": true, "private": true,
"scripts": { "scripts": {
"build": "bash build_ui.sh --all", "build": "bash build_ui.sh --all",

32
web/ui/react-app/package.json

@ -1,28 +1,26 @@
{ {
"name": "graph", "name": "@prometheus-io/app",
"version": "0.1.0", "version": "0.1.0",
"private": true, "private": true,
"dependencies": { "dependencies": {
"@codemirror/autocomplete": "^0.19.9", "@codemirror/autocomplete": "^6.0.0",
"@codemirror/closebrackets": "^0.19.0", "@codemirror/commands": "^6.0.0",
"@codemirror/commands": "^0.19.5", "@codemirror/language": "^6.0.0",
"@codemirror/comment": "^0.19.0", "@codemirror/lint": "^6.0.0",
"@codemirror/highlight": "^0.19.6", "@codemirror/search": "^6.0.0",
"@codemirror/history": "^0.19.2", "@codemirror/state": "^6.0.0",
"@codemirror/language": "^0.19.7", "@codemirror/view": "^6.0.0",
"@codemirror/lint": "^0.19.3",
"@codemirror/matchbrackets": "^0.19.3",
"@codemirror/search": "^0.19.3",
"@codemirror/state": "^0.19.6",
"@codemirror/view": "^0.19.27",
"@forevolve/bootstrap-dark": "^1.0.0", "@forevolve/bootstrap-dark": "^1.0.0",
"@fortawesome/fontawesome-svg-core": "6.1.1", "@fortawesome/fontawesome-svg-core": "6.1.1",
"@fortawesome/free-solid-svg-icons": "6.1.1", "@fortawesome/free-solid-svg-icons": "6.1.1",
"@fortawesome/react-fontawesome": "0.1.17", "@fortawesome/react-fontawesome": "0.1.17",
"@lezer/lr": "^1.0.0",
"@lezer/highlight": "^1.0.0",
"@lezer/common": "^1.0.0",
"@nexucis/fuzzy": "^0.4.0", "@nexucis/fuzzy": "^0.4.0",
"@nexucis/kvsearch": "^0.7.0", "@nexucis/kvsearch": "^0.7.0",
"@prometheus-io/codemirror-promql": "0.19.0",
"bootstrap": "^4.6.1", "bootstrap": "^4.6.1",
"codemirror-promql": "0.19.0",
"css.escape": "^1.5.1", "css.escape": "^1.5.1",
"downshift": "^6.1.7", "downshift": "^6.1.7",
"http-proxy-middleware": "^2.0.6", "http-proxy-middleware": "^2.0.6",
@ -89,11 +87,11 @@
"enzyme-to-json/serializer" "enzyme-to-json/serializer"
], ],
"transformIgnorePatterns": [ "transformIgnorePatterns": [
"<rootDir>/../node_modules/(?!codemirror-promql)/", "<rootDir>/../node_modules/(?!@prometheus-io/codemirror-promql)/",
"<rootDir>/../node_modules/(?!lezer-promql)/" "<rootDir>/../node_modules/(?!@prometheus-io/lezer-promql)/"
], ],
"moduleNameMapper": { "moduleNameMapper": {
"lezer-promql": "<rootDir>/../node_modules/lezer-promql/dist/index.cjs" "lezer-promql": "<rootDir>/../node_modules/@prometheus-io/lezer-promql/dist/index.cjs"
} }
}, },
"optionalDependencies": { "optionalDependencies": {

3
web/ui/react-app/src/pages/graph/CMTheme.tsx

@ -1,5 +1,6 @@
import { HighlightStyle, tags } from '@codemirror/highlight';
import { EditorView } from '@codemirror/view'; import { EditorView } from '@codemirror/view';
import { HighlightStyle } from '@codemirror/language';
import { tags } from '@lezer/highlight';
export const baseTheme = EditorView.theme({ export const baseTheme = EditorView.theme({
'&.cm-editor': { '&.cm-editor': {

36
web/ui/react-app/src/pages/graph/ExpressionInput.tsx

@ -3,15 +3,18 @@ import { Button, InputGroup, InputGroupAddon, InputGroupText } from 'reactstrap'
import { EditorView, highlightSpecialChars, keymap, ViewUpdate, placeholder } from '@codemirror/view'; import { EditorView, highlightSpecialChars, keymap, ViewUpdate, placeholder } from '@codemirror/view';
import { EditorState, Prec, Compartment } from '@codemirror/state'; import { EditorState, Prec, Compartment } from '@codemirror/state';
import { indentOnInput, syntaxTree } from '@codemirror/language'; import { bracketMatching, indentOnInput, syntaxHighlighting, syntaxTree } from '@codemirror/language';
import { history, historyKeymap } from '@codemirror/history'; import { defaultKeymap, history, historyKeymap, insertNewlineAndIndent } from '@codemirror/commands';
import { defaultKeymap, insertNewlineAndIndent } from '@codemirror/commands';
import { bracketMatching } from '@codemirror/matchbrackets';
import { closeBrackets, closeBracketsKeymap } from '@codemirror/closebrackets';
import { highlightSelectionMatches } from '@codemirror/search'; import { highlightSelectionMatches } from '@codemirror/search';
import { commentKeymap } from '@codemirror/comment';
import { lintKeymap } from '@codemirror/lint'; import { lintKeymap } from '@codemirror/lint';
import { autocompletion, completionKeymap, CompletionContext, CompletionResult } from '@codemirror/autocomplete'; import {
autocompletion,
completionKeymap,
CompletionContext,
CompletionResult,
closeBrackets,
closeBracketsKeymap,
} from '@codemirror/autocomplete';
import { baseTheme, lightTheme, darkTheme, promqlHighlighter } from './CMTheme'; import { baseTheme, lightTheme, darkTheme, promqlHighlighter } from './CMTheme';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
@ -19,8 +22,8 @@ import { faSearch, faSpinner, faGlobeEurope } from '@fortawesome/free-solid-svg-
import MetricsExplorer from './MetricsExplorer'; import MetricsExplorer from './MetricsExplorer';
import { usePathPrefix } from '../../contexts/PathPrefixContext'; import { usePathPrefix } from '../../contexts/PathPrefixContext';
import { useTheme } from '../../contexts/ThemeContext'; import { useTheme } from '../../contexts/ThemeContext';
import { CompleteStrategy, PromQLExtension } from 'codemirror-promql'; import { CompleteStrategy, PromQLExtension } from '@prometheus-io/codemirror-promql';
import { newCompleteStrategy } from 'codemirror-promql/dist/esm/complete'; import { newCompleteStrategy } from '@prometheus-io/codemirror-promql/dist/esm/complete';
const promqlExtension = new PromQLExtension(); const promqlExtension = new PromQLExtension();
@ -67,7 +70,7 @@ export class HistoryCompleteStrategy implements CompleteStrategy {
apply: q, apply: q,
info: q.length < 80 ? undefined : q, info: q.length < 80 ? undefined : q,
})), })),
span: /^[a-zA-Z0-9_:]+$/, validFor: /^[a-zA-Z0-9_:]+$/,
}; };
if (res !== null) { if (res !== null) {
@ -110,7 +113,7 @@ const ExpressionInput: FC<CMExpressionInputProps> = ({
), ),
}); });
const dynamicConfig = [ const dynamicConfig = [
enableHighlighting ? promqlHighlighter : [], enableHighlighting ? syntaxHighlighting(promqlHighlighter) : [],
promqlExtension.asExtension(), promqlExtension.asExtension(),
theme === 'dark' ? darkTheme : lightTheme, theme === 'dark' ? darkTheme : lightTheme,
]; ];
@ -136,14 +139,7 @@ const ExpressionInput: FC<CMExpressionInputProps> = ({
autocompletion(), autocompletion(),
highlightSelectionMatches(), highlightSelectionMatches(),
EditorView.lineWrapping, EditorView.lineWrapping,
keymap.of([ keymap.of([...closeBracketsKeymap, ...defaultKeymap, ...historyKeymap, ...completionKeymap, ...lintKeymap]),
...closeBracketsKeymap,
...defaultKeymap,
...historyKeymap,
...commentKeymap,
...completionKeymap,
...lintKeymap,
]),
placeholder('Expression (press Shift+Enter for newlines)'), placeholder('Expression (press Shift+Enter for newlines)'),
dynamicConfigCompartment.of(dynamicConfig), dynamicConfigCompartment.of(dynamicConfig),
// This keymap is added without precedence so that closing the autocomplete dropdown // This keymap is added without precedence so that closing the autocomplete dropdown
@ -157,7 +153,7 @@ const ExpressionInput: FC<CMExpressionInputProps> = ({
}, },
}, },
]), ]),
Prec.override( Prec.highest(
keymap.of([ keymap.of([
{ {
key: 'Enter', key: 'Enter',

Loading…
Cancel
Save