mirror of
https://github.com/SigNoz/signoz.git
synced 2026-06-21 15:50:27 +01:00
Compare commits
15 Commits
refactor/u
...
SIG-3098
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
860ddf34ca | ||
|
|
9c5b50ae3a | ||
|
|
fd13c6dee4 | ||
|
|
a894b08255 | ||
|
|
2c6c034e60 | ||
|
|
0a81bf8060 | ||
|
|
b38ffce7f2 | ||
|
|
696d83eeaf | ||
|
|
d98851dcf2 | ||
|
|
a103bb453d | ||
|
|
abae0c7f27 | ||
|
|
0cc1fb0edb | ||
|
|
f2ef42bd7f | ||
|
|
22158a3cee | ||
|
|
20fec8baa4 |
18
.github/CODEOWNERS
vendored
18
.github/CODEOWNERS
vendored
@@ -1,10 +1,13 @@
|
||||
# CODEOWNERS info: https://help.github.com/en/articles/about-code-owners
|
||||
|
||||
# Owners are automatically requested for review for PRs that changes code
|
||||
|
||||
# that they own.
|
||||
|
||||
/frontend/ @SigNoz/frontend-maintainers
|
||||
|
||||
# Onboarding
|
||||
|
||||
/frontend/src/container/OnboardingV2Container/onboarding-configs/onboarding-config-with-links.json @makeavish
|
||||
/frontend/src/container/OnboardingV2Container/AddDataSource/AddDataSource.tsx @makeavish
|
||||
|
||||
@@ -12,6 +15,7 @@
|
||||
.github @SigNoz/devops
|
||||
|
||||
# Scaffold Owners
|
||||
|
||||
/pkg/config/ @therealpandey
|
||||
/pkg/errors/ @therealpandey
|
||||
/pkg/factory/ @therealpandey
|
||||
@@ -21,22 +25,26 @@
|
||||
.golangci.yml @therealpandey
|
||||
|
||||
# Zeus Owners
|
||||
|
||||
/pkg/zeus/ @vikrantgupta25
|
||||
/ee/zeus/ @vikrantgupta25
|
||||
/pkg/licensing/ @vikrantgupta25
|
||||
/ee/licensing/ @vikrantgupta25
|
||||
|
||||
# SQL Owners
|
||||
|
||||
/pkg/sqlmigration/ @vikrantgupta25
|
||||
/ee/sqlmigration/ @vikrantgupta25
|
||||
/pkg/sqlschema/ @vikrantgupta25
|
||||
/ee/sqlschema/ @vikrantgupta25
|
||||
|
||||
# Analytics Owners
|
||||
|
||||
/pkg/analytics/ @vikrantgupta25
|
||||
/pkg/statsreporter/ @vikrantgupta25
|
||||
|
||||
# Querier Owners
|
||||
|
||||
/pkg/querier/ @srikanthccv
|
||||
/pkg/variables/ @srikanthccv
|
||||
/pkg/types/querybuildertypes/ @srikanthccv
|
||||
@@ -46,8 +54,16 @@
|
||||
/pkg/telemetrymetrics/ @srikanthccv
|
||||
/pkg/telemetrytraces/ @srikanthccv
|
||||
|
||||
# AuthN / AuthZ Owners
|
||||
# AuthN / AuthZ Owners
|
||||
|
||||
/pkg/authz/ @vikrantgupta25 @therealpandey
|
||||
|
||||
# Integration tests
|
||||
|
||||
/tests/integration/ @therealpandey
|
||||
|
||||
# Dashboard Owners
|
||||
|
||||
/frontend/src/pages/DashboardPage/ @SigNoz/pulse-frontend
|
||||
/frontend/src/container/NewDashboard/ @SigNoz/pulse-frontend
|
||||
/frontend/src/container/GridCardLayout/ @SigNoz/pulse-frontend
|
||||
|
||||
18
.github/workflows/integrationci.yaml
vendored
18
.github/workflows/integrationci.yaml
vendored
@@ -21,11 +21,11 @@ jobs:
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: 3.13
|
||||
- name: poetry
|
||||
- name: uv
|
||||
uses: astral-sh/setup-uv@v4
|
||||
- name: install
|
||||
run: |
|
||||
python -m pip install poetry==2.1.2
|
||||
python -m poetry config virtualenvs.in-project true
|
||||
cd tests/integration && poetry install --no-root
|
||||
cd tests/integration && uv sync
|
||||
- name: fmt
|
||||
run: |
|
||||
make py-fmt
|
||||
@@ -67,11 +67,11 @@ jobs:
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: 3.13
|
||||
- name: poetry
|
||||
- name: uv
|
||||
uses: astral-sh/setup-uv@v4
|
||||
- name: install
|
||||
run: |
|
||||
python -m pip install poetry==2.1.2
|
||||
python -m poetry config virtualenvs.in-project true
|
||||
cd tests/integration && poetry install --no-root
|
||||
cd tests/integration && uv sync
|
||||
- name: webdriver
|
||||
run: |
|
||||
wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add -
|
||||
@@ -89,7 +89,7 @@ jobs:
|
||||
- name: run
|
||||
run: |
|
||||
cd tests/integration && \
|
||||
poetry run pytest \
|
||||
uv run pytest \
|
||||
--basetemp=./tmp/ \
|
||||
src/${{matrix.src}} \
|
||||
--sqlstore-provider ${{matrix.sqlstore-provider}} \
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -222,8 +222,6 @@ cython_debug/
|
||||
#.idea/
|
||||
|
||||
### Python Patch ###
|
||||
# Poetry local configuration file - https://python-poetry.org/docs/configuration/#local-configuration
|
||||
poetry.toml
|
||||
|
||||
# ruff
|
||||
.ruff_cache/
|
||||
|
||||
10
.mockery.yml
Normal file
10
.mockery.yml
Normal file
@@ -0,0 +1,10 @@
|
||||
# Link to template variables: https://pkg.go.dev/github.com/vektra/mockery/v3/config#TemplateData
|
||||
template: testify
|
||||
packages:
|
||||
github.com/SigNoz/signoz/pkg/alertmanager:
|
||||
config:
|
||||
all: true
|
||||
dir: '{{.InterfaceDir}}/mocks'
|
||||
filename: "mocks.go"
|
||||
structname: 'Mock{{.InterfaceName}}'
|
||||
pkgname: '{{.SrcPackageName}}mock'
|
||||
14
Makefile
14
Makefile
@@ -202,25 +202,25 @@ docker-buildx-enterprise: go-build-enterprise js-build
|
||||
##############################################################
|
||||
.PHONY: py-fmt
|
||||
py-fmt: ## Run black for integration tests
|
||||
@cd tests/integration && poetry run black .
|
||||
@cd tests/integration && uv run black .
|
||||
|
||||
.PHONY: py-lint
|
||||
py-lint: ## Run lint for integration tests
|
||||
@cd tests/integration && poetry run isort .
|
||||
@cd tests/integration && poetry run autoflake .
|
||||
@cd tests/integration && poetry run pylint .
|
||||
@cd tests/integration && uv run isort .
|
||||
@cd tests/integration && uv run autoflake .
|
||||
@cd tests/integration && uv run pylint .
|
||||
|
||||
.PHONY: py-test-setup
|
||||
py-test-setup: ## Runs integration tests
|
||||
@cd tests/integration && poetry run pytest --basetemp=./tmp/ -vv --reuse --capture=no src/bootstrap/setup.py::test_setup
|
||||
@cd tests/integration && uv run pytest --basetemp=./tmp/ -vv --reuse --capture=no src/bootstrap/setup.py::test_setup
|
||||
|
||||
.PHONY: py-test-teardown
|
||||
py-test-teardown: ## Runs integration tests with teardown
|
||||
@cd tests/integration && poetry run pytest --basetemp=./tmp/ -vv --teardown --capture=no src/bootstrap/setup.py::test_teardown
|
||||
@cd tests/integration && uv run pytest --basetemp=./tmp/ -vv --teardown --capture=no src/bootstrap/setup.py::test_teardown
|
||||
|
||||
.PHONY: py-test
|
||||
py-test: ## Runs integration tests
|
||||
@cd tests/integration && poetry run pytest --basetemp=./tmp/ -vv --capture=no src/
|
||||
@cd tests/integration && uv run pytest --basetemp=./tmp/ -vv --capture=no src/
|
||||
|
||||
.PHONY: py-clean
|
||||
py-clean: ## Clear all pycache and pytest cache from tests directory recursively
|
||||
|
||||
@@ -9,7 +9,7 @@ SigNoz uses integration tests to verify that different components work together
|
||||
Before running integration tests, ensure you have the following installed:
|
||||
|
||||
- Python 3.13+
|
||||
- Poetry (for dependency management)
|
||||
- [uv](https://docs.astral.sh/uv/getting-started/installation/)
|
||||
- Docker (for containerized services)
|
||||
|
||||
### Initial Setup
|
||||
@@ -19,17 +19,19 @@ Before running integration tests, ensure you have the following installed:
|
||||
cd tests/integration
|
||||
```
|
||||
|
||||
2. Install dependencies using Poetry:
|
||||
2. Install dependencies using uv:
|
||||
```bash
|
||||
poetry install --no-root
|
||||
uv sync
|
||||
```
|
||||
|
||||
> **_NOTE:_** the build backend could throw an error while installing `psycopg2`, pleae see https://www.psycopg.org/docs/install.html#build-prerequisites
|
||||
|
||||
### Starting the Test Environment
|
||||
|
||||
To spin up all the containers necessary for writing integration tests and keep them running:
|
||||
|
||||
```bash
|
||||
poetry run pytest --basetemp=./tmp/ -vv --reuse src/bootstrap/setup.py::test_setup
|
||||
uv run pytest --basetemp=./tmp/ -vv --reuse src/bootstrap/setup.py::test_setup
|
||||
```
|
||||
|
||||
This command will:
|
||||
@@ -42,7 +44,7 @@ This command will:
|
||||
When you're done writing integration tests, clean up the environment:
|
||||
|
||||
```bash
|
||||
poetry run pytest --basetemp=./tmp/ -vv --teardown -s src/bootstrap/setup.py::test_teardown
|
||||
uv run pytest --basetemp=./tmp/ -vv --teardown -s src/bootstrap/setup.py::test_teardown
|
||||
```
|
||||
|
||||
This will destroy the running integration test setup and clean up resources.
|
||||
@@ -72,20 +74,20 @@ Python and pytest form the foundation of the integration testing framework. Test
|
||||
│ ├── sqlite.py
|
||||
│ ├── types.py
|
||||
│ └── zookeeper.py
|
||||
├── poetry.lock
|
||||
├── uv.lock
|
||||
├── pyproject.toml
|
||||
└── src
|
||||
└── bootstrap
|
||||
├── __init__.py
|
||||
├── a_database.py
|
||||
├── b_register.py
|
||||
└── c_license.py
|
||||
├── 01_database.py
|
||||
├── 02_register.py
|
||||
└── 03_license.py
|
||||
```
|
||||
|
||||
Each test suite follows some important principles:
|
||||
|
||||
1. **Organization**: Test suites live under `src/` in self-contained packages. Fixtures (a pytest concept) live inside `fixtures/`.
|
||||
2. **Execution Order**: Files are prefixed with `a_`, `b_`, `c_` to ensure sequential execution.
|
||||
2. **Execution Order**: Files are prefixed with two-digit numbers (`01_`, `02_`, `03_`) to ensure sequential execution.
|
||||
3. **Time Constraints**: Each suite should complete in under 10 minutes (setup takes ~4 mins).
|
||||
|
||||
### Test Suite Design
|
||||
@@ -107,7 +109,7 @@ Other test suites can be **pipelines, auth, querier.**
|
||||
|
||||
## How to write an integration test?
|
||||
|
||||
Now start writing an integration test. Create a new file `src/bootstrap/e_version.py` and paste the following:
|
||||
Now start writing an integration test. Create a new file `src/bootstrap/05_version.py` and paste the following:
|
||||
|
||||
```python
|
||||
import requests
|
||||
@@ -125,7 +127,7 @@ def test_version(signoz: types.SigNoz) -> None:
|
||||
We have written a simple test which calls the `version` endpoint of the container in step 1. In **order to just run this function, run the following command:**
|
||||
|
||||
```bash
|
||||
poetry run pytest --basetemp=./tmp/ -vv --reuse src/bootstrap/e_version.py::test_version
|
||||
uv run pytest --basetemp=./tmp/ -vv --reuse src/bootstrap/05_version.py::test_version
|
||||
```
|
||||
|
||||
> Note: The `--reuse` flag is used to reuse the environment if it is already running. Always use this flag when writing and running integration tests. If you don't use this flag, the environment will be destroyed and recreated every time you run the test.
|
||||
@@ -153,7 +155,7 @@ def test_user_registration(signoz: types.SigNoz) -> None:
|
||||
},
|
||||
timeout=2,
|
||||
)
|
||||
|
||||
|
||||
assert response.status_code == HTTPStatus.OK
|
||||
assert response.json()["setupCompleted"] is True
|
||||
```
|
||||
@@ -163,27 +165,27 @@ def test_user_registration(signoz: types.SigNoz) -> None:
|
||||
### Running All Tests
|
||||
|
||||
```bash
|
||||
poetry run pytest --basetemp=./tmp/ -vv --reuse src/
|
||||
uv run pytest --basetemp=./tmp/ -vv --reuse src/
|
||||
```
|
||||
|
||||
### Running Specific Test Categories
|
||||
|
||||
```bash
|
||||
poetry run pytest --basetemp=./tmp/ -vv --reuse src/<suite>
|
||||
uv run pytest --basetemp=./tmp/ -vv --reuse src/<suite>
|
||||
|
||||
# Run querier tests
|
||||
poetry run pytest --basetemp=./tmp/ -vv --reuse src/querier/
|
||||
uv run pytest --basetemp=./tmp/ -vv --reuse src/querier/
|
||||
# Run auth tests
|
||||
poetry run pytest --basetemp=./tmp/ -vv --reuse src/auth/
|
||||
uv run pytest --basetemp=./tmp/ -vv --reuse src/auth/
|
||||
```
|
||||
|
||||
### Running Individual Tests
|
||||
|
||||
```bash
|
||||
poetry run pytest --basetemp=./tmp/ -vv --reuse src/<suite>/<file>.py::test_name
|
||||
uv run pytest --basetemp=./tmp/ -vv --reuse src/<suite>/<file>.py::test_name
|
||||
|
||||
# Run test_register in file a_register.py in auth suite
|
||||
poetry run pytest --basetemp=./tmp/ -vv --reuse src/auth/a_register.py::test_register
|
||||
# Run test_register in file 01_register.py in passwordauthn suite
|
||||
uv run pytest --basetemp=./tmp/ -vv --reuse src/passwordauthn/01_register.py::test_register
|
||||
```
|
||||
|
||||
## How to configure different options for integration tests?
|
||||
@@ -197,7 +199,7 @@ Tests can be configured using pytest options:
|
||||
|
||||
Example:
|
||||
```bash
|
||||
poetry run pytest --basetemp=./tmp/ -vv --reuse --sqlstore-provider=postgres --postgres-version=14 src/auth/
|
||||
uv run pytest --basetemp=./tmp/ -vv --reuse --sqlstore-provider=postgres --postgres-version=14 src/auth/
|
||||
```
|
||||
|
||||
|
||||
@@ -205,7 +207,7 @@ poetry run pytest --basetemp=./tmp/ -vv --reuse --sqlstore-provider=postgres --p
|
||||
|
||||
- **Always use the `--reuse` flag** when setting up the environment to keep containers running
|
||||
- **Use the `--teardown` flag** when cleaning up to avoid resource leaks
|
||||
- **Follow the naming convention** with alphabetical prefixes for test execution order
|
||||
- **Follow the naming convention** with two-digit numeric prefixes (`01_`, `02_`) for test execution order
|
||||
- **Use proper timeouts** in HTTP requests to avoid hanging tests
|
||||
- **Clean up test data** between tests to avoid interference
|
||||
- **Use descriptive test names** that clearly indicate what is being tested
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/SigNoz/signoz/pkg/factory"
|
||||
"github.com/SigNoz/signoz/pkg/queryparser"
|
||||
"github.com/SigNoz/signoz/pkg/ruler/rulestore/sqlrulestore"
|
||||
"github.com/SigNoz/signoz/pkg/types/telemetrytypes"
|
||||
"go.opentelemetry.io/contrib/instrumentation/github.com/gorilla/mux/otelmux"
|
||||
"go.opentelemetry.io/otel/propagation"
|
||||
|
||||
@@ -104,6 +105,7 @@ func NewServer(config signoz.Config, signoz *signoz.SigNoz) (*Server, error) {
|
||||
signoz.Alertmanager,
|
||||
signoz.SQLStore,
|
||||
signoz.TelemetryStore,
|
||||
signoz.TelemetryMetadataStore,
|
||||
signoz.Prometheus,
|
||||
signoz.Modules.OrgGetter,
|
||||
signoz.Querier,
|
||||
@@ -355,12 +357,13 @@ func (s *Server) Stop(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func makeRulesManager(ch baseint.Reader, cache cache.Cache, alertmanager alertmanager.Alertmanager, sqlstore sqlstore.SQLStore, telemetryStore telemetrystore.TelemetryStore, prometheus prometheus.Prometheus, orgGetter organization.Getter, querier querier.Querier, providerSettings factory.ProviderSettings, queryParser queryparser.QueryParser) (*baserules.Manager, error) {
|
||||
func makeRulesManager(ch baseint.Reader, cache cache.Cache, alertmanager alertmanager.Alertmanager, sqlstore sqlstore.SQLStore, telemetryStore telemetrystore.TelemetryStore, metadataStore telemetrytypes.MetadataStore, prometheus prometheus.Prometheus, orgGetter organization.Getter, querier querier.Querier, providerSettings factory.ProviderSettings, queryParser queryparser.QueryParser) (*baserules.Manager, error) {
|
||||
ruleStore := sqlrulestore.NewRuleStore(sqlstore, queryParser, providerSettings)
|
||||
maintenanceStore := sqlrulestore.NewMaintenanceStore(sqlstore)
|
||||
// create manager opts
|
||||
managerOpts := &baserules.ManagerOptions{
|
||||
TelemetryStore: telemetryStore,
|
||||
MetadataStore: metadataStore,
|
||||
Prometheus: prometheus,
|
||||
Context: context.Background(),
|
||||
Logger: zap.L(),
|
||||
@@ -376,6 +379,7 @@ func makeRulesManager(ch baseint.Reader, cache cache.Cache, alertmanager alertma
|
||||
RuleStore: ruleStore,
|
||||
MaintenanceStore: maintenanceStore,
|
||||
SqlStore: sqlstore,
|
||||
QueryParser: queryParser,
|
||||
}
|
||||
|
||||
// create Manager
|
||||
|
||||
@@ -247,7 +247,8 @@ func (r *AnomalyRule) buildAndRunQuery(ctx context.Context, orgID valuer.UUID, t
|
||||
}
|
||||
}
|
||||
results, err := r.Threshold.Eval(*series, r.Unit(), ruletypes.EvalData{
|
||||
ActiveAlerts: r.ActiveAlertsLabelFP(),
|
||||
ActiveAlerts: r.ActiveAlertsLabelFP(),
|
||||
SendUnmatched: r.ShouldSendUnmatched(),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -291,7 +292,19 @@ func (r *AnomalyRule) buildAndRunQueryV5(ctx context.Context, orgID valuer.UUID,
|
||||
scoresJSON, _ := json.Marshal(queryResult.AnomalyScores)
|
||||
r.logger.InfoContext(ctx, "anomaly scores", "scores", string(scoresJSON))
|
||||
|
||||
for _, series := range queryResult.AnomalyScores {
|
||||
// Filter out new series if newGroupEvalDelay is configured
|
||||
seriesToProcess := queryResult.AnomalyScores
|
||||
if r.ShouldSkipNewGroups() {
|
||||
filteredSeries, filterErr := r.BaseRule.FilterNewSeries(ctx, ts, seriesToProcess)
|
||||
// In case of error we log the error and continue with the original series
|
||||
if filterErr != nil {
|
||||
r.logger.ErrorContext(ctx, "Error filtering new series, ", "error", filterErr, "rule_name", r.Name())
|
||||
} else {
|
||||
seriesToProcess = filteredSeries
|
||||
}
|
||||
}
|
||||
|
||||
for _, series := range seriesToProcess {
|
||||
if r.Condition().RequireMinPoints {
|
||||
if len(series.Points) < r.Condition().RequiredNumPoints {
|
||||
r.logger.InfoContext(ctx, "not enough data points to evaluate series, skipping", "ruleid", r.ID(), "numPoints", len(series.Points), "requiredPoints", r.Condition().RequiredNumPoints)
|
||||
@@ -299,7 +312,8 @@ func (r *AnomalyRule) buildAndRunQueryV5(ctx context.Context, orgID valuer.UUID,
|
||||
}
|
||||
}
|
||||
results, err := r.Threshold.Eval(*series, r.Unit(), ruletypes.EvalData{
|
||||
ActiveAlerts: r.ActiveAlertsLabelFP(),
|
||||
ActiveAlerts: r.ActiveAlertsLabelFP(),
|
||||
SendUnmatched: r.ShouldSendUnmatched(),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -37,6 +37,8 @@ func PrepareTaskFunc(opts baserules.PrepareTaskOptions) (baserules.Task, error)
|
||||
opts.SLogger,
|
||||
baserules.WithEvalDelay(opts.ManagerOpts.EvalDelay),
|
||||
baserules.WithSQLStore(opts.SQLStore),
|
||||
baserules.WithQueryParser(opts.ManagerOpts.QueryParser),
|
||||
baserules.WithMetadataStore(opts.ManagerOpts.MetadataStore),
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
@@ -59,6 +61,8 @@ func PrepareTaskFunc(opts baserules.PrepareTaskOptions) (baserules.Task, error)
|
||||
opts.Reader,
|
||||
opts.ManagerOpts.Prometheus,
|
||||
baserules.WithSQLStore(opts.SQLStore),
|
||||
baserules.WithQueryParser(opts.ManagerOpts.QueryParser),
|
||||
baserules.WithMetadataStore(opts.ManagerOpts.MetadataStore),
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
@@ -82,6 +86,8 @@ func PrepareTaskFunc(opts baserules.PrepareTaskOptions) (baserules.Task, error)
|
||||
opts.Cache,
|
||||
baserules.WithEvalDelay(opts.ManagerOpts.EvalDelay),
|
||||
baserules.WithSQLStore(opts.SQLStore),
|
||||
baserules.WithQueryParser(opts.ManagerOpts.QueryParser),
|
||||
baserules.WithMetadataStore(opts.ManagerOpts.MetadataStore),
|
||||
)
|
||||
if err != nil {
|
||||
return task, err
|
||||
@@ -140,6 +146,8 @@ func TestNotification(opts baserules.PrepareTestRuleOptions) (int, *basemodel.Ap
|
||||
baserules.WithSendAlways(),
|
||||
baserules.WithSendUnmatched(),
|
||||
baserules.WithSQLStore(opts.SQLStore),
|
||||
baserules.WithQueryParser(opts.ManagerOpts.QueryParser),
|
||||
baserules.WithMetadataStore(opts.ManagerOpts.MetadataStore),
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
@@ -160,6 +168,8 @@ func TestNotification(opts baserules.PrepareTestRuleOptions) (int, *basemodel.Ap
|
||||
baserules.WithSendAlways(),
|
||||
baserules.WithSendUnmatched(),
|
||||
baserules.WithSQLStore(opts.SQLStore),
|
||||
baserules.WithQueryParser(opts.ManagerOpts.QueryParser),
|
||||
baserules.WithMetadataStore(opts.ManagerOpts.MetadataStore),
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
@@ -179,6 +189,8 @@ func TestNotification(opts baserules.PrepareTestRuleOptions) (int, *basemodel.Ap
|
||||
baserules.WithSendAlways(),
|
||||
baserules.WithSendUnmatched(),
|
||||
baserules.WithSQLStore(opts.SQLStore),
|
||||
baserules.WithQueryParser(opts.ManagerOpts.QueryParser),
|
||||
baserules.WithMetadataStore(opts.ManagerOpts.MetadataStore),
|
||||
)
|
||||
if err != nil {
|
||||
zap.L().Error("failed to prepare a new anomaly rule for test", zap.String("name", alertname), zap.Error(err))
|
||||
|
||||
283
ee/query-service/rules/manager_test.go
Normal file
283
ee/query-service/rules/manager_test.go
Normal file
@@ -0,0 +1,283 @@
|
||||
package rules
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"math"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/alertmanager"
|
||||
alertmanagermock "github.com/SigNoz/signoz/pkg/alertmanager/mocks"
|
||||
"github.com/SigNoz/signoz/pkg/instrumentation/instrumentationtest"
|
||||
"github.com/SigNoz/signoz/pkg/prometheus"
|
||||
"github.com/SigNoz/signoz/pkg/prometheus/prometheustest"
|
||||
"github.com/SigNoz/signoz/pkg/query-service/rules"
|
||||
"github.com/SigNoz/signoz/pkg/sqlstore"
|
||||
"github.com/SigNoz/signoz/pkg/sqlstore/sqlstoretest"
|
||||
"github.com/SigNoz/signoz/pkg/telemetrystore"
|
||||
"github.com/SigNoz/signoz/pkg/telemetrystore/telemetrystoretest"
|
||||
"github.com/SigNoz/signoz/pkg/types/alertmanagertypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/metrictypes"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
cmock "github.com/srikanthccv/ClickHouse-go-mock"
|
||||
)
|
||||
|
||||
func TestManager_TestNotification_SendUnmatched_ThresholdRule(t *testing.T) {
|
||||
target := 10.0
|
||||
recovery := 5.0
|
||||
|
||||
for _, tc := range rules.TcTestNotiSendUnmatchedThresholdRule {
|
||||
t.Run(tc.Name, func(t *testing.T) {
|
||||
rule := rules.ThresholdRuleAtLeastOnceValueAbove(target, &recovery)
|
||||
|
||||
// Marshal rule to JSON as TestNotification expects
|
||||
ruleBytes, err := json.Marshal(rule)
|
||||
require.NoError(t, err)
|
||||
|
||||
orgID := valuer.GenerateUUID()
|
||||
|
||||
// for saving temp alerts that are triggered via TestNotification
|
||||
triggeredTestAlerts := []map[*alertmanagertypes.PostableAlert][]string{}
|
||||
|
||||
// Create manager using test factory with hooks
|
||||
mgr := rules.NewTestManager(t, &rules.TestManagerOptions{
|
||||
AlertmanagerHook: func(am alertmanager.Alertmanager) {
|
||||
fAlert := am.(*alertmanagermock.MockAlertmanager)
|
||||
// mock set notification config
|
||||
fAlert.On("SetNotificationConfig", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil)
|
||||
// for saving temp alerts that are triggered via TestNotification
|
||||
if tc.ExpectAlerts > 0 {
|
||||
fAlert.On("TestAlert", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Run(func(args mock.Arguments) {
|
||||
triggeredTestAlerts = append(triggeredTestAlerts, args.Get(3).(map[*alertmanagertypes.PostableAlert][]string))
|
||||
}).Return(nil).Times(tc.ExpectAlerts)
|
||||
}
|
||||
},
|
||||
ManagerOptionsHook: func(opts *rules.ManagerOptions) {
|
||||
opts.PrepareTestRuleFunc = TestNotification
|
||||
},
|
||||
SqlStoreHook: func(store sqlstore.SQLStore) {
|
||||
mockStore := store.(*sqlstoretest.Provider)
|
||||
// Mock the organizations query that SendAlerts makes
|
||||
// Bun generates: SELECT id FROM organizations LIMIT 1 (or SELECT "id" FROM "organizations" LIMIT 1)
|
||||
orgRows := mockStore.Mock().NewRows([]string{"id"}).AddRow(orgID.StringValue())
|
||||
// Match bun's generated query pattern - bun may quote identifiers
|
||||
mockStore.Mock().ExpectQuery("SELECT (.+) FROM (.+)organizations(.+) LIMIT (.+)").WillReturnRows(orgRows)
|
||||
},
|
||||
TelemetryStoreHook: func(store telemetrystore.TelemetryStore) {
|
||||
telemetryStore := store.(*telemetrystoretest.Provider)
|
||||
// Set up mock data for telemetry store
|
||||
cols := make([]cmock.ColumnType, 0)
|
||||
cols = append(cols, cmock.ColumnType{Name: "value", Type: "Float64"})
|
||||
cols = append(cols, cmock.ColumnType{Name: "attr", Type: "String"})
|
||||
cols = append(cols, cmock.ColumnType{Name: "ts", Type: "DateTime"})
|
||||
|
||||
alertDataRows := cmock.NewRows(cols, tc.Values)
|
||||
|
||||
mock := telemetryStore.Mock()
|
||||
|
||||
// Generate query arguments for the metric query
|
||||
evalTime := time.Now().UTC()
|
||||
evalWindow := 5 * time.Minute
|
||||
evalDelay := time.Duration(0)
|
||||
queryArgs := rules.GenerateMetricQueryCHArgs(
|
||||
evalTime,
|
||||
evalWindow,
|
||||
evalDelay,
|
||||
"probe_success",
|
||||
metrictypes.Unspecified,
|
||||
)
|
||||
|
||||
mock.ExpectQuery("*WITH __temporal_aggregation_cte*").
|
||||
WithArgs(queryArgs...).
|
||||
WillReturnRows(alertDataRows)
|
||||
},
|
||||
})
|
||||
|
||||
count, apiErr := mgr.TestNotification(context.Background(), orgID, string(ruleBytes))
|
||||
if apiErr != nil {
|
||||
t.Logf("TestNotification error: %v, type: %s", apiErr.Err, apiErr.Typ)
|
||||
}
|
||||
require.Nil(t, apiErr)
|
||||
assert.Equal(t, tc.ExpectAlerts, count)
|
||||
|
||||
if tc.ExpectAlerts > 0 {
|
||||
// check if the alert has been triggered
|
||||
require.Len(t, triggeredTestAlerts, 1)
|
||||
var gotAlerts []*alertmanagertypes.PostableAlert
|
||||
for a := range triggeredTestAlerts[0] {
|
||||
gotAlerts = append(gotAlerts, a)
|
||||
}
|
||||
require.Len(t, gotAlerts, tc.ExpectAlerts)
|
||||
// check if the alert has triggered with correct threshold value
|
||||
if tc.ExpectValue != 0 {
|
||||
assert.Equal(t, strconv.FormatFloat(tc.ExpectValue, 'f', -1, 64), gotAlerts[0].Annotations["value"])
|
||||
}
|
||||
} else {
|
||||
// check if no alerts have been triggered
|
||||
assert.Empty(t, triggeredTestAlerts)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestManager_TestNotification_SendUnmatched_PromRule(t *testing.T) {
|
||||
target := 10.0
|
||||
|
||||
for _, tc := range rules.TcTestNotificationSendUnmatchedPromRule {
|
||||
t.Run(tc.Name, func(t *testing.T) {
|
||||
// Capture base time once per test case to ensure consistent timestamps
|
||||
baseTime := time.Now().UTC()
|
||||
|
||||
rule := rules.BuildPromAtLeastOnceValueAbove(target, nil)
|
||||
|
||||
// Marshal rule to JSON as TestNotification expects
|
||||
ruleBytes, err := json.Marshal(rule)
|
||||
require.NoError(t, err)
|
||||
|
||||
orgID := valuer.GenerateUUID()
|
||||
|
||||
// for saving temp alerts that are triggered via TestNotification
|
||||
triggeredTestAlerts := []map[*alertmanagertypes.PostableAlert][]string{}
|
||||
|
||||
// Variable to store promProvider for cleanup
|
||||
var promProvider *prometheustest.Provider
|
||||
|
||||
// Create manager using test factory with hooks
|
||||
mgr := rules.NewTestManager(t, &rules.TestManagerOptions{
|
||||
AlertmanagerHook: func(am alertmanager.Alertmanager) {
|
||||
mockAM := am.(*alertmanagermock.MockAlertmanager)
|
||||
// mock set notification config
|
||||
mockAM.On("SetNotificationConfig", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil)
|
||||
// for saving temp alerts that are triggered via TestNotification
|
||||
if tc.ExpectAlerts > 0 {
|
||||
mockAM.On("TestAlert", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Run(func(args mock.Arguments) {
|
||||
triggeredTestAlerts = append(triggeredTestAlerts, args.Get(3).(map[*alertmanagertypes.PostableAlert][]string))
|
||||
}).Return(nil).Times(tc.ExpectAlerts)
|
||||
}
|
||||
},
|
||||
SqlStoreHook: func(store sqlstore.SQLStore) {
|
||||
mockStore := store.(*sqlstoretest.Provider)
|
||||
// Mock the organizations query that SendAlerts makes
|
||||
orgRows := mockStore.Mock().NewRows([]string{"id"}).AddRow(orgID.StringValue())
|
||||
mockStore.Mock().ExpectQuery("SELECT (.+) FROM (.+)organizations(.+) LIMIT (.+)").WillReturnRows(orgRows)
|
||||
},
|
||||
TelemetryStoreHook: func(store telemetrystore.TelemetryStore) {
|
||||
mockStore := store.(*telemetrystoretest.Provider)
|
||||
|
||||
// Set up Prometheus-specific mock data
|
||||
// Fingerprint columns for Prometheus queries
|
||||
fingerprintCols := []cmock.ColumnType{
|
||||
{Name: "fingerprint", Type: "UInt64"},
|
||||
{Name: "any(labels)", Type: "String"},
|
||||
}
|
||||
|
||||
// Samples columns for Prometheus queries
|
||||
samplesCols := []cmock.ColumnType{
|
||||
{Name: "metric_name", Type: "String"},
|
||||
{Name: "fingerprint", Type: "UInt64"},
|
||||
{Name: "unix_milli", Type: "Int64"},
|
||||
{Name: "value", Type: "Float64"},
|
||||
{Name: "flags", Type: "UInt32"},
|
||||
}
|
||||
|
||||
// Calculate query time range similar to Prometheus rule tests
|
||||
// TestNotification uses time.Now().UTC() for evaluation
|
||||
// We calculate the query window based on current time to match what the actual evaluation will use
|
||||
evalTime := baseTime
|
||||
evalWindowMs := int64(5 * 60 * 1000) // 5 minutes in ms
|
||||
evalTimeMs := evalTime.UnixMilli()
|
||||
queryStart := ((evalTimeMs-2*evalWindowMs)/60000)*60000 + 1 // truncate to minute + 1ms
|
||||
queryEnd := (evalTimeMs / 60000) * 60000 // truncate to minute
|
||||
|
||||
// Create fingerprint data
|
||||
fingerprint := uint64(12345)
|
||||
labelsJSON := `{"__name__":"test_metric"}`
|
||||
fingerprintData := [][]interface{}{
|
||||
{fingerprint, labelsJSON},
|
||||
}
|
||||
fingerprintRows := cmock.NewRows(fingerprintCols, fingerprintData)
|
||||
|
||||
// Create samples data from test case values, calculating timestamps relative to baseTime
|
||||
validSamplesData := make([][]interface{}, 0)
|
||||
for _, v := range tc.Values {
|
||||
// Skip NaN and Inf values in the samples data
|
||||
if math.IsNaN(v.Value) || math.IsInf(v.Value, 0) {
|
||||
continue
|
||||
}
|
||||
// Calculate timestamp relative to baseTime
|
||||
sampleTimestamp := baseTime.Add(v.Offset).UnixMilli()
|
||||
validSamplesData = append(validSamplesData, []interface{}{
|
||||
"test_metric",
|
||||
fingerprint,
|
||||
sampleTimestamp,
|
||||
v.Value,
|
||||
uint32(0), // flags - 0 means normal value
|
||||
})
|
||||
}
|
||||
samplesRows := cmock.NewRows(samplesCols, validSamplesData)
|
||||
|
||||
mock := mockStore.Mock()
|
||||
|
||||
// Mock the fingerprint query (for Prometheus label matching)
|
||||
mock.ExpectQuery("SELECT fingerprint, any").
|
||||
WithArgs("test_metric", "__name__", "test_metric").
|
||||
WillReturnRows(fingerprintRows)
|
||||
|
||||
// Mock the samples query (for Prometheus metric data)
|
||||
mock.ExpectQuery("SELECT metric_name, fingerprint, unix_milli").
|
||||
WithArgs(
|
||||
"test_metric",
|
||||
"test_metric",
|
||||
"__name__",
|
||||
"test_metric",
|
||||
queryStart,
|
||||
queryEnd,
|
||||
).
|
||||
WillReturnRows(samplesRows)
|
||||
|
||||
// Create Prometheus provider for this test
|
||||
promProvider = prometheustest.New(context.Background(), instrumentationtest.New().ToProviderSettings(), prometheus.Config{}, store)
|
||||
},
|
||||
ManagerOptionsHook: func(opts *rules.ManagerOptions) {
|
||||
// Set Prometheus provider for PromQL queries
|
||||
if promProvider != nil {
|
||||
opts.Prometheus = promProvider
|
||||
}
|
||||
opts.PrepareTestRuleFunc = TestNotification
|
||||
},
|
||||
})
|
||||
|
||||
count, apiErr := mgr.TestNotification(context.Background(), orgID, string(ruleBytes))
|
||||
if apiErr != nil {
|
||||
t.Logf("TestNotification error: %v, type: %s", apiErr.Err, apiErr.Typ)
|
||||
}
|
||||
require.Nil(t, apiErr)
|
||||
assert.Equal(t, tc.ExpectAlerts, count)
|
||||
|
||||
if tc.ExpectAlerts > 0 {
|
||||
// check if the alert has been triggered
|
||||
require.Len(t, triggeredTestAlerts, 1)
|
||||
var gotAlerts []*alertmanagertypes.PostableAlert
|
||||
for a := range triggeredTestAlerts[0] {
|
||||
gotAlerts = append(gotAlerts, a)
|
||||
}
|
||||
require.Len(t, gotAlerts, tc.ExpectAlerts)
|
||||
// check if the alert has triggered with correct threshold value
|
||||
if tc.ExpectValue != 0 && !math.IsNaN(tc.ExpectValue) && !math.IsInf(tc.ExpectValue, 0) {
|
||||
assert.Equal(t, strconv.FormatFloat(tc.ExpectValue, 'f', -1, 64), gotAlerts[0].Annotations["value"])
|
||||
}
|
||||
} else {
|
||||
// check if no alerts have been triggered
|
||||
assert.Empty(t, triggeredTestAlerts)
|
||||
}
|
||||
|
||||
promProvider.Close()
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -45,6 +45,7 @@
|
||||
"DEFAULT": "Open source Observability Platform | SigNoz",
|
||||
"ALERT_HISTORY": "SigNoz | Alert Rule History",
|
||||
"ALERT_OVERVIEW": "SigNoz | Alert Rule Overview",
|
||||
"ALERT_TYPE_SELECTION": "SigNoz | Select Alert Type",
|
||||
"INFRASTRUCTURE_MONITORING_HOSTS": "SigNoz | Infra Monitoring",
|
||||
"INFRASTRUCTURE_MONITORING_KUBERNETES": "SigNoz | Infra Monitoring",
|
||||
"METER_EXPLORER": "SigNoz | Meter Explorer",
|
||||
|
||||
@@ -93,13 +93,15 @@ export const OnboardingV2 = Loadable(
|
||||
() => import(/* webpackChunkName: "Onboarding V2" */ 'pages/OnboardingPageV2'),
|
||||
);
|
||||
|
||||
export const DashboardPage = Loadable(
|
||||
export const DashboardsListPage = Loadable(
|
||||
() =>
|
||||
import(/* webpackChunkName: "DashboardPage" */ 'pages/DashboardsListPage'),
|
||||
import(
|
||||
/* webpackChunkName: "DashboardsListPage" */ 'pages/DashboardsListPage'
|
||||
),
|
||||
);
|
||||
|
||||
export const NewDashboardPage = Loadable(
|
||||
() => import(/* webpackChunkName: "New DashboardPage" */ 'pages/NewDashboard'),
|
||||
export const DashboardPage = Loadable(
|
||||
() => import(/* webpackChunkName: "DashboardPage" */ 'pages/DashboardPage'),
|
||||
);
|
||||
|
||||
export const DashboardWidget = Loadable(
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import ROUTES from 'constants/routes';
|
||||
import AlertTypeSelectionPage from 'pages/AlertTypeSelection';
|
||||
import MessagingQueues from 'pages/MessagingQueues';
|
||||
import MeterExplorer from 'pages/MeterExplorer';
|
||||
import { RouteProps } from 'react-router-dom';
|
||||
@@ -12,6 +13,7 @@ import {
|
||||
CreateAlertChannelAlerts,
|
||||
CreateNewAlerts,
|
||||
DashboardPage,
|
||||
DashboardsListPage,
|
||||
DashboardWidget,
|
||||
EditRulesPage,
|
||||
ErrorDetails,
|
||||
@@ -27,7 +29,6 @@ import {
|
||||
LogsIndexToFields,
|
||||
LogsSaveViews,
|
||||
MetricsExplorer,
|
||||
NewDashboardPage,
|
||||
OldLogsExplorer,
|
||||
Onboarding,
|
||||
OnboardingV2,
|
||||
@@ -159,14 +160,14 @@ const routes: AppRoutes[] = [
|
||||
{
|
||||
path: ROUTES.ALL_DASHBOARD,
|
||||
exact: true,
|
||||
component: DashboardPage,
|
||||
component: DashboardsListPage,
|
||||
isPrivate: true,
|
||||
key: 'ALL_DASHBOARD',
|
||||
},
|
||||
{
|
||||
path: ROUTES.DASHBOARD,
|
||||
exact: true,
|
||||
component: NewDashboardPage,
|
||||
component: DashboardPage,
|
||||
isPrivate: true,
|
||||
key: 'DASHBOARD',
|
||||
},
|
||||
@@ -198,6 +199,13 @@ const routes: AppRoutes[] = [
|
||||
isPrivate: true,
|
||||
key: 'LIST_ALL_ALERT',
|
||||
},
|
||||
{
|
||||
path: ROUTES.ALERT_TYPE_SELECTION,
|
||||
exact: true,
|
||||
component: AlertTypeSelectionPage,
|
||||
isPrivate: true,
|
||||
key: 'ALERT_TYPE_SELECTION',
|
||||
},
|
||||
{
|
||||
path: ROUTES.ALERTS_NEW,
|
||||
exact: true,
|
||||
|
||||
@@ -16,7 +16,7 @@ import {
|
||||
QueryRangePayloadV5,
|
||||
} from 'types/api/v5/queryRange';
|
||||
import { EQueryType } from 'types/common/dashboard';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
import { DataSource, ReduceOperators } from 'types/common/queryBuilder';
|
||||
import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
|
||||
import { prepareQueryRangePayloadV5 } from './prepareQueryRangePayloadV5';
|
||||
@@ -41,7 +41,7 @@ describe('prepareQueryRangePayloadV5', () => {
|
||||
temporality: '',
|
||||
timeAggregation: 'sum',
|
||||
spaceAggregation: 'avg',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
},
|
||||
],
|
||||
timeAggregation: 'sum',
|
||||
@@ -62,7 +62,7 @@ describe('prepareQueryRangePayloadV5', () => {
|
||||
limit: null,
|
||||
stepInterval: 600,
|
||||
orderBy: [],
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
legend: 'Legend A',
|
||||
...overrides,
|
||||
});
|
||||
@@ -416,7 +416,7 @@ describe('prepareQueryRangePayloadV5', () => {
|
||||
metricName: 'cpu_usage',
|
||||
timeAggregation: 'sum',
|
||||
spaceAggregation: 'avg',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
temporality: undefined,
|
||||
}),
|
||||
],
|
||||
@@ -569,7 +569,7 @@ describe('prepareQueryRangePayloadV5', () => {
|
||||
},
|
||||
],
|
||||
legend: '{{service.name}}',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
offset: 0,
|
||||
pageSize: 100,
|
||||
},
|
||||
|
||||
@@ -4,7 +4,7 @@ import { getWidgetQueryBuilder } from 'container/MetricsApplication/MetricsAppli
|
||||
import { getWidgetQuery } from 'pages/MessagingQueues/MQDetails/MetricPage/MetricPageUtil';
|
||||
import { Widgets } from 'types/api/dashboard/getAll';
|
||||
import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
import { DataSource, ReduceOperators } from 'types/common/queryBuilder';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
// dynamic step interval
|
||||
@@ -57,7 +57,7 @@ export const celeryAllStateWidgetData = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: getStepInterval(startTime, endTime),
|
||||
timeAggregation: 'rate',
|
||||
@@ -121,7 +121,7 @@ export const celeryRetryStateWidgetData = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: getStepInterval(startTime, endTime),
|
||||
timeAggregation: 'count',
|
||||
@@ -181,7 +181,7 @@ export const celeryFailedStateWidgetData = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: getStepInterval(startTime, endTime),
|
||||
timeAggregation: 'rate',
|
||||
@@ -241,7 +241,7 @@ export const celerySuccessStateWidgetData = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: getStepInterval(startTime, endTime),
|
||||
timeAggregation: 'rate',
|
||||
@@ -288,7 +288,7 @@ export const celeryTasksByWorkerWidgetData = (
|
||||
limit: 10,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: getStepInterval(startTime, endTime),
|
||||
timeAggregation: 'rate',
|
||||
@@ -351,7 +351,7 @@ export const celeryErrorByWorkerWidgetData = (
|
||||
},
|
||||
],
|
||||
legend: '',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
},
|
||||
{
|
||||
dataSource: 'traces',
|
||||
@@ -385,7 +385,7 @@ export const celeryErrorByWorkerWidgetData = (
|
||||
},
|
||||
],
|
||||
legend: '',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
},
|
||||
{
|
||||
queryName: 'F1',
|
||||
@@ -436,7 +436,7 @@ export const celeryLatencyByWorkerWidgetData = (
|
||||
limit: 10,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: getStepInterval(startTime, endTime),
|
||||
timeAggregation: 'p99',
|
||||
@@ -485,7 +485,7 @@ export const celeryActiveTasksWidgetData = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'avg',
|
||||
stepInterval: getStepInterval(startTime, endTime),
|
||||
timeAggregation: 'latest',
|
||||
@@ -539,7 +539,7 @@ export const celeryTaskLatencyWidgetData = (
|
||||
},
|
||||
],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: getStepInterval(startTime, endTime),
|
||||
timeAggregation: type || 'p99',
|
||||
@@ -590,7 +590,7 @@ export const celerySlowestTasksTableWidgetData = getWidgetQueryBuilder(
|
||||
},
|
||||
],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -652,7 +652,7 @@ export const celeryRetryTasksTableWidgetData = getWidgetQueryBuilder(
|
||||
},
|
||||
],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -715,7 +715,7 @@ export const celeryFailedTasksTableWidgetData = getWidgetQueryBuilder(
|
||||
},
|
||||
],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -776,7 +776,7 @@ export const celerySuccessTasksTableWidgetData = getWidgetQueryBuilder(
|
||||
},
|
||||
],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -838,7 +838,7 @@ export const celeryTimeSeriesTablesWidgetData = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -877,7 +877,7 @@ export const celeryAllStateCountWidgetData = getWidgetQueryBuilder(
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'last',
|
||||
reduceTo: ReduceOperators.LAST,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'count_distinct',
|
||||
@@ -926,7 +926,7 @@ export const celerySuccessStateCountWidgetData = getWidgetQueryBuilder(
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'last',
|
||||
reduceTo: ReduceOperators.LAST,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'count_distinct',
|
||||
@@ -975,7 +975,7 @@ export const celeryFailedStateCountWidgetData = getWidgetQueryBuilder(
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'last',
|
||||
reduceTo: ReduceOperators.LAST,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'count_distinct',
|
||||
@@ -1024,7 +1024,7 @@ export const celeryRetryStateCountWidgetData = getWidgetQueryBuilder(
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'last',
|
||||
reduceTo: ReduceOperators.LAST,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'count_distinct',
|
||||
|
||||
@@ -98,7 +98,20 @@ function ClientSideQBSearch(
|
||||
const [isOpen, setIsOpen] = useState<boolean>(false);
|
||||
|
||||
// create the tags from the initial query here, this should only be computed on the first load as post that tags and query will be always in sync.
|
||||
const [tags, setTags] = useState<ITag[]>(filters.items as ITag[]);
|
||||
const [tags, setTags] = useState<ITag[]>(() => {
|
||||
const currentTags: ITag[] = [];
|
||||
filters.items.forEach((item) => {
|
||||
if (item.key) {
|
||||
currentTags.push({
|
||||
id: item.id,
|
||||
key: item.key,
|
||||
op: item.op,
|
||||
value: item.value,
|
||||
});
|
||||
}
|
||||
});
|
||||
return currentTags;
|
||||
});
|
||||
|
||||
// this will maintain the current state of in process filter item
|
||||
const [currentFilterItem, setCurrentFilterItem] = useState<ITag | undefined>();
|
||||
@@ -143,14 +156,17 @@ function ClientSideQBSearch(
|
||||
setSearchValue((parsedValue as BaseAutocompleteData)?.key);
|
||||
} else if (currentState === DropdownState.OPERATOR) {
|
||||
if (value === OPERATORS.EXISTS || value === OPERATORS.NOT_EXISTS) {
|
||||
setTags((prev) => [
|
||||
...prev,
|
||||
{
|
||||
key: currentFilterItem?.key,
|
||||
op: value,
|
||||
value: '',
|
||||
} as ITag,
|
||||
]);
|
||||
setTags((prev) => {
|
||||
const newTags = [...prev];
|
||||
if (currentFilterItem?.key) {
|
||||
newTags.push({
|
||||
key: currentFilterItem.key,
|
||||
op: value,
|
||||
value: '',
|
||||
});
|
||||
}
|
||||
return newTags;
|
||||
});
|
||||
setCurrentFilterItem(undefined);
|
||||
setSearchValue('');
|
||||
setCurrentState(DropdownState.ATTRIBUTE_KEY);
|
||||
@@ -176,14 +192,17 @@ function ClientSideQBSearch(
|
||||
setSearchValue('');
|
||||
setCurrentState(DropdownState.ATTRIBUTE_KEY);
|
||||
setCurrentFilterItem(undefined);
|
||||
setTags((prev) => [
|
||||
...prev,
|
||||
{
|
||||
key: currentFilterItem?.key,
|
||||
op: currentFilterItem?.op,
|
||||
value: tagValue,
|
||||
} as ITag,
|
||||
]);
|
||||
setTags((prev) => {
|
||||
const newTags = [...prev];
|
||||
if (currentFilterItem?.key) {
|
||||
newTags.push({
|
||||
key: currentFilterItem.key,
|
||||
op: currentFilterItem?.op,
|
||||
value: tagValue,
|
||||
});
|
||||
}
|
||||
return newTags;
|
||||
});
|
||||
return;
|
||||
}
|
||||
// this is for adding subsequent comma seperated values
|
||||
@@ -195,14 +214,17 @@ function ClientSideQBSearch(
|
||||
setSearchValue('');
|
||||
setCurrentState(DropdownState.ATTRIBUTE_KEY);
|
||||
setCurrentFilterItem(undefined);
|
||||
setTags((prev) => [
|
||||
...prev,
|
||||
{
|
||||
key: currentFilterItem?.key,
|
||||
op: currentFilterItem?.op,
|
||||
value,
|
||||
} as ITag,
|
||||
]);
|
||||
setTags((prev) => {
|
||||
const newTags = [...prev];
|
||||
if (currentFilterItem?.key) {
|
||||
newTags.push({
|
||||
key: currentFilterItem?.key,
|
||||
op: currentFilterItem?.op,
|
||||
value,
|
||||
});
|
||||
}
|
||||
return newTags;
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -255,14 +277,17 @@ function ClientSideQBSearch(
|
||||
currentFilterItem?.op === OPERATORS.NOT_EXISTS
|
||||
) {
|
||||
// is exists and not exists operator is present then convert directly to tag! no need of value here
|
||||
setTags((prev) => [
|
||||
...prev,
|
||||
{
|
||||
key: currentFilterItem?.key,
|
||||
op: currentFilterItem?.op,
|
||||
value: '',
|
||||
},
|
||||
]);
|
||||
setTags((prev) => {
|
||||
const newTags = [...prev];
|
||||
if (currentFilterItem?.key) {
|
||||
newTags.push({
|
||||
key: currentFilterItem.key,
|
||||
op: currentFilterItem.op,
|
||||
value: '',
|
||||
});
|
||||
}
|
||||
return newTags;
|
||||
});
|
||||
setCurrentFilterItem(undefined);
|
||||
setSearchValue('');
|
||||
setCurrentState(DropdownState.ATTRIBUTE_KEY);
|
||||
@@ -274,23 +299,25 @@ function ClientSideQBSearch(
|
||||
: 1,
|
||||
)
|
||||
) {
|
||||
setTags((prev) => [
|
||||
...prev,
|
||||
{
|
||||
key: currentFilterItem?.key as BaseAutocompleteData,
|
||||
op: currentFilterItem?.op as string,
|
||||
value: currentFilterItem?.value || '',
|
||||
},
|
||||
]);
|
||||
setTags((prev) => {
|
||||
const newTags = [...prev];
|
||||
if (currentFilterItem) {
|
||||
const newTag = {
|
||||
key: currentFilterItem?.key,
|
||||
op: currentFilterItem?.op,
|
||||
value: currentFilterItem?.value,
|
||||
};
|
||||
newTags.push(newTag);
|
||||
}
|
||||
return newTags;
|
||||
});
|
||||
setCurrentFilterItem(undefined);
|
||||
setSearchValue('');
|
||||
setCurrentState(DropdownState.ATTRIBUTE_KEY);
|
||||
}
|
||||
}
|
||||
}, [
|
||||
currentFilterItem?.key,
|
||||
currentFilterItem?.op,
|
||||
currentFilterItem?.value,
|
||||
currentFilterItem,
|
||||
searchValue,
|
||||
whereClauseConfig?.customKey,
|
||||
whereClauseConfig?.customOp,
|
||||
@@ -321,14 +348,17 @@ function ClientSideQBSearch(
|
||||
tagOperator === OPERATORS.EXISTS ||
|
||||
tagOperator === OPERATORS.NOT_EXISTS
|
||||
) {
|
||||
setTags((prev) => [
|
||||
...prev,
|
||||
{
|
||||
key: currentFilterItem?.key,
|
||||
op: tagOperator,
|
||||
value: '',
|
||||
} as ITag,
|
||||
]);
|
||||
setTags((prev) => {
|
||||
const newTags = [...prev];
|
||||
if (currentFilterItem?.key) {
|
||||
newTags.push({
|
||||
key: currentFilterItem.key,
|
||||
op: tagOperator,
|
||||
value: '',
|
||||
});
|
||||
}
|
||||
return newTags;
|
||||
});
|
||||
setCurrentFilterItem(undefined);
|
||||
setSearchValue('');
|
||||
setCurrentState(DropdownState.ATTRIBUTE_KEY);
|
||||
@@ -498,12 +528,18 @@ function ClientSideQBSearch(
|
||||
|
||||
if (!isEqual(filters, filterTags)) {
|
||||
onChange(filterTags);
|
||||
setTags(
|
||||
filterTags.items.map((tag) => ({
|
||||
...tag,
|
||||
op: getOperatorFromValue(tag.op),
|
||||
})) as ITag[],
|
||||
);
|
||||
const newTags: ITag[] = [];
|
||||
filterTags.items.forEach((tag) => {
|
||||
if (tag.key) {
|
||||
newTags.push({
|
||||
id: tag.id,
|
||||
key: tag.key,
|
||||
op: getOperatorFromValue(tag.op),
|
||||
value: tag.value,
|
||||
});
|
||||
}
|
||||
});
|
||||
setTags(newTags);
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [tags]);
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
} from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData';
|
||||
import { EQueryType } from 'types/common/dashboard';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
import { DataSource, ReduceOperators } from 'types/common/queryBuilder';
|
||||
import { nanoToMilli } from 'utils/timeUtils';
|
||||
|
||||
export const columns = [
|
||||
@@ -121,7 +121,7 @@ export const getHostTracesQueryPayload = (
|
||||
],
|
||||
groupBy: [],
|
||||
legend: '',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
},
|
||||
],
|
||||
queryFormulas: [],
|
||||
|
||||
@@ -3,7 +3,7 @@ import { GetQueryResultsProps } from 'lib/dashboard/getQueryResults';
|
||||
import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData';
|
||||
import { EQueryType } from 'types/common/dashboard';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
import { DataSource, ReduceOperators } from 'types/common/queryBuilder';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
export const getHostLogsQueryPayload = (
|
||||
@@ -45,7 +45,7 @@ export const getHostLogsQueryPayload = (
|
||||
],
|
||||
groupBy: [],
|
||||
legend: '',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
offset: 0,
|
||||
pageSize: 100,
|
||||
},
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
|
||||
import QueryAddOns from '../QueryV2/QueryAddOns/QueryAddOns';
|
||||
import { PANEL_TYPES } from 'constants/queryBuilder';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
import { DataSource, ReduceOperators } from 'types/common/queryBuilder';
|
||||
|
||||
// Mocks: only what is required for this component to render and for us to assert handler calls
|
||||
const mockHandleChangeQueryData = jest.fn();
|
||||
@@ -200,7 +200,7 @@ describe('QueryAddOns', () => {
|
||||
it('auto-opens reduce-to content when reduceTo is set', () => {
|
||||
render(
|
||||
<QueryAddOns
|
||||
query={baseQuery({ reduceTo: 'sum' })}
|
||||
query={baseQuery({ reduceTo: ReduceOperators.SUM })}
|
||||
version="v5"
|
||||
isListViewPanel={false}
|
||||
showReduceTo
|
||||
@@ -216,8 +216,10 @@ describe('QueryAddOns', () => {
|
||||
it('calls handleSetQueryData when reduce-to value changes', async () => {
|
||||
const user = userEvent.setup({ pointerEventsCheck: 0 });
|
||||
const query = baseQuery({
|
||||
reduceTo: 'avg',
|
||||
aggregations: [{ id: 'a', operator: 'count', reduceTo: 'avg' }],
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
aggregations: [
|
||||
{ id: 'a', operator: 'count', reduceTo: ReduceOperators.AVG },
|
||||
],
|
||||
});
|
||||
render(
|
||||
<QueryAddOns
|
||||
@@ -258,7 +260,7 @@ describe('QueryAddOns', () => {
|
||||
aggregations: [
|
||||
{
|
||||
...(query.aggregations?.[0] as any),
|
||||
reduceTo: 'sum',
|
||||
reduceTo: ReduceOperators.SUM,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
DataTypes,
|
||||
} from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
import { TagFilter } from 'types/api/queryBuilder/queryBuilderData';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
import { DataSource, ReduceOperators } from 'types/common/queryBuilder';
|
||||
import { extractQueryPairs } from 'utils/queryContextUtils';
|
||||
|
||||
import {
|
||||
@@ -803,7 +803,7 @@ describe('convertAggregationToExpression', () => {
|
||||
timeAggregation: 'avg',
|
||||
spaceAggregation: 'max',
|
||||
alias: 'test_alias',
|
||||
reduceTo: 'sum',
|
||||
reduceTo: ReduceOperators.SUM,
|
||||
temporality: 'delta',
|
||||
});
|
||||
|
||||
@@ -812,7 +812,7 @@ describe('convertAggregationToExpression', () => {
|
||||
metricName: 'test_metric',
|
||||
timeAggregation: 'avg',
|
||||
spaceAggregation: 'max',
|
||||
reduceTo: 'sum',
|
||||
reduceTo: ReduceOperators.SUM,
|
||||
temporality: 'delta',
|
||||
},
|
||||
]);
|
||||
|
||||
@@ -34,7 +34,7 @@ function YAxisUnitSelector({
|
||||
initialValue,
|
||||
);
|
||||
const currentUniversalUnitName = getUniversalNameFromMetricUnit(value);
|
||||
return `Unit mismatch. Saved unit is ${initialUniversalUnitName}, but ${currentUniversalUnitName} is selected.`;
|
||||
return `Unit mismatch. The metric was sent with unit ${initialUniversalUnitName}, but ${currentUniversalUnitName} is selected.`;
|
||||
}
|
||||
return '';
|
||||
}, [initialValue, value, loading]);
|
||||
@@ -82,6 +82,7 @@ function YAxisUnitSelector({
|
||||
'warning-state': incompatibleUnitMessage,
|
||||
})}
|
||||
data-testid={dataTestId}
|
||||
allowClear
|
||||
>
|
||||
{categories.map((category) => (
|
||||
<Select.OptGroup key={category.name} label={category.name}>
|
||||
|
||||
@@ -106,7 +106,7 @@ describe('YAxisUnitSelector', () => {
|
||||
fireEvent.mouseOver(warningIcon);
|
||||
return screen
|
||||
.findByText(
|
||||
'Unit mismatch. Saved unit is Seconds (s), but Bytes (B) is selected.',
|
||||
'Unit mismatch. The metric was sent with unit Seconds (s), but Bytes (B) is selected.',
|
||||
)
|
||||
.then((el) => expect(el).toBeInTheDocument());
|
||||
});
|
||||
|
||||
@@ -12,4 +12,8 @@
|
||||
.anticon {
|
||||
color: var(--bg-amber-400) !important;
|
||||
}
|
||||
|
||||
.ant-select-clear {
|
||||
right: 28px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,4 +51,6 @@ export enum QueryParams {
|
||||
thresholds = 'thresholds',
|
||||
selectedExplorerView = 'selectedExplorerView',
|
||||
variables = 'variables',
|
||||
version = 'version',
|
||||
showNewCreateAlertsPage = 'showNewCreateAlertsPage',
|
||||
}
|
||||
|
||||
@@ -138,11 +138,11 @@ export const mapOfFormulaToFilters: Record<
|
||||
};
|
||||
|
||||
export const REDUCE_TO_VALUES: SelectOption<ReduceOperators, string>[] = [
|
||||
{ value: 'last', label: 'Latest of values in timeframe' },
|
||||
{ value: 'sum', label: 'Sum of values in timeframe' },
|
||||
{ value: 'avg', label: 'Average of values in timeframe' },
|
||||
{ value: 'max', label: 'Max of values in timeframe' },
|
||||
{ value: 'min', label: 'Min of values in timeframe' },
|
||||
{ value: ReduceOperators.LAST, label: 'Latest of values in timeframe' },
|
||||
{ value: ReduceOperators.SUM, label: 'Sum of values in timeframe' },
|
||||
{ value: ReduceOperators.AVG, label: 'Average of values in timeframe' },
|
||||
{ value: ReduceOperators.MAX, label: 'Max of values in timeframe' },
|
||||
{ value: ReduceOperators.MIN, label: 'Min of values in timeframe' },
|
||||
];
|
||||
|
||||
export const initialHavingValues: HavingForm = {
|
||||
@@ -180,7 +180,7 @@ export const initialQueryBuilderFormValues: IBuilderQuery = {
|
||||
temporality: '',
|
||||
timeAggregation: MetricAggregateOperator.COUNT,
|
||||
spaceAggregation: MetricAggregateOperator.SUM,
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
},
|
||||
],
|
||||
functions: [],
|
||||
@@ -196,7 +196,7 @@ export const initialQueryBuilderFormValues: IBuilderQuery = {
|
||||
orderBy: [],
|
||||
groupBy: [],
|
||||
legend: '',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
source: '',
|
||||
};
|
||||
|
||||
@@ -228,7 +228,7 @@ export const initialQueryBuilderFormMeterValues: IBuilderQuery = {
|
||||
temporality: '',
|
||||
timeAggregation: MeterAggregateOperator.COUNT,
|
||||
spaceAggregation: MeterAggregateOperator.SUM,
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
},
|
||||
],
|
||||
functions: [],
|
||||
@@ -244,7 +244,7 @@ export const initialQueryBuilderFormMeterValues: IBuilderQuery = {
|
||||
orderBy: [],
|
||||
groupBy: [],
|
||||
legend: '',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
};
|
||||
|
||||
export const initialQueryBuilderFormValuesMap: Record<
|
||||
|
||||
@@ -27,6 +27,7 @@ const ROUTES = {
|
||||
ALERTS_NEW: '/alerts/new',
|
||||
ALERT_HISTORY: '/alerts/history',
|
||||
ALERT_OVERVIEW: '/alerts/overview',
|
||||
ALERT_TYPE_SELECTION: '/alerts/type-selection',
|
||||
ALL_CHANNELS: '/settings/channels',
|
||||
CHANNELS_NEW: '/settings/channels/new',
|
||||
CHANNELS_EDIT: '/settings/channels/edit/:channelId',
|
||||
|
||||
@@ -37,7 +37,7 @@ import {
|
||||
} from 'types/api/v5/queryRange';
|
||||
import { QueryData } from 'types/api/widgets/getQuery';
|
||||
import { EQueryType } from 'types/common/dashboard';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
import { DataSource, ReduceOperators } from 'types/common/queryBuilder';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { domainNameKey } from './constants';
|
||||
@@ -401,7 +401,7 @@ export const getDomainMetricsQueryPayload = (
|
||||
orderBy: [],
|
||||
groupBy: [],
|
||||
legend: '',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
},
|
||||
{
|
||||
dataSource: DataSource.TRACES,
|
||||
@@ -429,7 +429,7 @@ export const getDomainMetricsQueryPayload = (
|
||||
orderBy: [],
|
||||
groupBy: [],
|
||||
legend: '',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
},
|
||||
{
|
||||
dataSource: DataSource.TRACES,
|
||||
@@ -457,7 +457,7 @@ export const getDomainMetricsQueryPayload = (
|
||||
orderBy: [],
|
||||
groupBy: [],
|
||||
legend: '',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
},
|
||||
{
|
||||
dataSource: DataSource.TRACES,
|
||||
@@ -485,7 +485,7 @@ export const getDomainMetricsQueryPayload = (
|
||||
orderBy: [],
|
||||
groupBy: [],
|
||||
legend: '',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
},
|
||||
],
|
||||
queryFormulas: [
|
||||
@@ -653,7 +653,7 @@ export const getEndPointsQueryPayload = (
|
||||
limit: 1000,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'count',
|
||||
@@ -700,7 +700,7 @@ export const getEndPointsQueryPayload = (
|
||||
limit: 1000,
|
||||
orderBy: [],
|
||||
queryName: 'B',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'p99',
|
||||
@@ -748,7 +748,7 @@ export const getEndPointsQueryPayload = (
|
||||
limit: 1000,
|
||||
orderBy: [],
|
||||
queryName: 'C',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'max',
|
||||
@@ -805,7 +805,7 @@ export const getEndPointsQueryPayload = (
|
||||
limit: 1000,
|
||||
orderBy: [],
|
||||
queryName: 'D',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'count',
|
||||
@@ -1431,7 +1431,7 @@ export const getEndPointDetailsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'rate',
|
||||
@@ -1461,7 +1461,7 @@ export const getEndPointDetailsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'B',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'p99',
|
||||
@@ -1491,7 +1491,7 @@ export const getEndPointDetailsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'C',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'count',
|
||||
@@ -1521,7 +1521,7 @@ export const getEndPointDetailsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'D',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'max',
|
||||
@@ -1551,7 +1551,7 @@ export const getEndPointDetailsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'E',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'count',
|
||||
@@ -1629,7 +1629,7 @@ export const getEndPointDetailsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'count',
|
||||
@@ -1665,7 +1665,7 @@ export const getEndPointDetailsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'B',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'p99',
|
||||
@@ -1705,7 +1705,7 @@ export const getEndPointDetailsQueryPayload = (
|
||||
},
|
||||
],
|
||||
legend: 'rate',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
},
|
||||
],
|
||||
queryFormulas: [],
|
||||
@@ -1781,7 +1781,7 @@ export const getEndPointDetailsQueryPayload = (
|
||||
type: 'attribute',
|
||||
},
|
||||
],
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
},
|
||||
],
|
||||
queryFormulas: [],
|
||||
@@ -1850,7 +1850,7 @@ export const getEndPointDetailsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'count',
|
||||
@@ -1887,7 +1887,7 @@ export const getEndPointDetailsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'B',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'p99',
|
||||
@@ -1924,7 +1924,7 @@ export const getEndPointDetailsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'C',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'rate',
|
||||
@@ -1961,7 +1961,7 @@ export const getEndPointDetailsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'D',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'count',
|
||||
@@ -2039,7 +2039,7 @@ export const getEndPointDetailsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: null,
|
||||
timeAggregation: 'rate',
|
||||
@@ -2110,7 +2110,7 @@ export const getEndPointDetailsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: null,
|
||||
timeAggregation: 'p99',
|
||||
@@ -2208,7 +2208,7 @@ export const getEndPointZeroStateQueryPayload = (
|
||||
type: 'tag',
|
||||
},
|
||||
],
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
},
|
||||
],
|
||||
queryFormulas: [],
|
||||
@@ -2787,7 +2787,7 @@ export const getStatusCodeBarChartWidgetData = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'rate',
|
||||
@@ -2909,7 +2909,7 @@ export const getAllEndpointsWidgetData = (
|
||||
limit: 1000,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'count',
|
||||
@@ -2941,7 +2941,7 @@ export const getAllEndpointsWidgetData = (
|
||||
limit: 1000,
|
||||
orderBy: [],
|
||||
queryName: 'B',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'p99',
|
||||
@@ -2973,7 +2973,7 @@ export const getAllEndpointsWidgetData = (
|
||||
limit: 1000,
|
||||
orderBy: [],
|
||||
queryName: 'C',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'max',
|
||||
@@ -3005,7 +3005,7 @@ export const getAllEndpointsWidgetData = (
|
||||
limit: 1000,
|
||||
orderBy: [],
|
||||
queryName: 'D',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'count',
|
||||
@@ -3191,7 +3191,7 @@ export const getRateOverTimeWidgetData = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: null,
|
||||
timeAggregation: 'rate',
|
||||
@@ -3242,7 +3242,7 @@ export const getLatencyOverTimeWidgetData = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: null,
|
||||
timeAggregation: 'p99',
|
||||
|
||||
@@ -1,24 +1,12 @@
|
||||
import ROUTES from 'constants/routes';
|
||||
import * as usePrefillAlertConditions from 'container/FormAlertRules/usePrefillAlertConditions';
|
||||
import AlertTypeSelectionPage from 'pages/AlertTypeSelection';
|
||||
import CreateAlertPage from 'pages/CreateAlert';
|
||||
import { act, fireEvent, render } from 'tests/test-utils';
|
||||
import { AlertTypes } from 'types/api/alerts/alertTypes';
|
||||
|
||||
import { ALERT_TYPE_TO_TITLE, ALERT_TYPE_URL_MAP } from './constants';
|
||||
|
||||
jest.mock('react-router-dom', () => ({
|
||||
...jest.requireActual('react-router-dom'),
|
||||
useLocation: (): { pathname: string } => ({
|
||||
pathname: `${process.env.FRONTEND_API_ENDPOINT}${ROUTES.ALERTS_NEW}`,
|
||||
}),
|
||||
}));
|
||||
|
||||
jest.mock('hooks/useSafeNavigate', () => ({
|
||||
useSafeNavigate: (): any => ({
|
||||
safeNavigate: jest.fn(),
|
||||
}),
|
||||
}));
|
||||
|
||||
jest
|
||||
.spyOn(usePrefillAlertConditions, 'usePrefillAlertConditions')
|
||||
.mockReturnValue({
|
||||
@@ -66,13 +54,20 @@ describe('Alert rule documentation redirection', () => {
|
||||
window.open = mockWindowOpen;
|
||||
});
|
||||
|
||||
jest.mock('react-router-dom', () => ({
|
||||
...jest.requireActual('react-router-dom'),
|
||||
useLocation: (): { pathname: string } => ({
|
||||
pathname: `${process.env.FRONTEND_API_ENDPOINT}${ROUTES.ALERT_TYPE_SELECTION}`,
|
||||
}),
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
act(() => {
|
||||
renderResult = render(
|
||||
<CreateAlertPage />,
|
||||
<AlertTypeSelectionPage />,
|
||||
{},
|
||||
{
|
||||
initialRoute: ROUTES.ALERTS_NEW,
|
||||
initialRoute: ROUTES.ALERT_TYPE_SELECTION,
|
||||
},
|
||||
);
|
||||
});
|
||||
@@ -117,18 +112,20 @@ describe('Alert rule documentation redirection', () => {
|
||||
|
||||
expect(mockWindowOpen).toHaveBeenCalledTimes(alertTypeCount);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Create alert page redirection', () => {
|
||||
Object.values(AlertTypes)
|
||||
.filter((type) => type !== AlertTypes.ANOMALY_BASED_ALERT)
|
||||
.forEach((alertType) => {
|
||||
it(`should redirect to create alert page for ${alertType} and "Check an example alert" should redirect to the correct documentation`, () => {
|
||||
const { getByTestId, getByRole } = renderResult;
|
||||
|
||||
const alertTypeLink = getByTestId(`alert-type-card-${alertType}`);
|
||||
|
||||
act(() => {
|
||||
fireEvent.click(alertTypeLink);
|
||||
});
|
||||
const { getByRole } = render(
|
||||
<CreateAlertPage />,
|
||||
{},
|
||||
{
|
||||
initialRoute: `${ROUTES.ALERTS_NEW}?alertType=${alertType}`,
|
||||
},
|
||||
);
|
||||
|
||||
act(() => {
|
||||
fireEvent.click(
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { QueryParams } from 'constants/query';
|
||||
import { initialQueriesMap } from 'constants/queryBuilder';
|
||||
import * as useCompositeQueryParamHooks from 'hooks/queryBuilder/useGetCompositeQueryParam';
|
||||
import * as useUrlQueryHooks from 'hooks/useUrlQuery';
|
||||
import { AlertTypes } from 'types/api/alerts/alertTypes';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
|
||||
import CreateAlertRule from '../index';
|
||||
|
||||
jest.mock('container/FormAlertRules', () => ({
|
||||
__esModule: true,
|
||||
default: function MockFormAlertRules({
|
||||
alertType,
|
||||
}: {
|
||||
alertType: AlertTypes;
|
||||
}): JSX.Element {
|
||||
return (
|
||||
<div>
|
||||
<h1>Form Alert Rules</h1>
|
||||
<p>{alertType}</p>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
AlertDetectionTypes: {
|
||||
THRESHOLD_ALERT: 'threshold_rule',
|
||||
ANOMALY_DETECTION_ALERT: 'anomaly_rule',
|
||||
},
|
||||
}));
|
||||
jest.mock('container/CreateAlertV2', () => ({
|
||||
__esModule: true,
|
||||
default: function MockCreateAlertV2(): JSX.Element {
|
||||
return <div>Create Alert V2</div>;
|
||||
},
|
||||
}));
|
||||
|
||||
const useCompositeQueryParamSpy = jest.spyOn(
|
||||
useCompositeQueryParamHooks,
|
||||
'useGetCompositeQueryParam',
|
||||
);
|
||||
const useUrlQuerySpy = jest.spyOn(useUrlQueryHooks, 'default');
|
||||
|
||||
const mockSetUrlQuery = jest.fn();
|
||||
const mockToString = jest.fn();
|
||||
const mockGetUrlQuery = jest.fn();
|
||||
|
||||
const FORM_ALERT_RULES_TEXT = 'Form Alert Rules';
|
||||
const CREATE_ALERT_V2_TEXT = 'Create Alert V2';
|
||||
|
||||
describe('CreateAlertRule', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
useUrlQuerySpy.mockReturnValue(({
|
||||
set: mockSetUrlQuery,
|
||||
toString: mockToString,
|
||||
get: mockGetUrlQuery,
|
||||
} as Partial<URLSearchParams>) as URLSearchParams);
|
||||
useCompositeQueryParamSpy.mockReturnValue(initialQueriesMap.metrics);
|
||||
});
|
||||
|
||||
it('should render v1 flow when showNewCreateAlertsPage is false', () => {
|
||||
mockGetUrlQuery.mockReturnValue(null);
|
||||
render(<CreateAlertRule />);
|
||||
expect(screen.getByText(FORM_ALERT_RULES_TEXT)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render v2 flow when showNewCreateAlertsPage is true', () => {
|
||||
mockGetUrlQuery.mockImplementation((key: string) => {
|
||||
if (key === QueryParams.showNewCreateAlertsPage) {
|
||||
return 'true';
|
||||
}
|
||||
return null;
|
||||
});
|
||||
render(<CreateAlertRule />);
|
||||
expect(screen.getByText(CREATE_ALERT_V2_TEXT)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render v1 flow when ruleType is anomaly_rule even if showNewCreateAlertsPage is true', () => {
|
||||
mockGetUrlQuery.mockImplementation((key: string) => {
|
||||
if (key === QueryParams.showNewCreateAlertsPage) {
|
||||
return 'true';
|
||||
}
|
||||
if (key === QueryParams.ruleType) {
|
||||
return 'anomaly_rule';
|
||||
}
|
||||
return null;
|
||||
});
|
||||
render(<CreateAlertRule />);
|
||||
expect(screen.getByText(FORM_ALERT_RULES_TEXT)).toBeInTheDocument();
|
||||
expect(screen.queryByText(CREATE_ALERT_V2_TEXT)).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should use alertType from URL when provided', () => {
|
||||
mockGetUrlQuery.mockImplementation((key: string) => {
|
||||
if (key === QueryParams.alertType) {
|
||||
return AlertTypes.LOGS_BASED_ALERT;
|
||||
}
|
||||
return null;
|
||||
});
|
||||
render(<CreateAlertRule />);
|
||||
expect(screen.getByText(FORM_ALERT_RULES_TEXT)).toBeInTheDocument();
|
||||
expect(screen.getByText(AlertTypes.LOGS_BASED_ALERT)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should use alertType from compositeQuery dataSource when alertType is not in URL', () => {
|
||||
mockGetUrlQuery.mockReturnValue(null);
|
||||
useCompositeQueryParamSpy.mockReturnValue({
|
||||
...initialQueriesMap.metrics,
|
||||
builder: {
|
||||
...initialQueriesMap.metrics.builder,
|
||||
queryData: [
|
||||
{
|
||||
...initialQueriesMap.metrics.builder.queryData[0],
|
||||
dataSource: DataSource.TRACES,
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
render(<CreateAlertRule />);
|
||||
expect(screen.getByText(FORM_ALERT_RULES_TEXT)).toBeInTheDocument();
|
||||
expect(screen.getByText(AlertTypes.TRACES_BASED_ALERT)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should default to METRICS_BASED_ALERT when no alertType and no compositeQuery', () => {
|
||||
mockGetUrlQuery.mockReturnValue(null);
|
||||
useCompositeQueryParamSpy.mockReturnValue(null);
|
||||
render(<CreateAlertRule />);
|
||||
expect(screen.getByText(FORM_ALERT_RULES_TEXT)).toBeInTheDocument();
|
||||
expect(screen.getByText(AlertTypes.METRICS_BASED_ALERT)).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -1,133 +1,49 @@
|
||||
import { Form, Row } from 'antd';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import { Form } from 'antd';
|
||||
import { ENTITY_VERSION_V5 } from 'constants/app';
|
||||
import { QueryParams } from 'constants/query';
|
||||
import CreateAlertV2 from 'container/CreateAlertV2';
|
||||
import FormAlertRules, { AlertDetectionTypes } from 'container/FormAlertRules';
|
||||
import { ThresholdProps } from 'container/NewWidget/RightContainer/Threshold/types';
|
||||
import { useGetCompositeQueryParam } from 'hooks/queryBuilder/useGetCompositeQueryParam';
|
||||
import history from 'lib/history';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import useUrlQuery from 'hooks/useUrlQuery';
|
||||
import { useMemo } from 'react';
|
||||
import { AlertTypes } from 'types/api/alerts/alertTypes';
|
||||
import { AlertDef } from 'types/api/alerts/def';
|
||||
|
||||
import { ALERT_TYPE_VS_SOURCE_MAPPING } from './config';
|
||||
import {
|
||||
alertDefaults,
|
||||
anamolyAlertDefaults,
|
||||
exceptionAlertDefaults,
|
||||
logAlertDefaults,
|
||||
traceAlertDefaults,
|
||||
} from './defaults';
|
||||
import SelectAlertType from './SelectAlertType';
|
||||
import { ALERTS_VALUES_MAP } from './defaults';
|
||||
|
||||
function CreateRules(): JSX.Element {
|
||||
const [initValues, setInitValues] = useState<AlertDef | null>(null);
|
||||
|
||||
const location = useLocation();
|
||||
const queryParams = new URLSearchParams(location.search);
|
||||
const alertTypeFromURL = queryParams.get(QueryParams.ruleType);
|
||||
const version = queryParams.get('version');
|
||||
const alertTypeFromParams =
|
||||
alertTypeFromURL === AlertDetectionTypes.ANOMALY_DETECTION_ALERT
|
||||
? AlertTypes.ANOMALY_BASED_ALERT
|
||||
: queryParams.get(QueryParams.alertType);
|
||||
|
||||
const { thresholds } = (location.state as {
|
||||
thresholds: ThresholdProps[];
|
||||
}) || {
|
||||
thresholds: null,
|
||||
};
|
||||
|
||||
const compositeQuery = useGetCompositeQueryParam();
|
||||
function getAlertTypeFromDataSource(): AlertTypes | null {
|
||||
if (!compositeQuery) {
|
||||
return null;
|
||||
}
|
||||
const dataSource = compositeQuery?.builder?.queryData[0]?.dataSource;
|
||||
|
||||
return ALERT_TYPE_VS_SOURCE_MAPPING[dataSource];
|
||||
}
|
||||
|
||||
const [alertType, setAlertType] = useState<AlertTypes>(
|
||||
(alertTypeFromParams as AlertTypes) || getAlertTypeFromDataSource(),
|
||||
);
|
||||
|
||||
const [formInstance] = Form.useForm();
|
||||
const compositeQuery = useGetCompositeQueryParam();
|
||||
const queryParams = useUrlQuery();
|
||||
|
||||
const onSelectType = (typ: AlertTypes): void => {
|
||||
setAlertType(typ);
|
||||
|
||||
switch (typ) {
|
||||
case AlertTypes.LOGS_BASED_ALERT:
|
||||
setInitValues(logAlertDefaults);
|
||||
break;
|
||||
case AlertTypes.TRACES_BASED_ALERT:
|
||||
setInitValues(traceAlertDefaults);
|
||||
break;
|
||||
case AlertTypes.EXCEPTIONS_BASED_ALERT:
|
||||
setInitValues(exceptionAlertDefaults);
|
||||
break;
|
||||
case AlertTypes.ANOMALY_BASED_ALERT:
|
||||
setInitValues({
|
||||
...anamolyAlertDefaults,
|
||||
version: version || ENTITY_VERSION_V5,
|
||||
ruleType: AlertDetectionTypes.ANOMALY_DETECTION_ALERT,
|
||||
});
|
||||
break;
|
||||
default:
|
||||
setInitValues({
|
||||
...alertDefaults,
|
||||
version: version || ENTITY_VERSION_V5,
|
||||
ruleType: AlertDetectionTypes.THRESHOLD_ALERT,
|
||||
});
|
||||
}
|
||||
|
||||
queryParams.set(
|
||||
QueryParams.alertType,
|
||||
typ === AlertTypes.ANOMALY_BASED_ALERT
|
||||
? AlertTypes.METRICS_BASED_ALERT
|
||||
: typ,
|
||||
);
|
||||
|
||||
if (
|
||||
typ === AlertTypes.ANOMALY_BASED_ALERT ||
|
||||
alertTypeFromURL === AlertDetectionTypes.ANOMALY_DETECTION_ALERT
|
||||
) {
|
||||
queryParams.set(
|
||||
QueryParams.ruleType,
|
||||
AlertDetectionTypes.ANOMALY_DETECTION_ALERT,
|
||||
);
|
||||
} else {
|
||||
queryParams.set(QueryParams.ruleType, AlertDetectionTypes.THRESHOLD_ALERT);
|
||||
}
|
||||
|
||||
const generatedUrl = `${location.pathname}?${queryParams.toString()}`;
|
||||
history.replace(generatedUrl, {
|
||||
thresholds,
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (alertType) {
|
||||
onSelectType(alertType);
|
||||
} else {
|
||||
logEvent('Alert: New alert data source selection page visited', {});
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [alertType]);
|
||||
|
||||
if (!initValues) {
|
||||
return (
|
||||
<Row wrap={false}>
|
||||
<SelectAlertType onSelect={onSelectType} />
|
||||
</Row>
|
||||
);
|
||||
}
|
||||
|
||||
const ruleTypeFromURL = queryParams.get(QueryParams.ruleType);
|
||||
const alertTypeFromURL = queryParams.get(QueryParams.alertType);
|
||||
const version = queryParams.get(QueryParams.version);
|
||||
const showNewCreateAlertsPageFlag =
|
||||
queryParams.get('showNewCreateAlertsPage') === 'true';
|
||||
queryParams.get(QueryParams.showNewCreateAlertsPage) === 'true';
|
||||
|
||||
const alertType = useMemo(() => {
|
||||
if (ruleTypeFromURL === AlertDetectionTypes.ANOMALY_DETECTION_ALERT) {
|
||||
return AlertTypes.ANOMALY_BASED_ALERT;
|
||||
}
|
||||
if (!alertTypeFromURL) {
|
||||
const dataSource = compositeQuery?.builder.queryData?.[0]?.dataSource;
|
||||
if (dataSource) {
|
||||
return ALERT_TYPE_VS_SOURCE_MAPPING[dataSource];
|
||||
}
|
||||
return AlertTypes.METRICS_BASED_ALERT;
|
||||
}
|
||||
return alertTypeFromURL as AlertTypes;
|
||||
}, [alertTypeFromURL, ruleTypeFromURL, compositeQuery?.builder.queryData]);
|
||||
|
||||
const initialAlertValue: AlertDef = useMemo(
|
||||
() => ({
|
||||
...ALERTS_VALUES_MAP[alertType],
|
||||
version: version || ENTITY_VERSION_V5,
|
||||
}),
|
||||
[alertType, version],
|
||||
);
|
||||
|
||||
if (
|
||||
showNewCreateAlertsPageFlag &&
|
||||
@@ -140,7 +56,7 @@ function CreateRules(): JSX.Element {
|
||||
<FormAlertRules
|
||||
alertType={alertType}
|
||||
formInstance={formInstance}
|
||||
initialValue={initValues}
|
||||
initialValue={initialAlertValue}
|
||||
ruleId=""
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { Select, Tooltip, Typography } from 'antd';
|
||||
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
||||
import { Info } from 'lucide-react';
|
||||
import { useMemo } from 'react';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
|
||||
import { ALL_SELECTED_VALUE } from '../constants';
|
||||
import { useCreateAlertState } from '../context';
|
||||
|
||||
function MultipleNotifications(): JSX.Element {
|
||||
@@ -12,6 +13,12 @@ function MultipleNotifications(): JSX.Element {
|
||||
} = useCreateAlertState();
|
||||
const { currentQuery } = useQueryBuilder();
|
||||
|
||||
const isAllOptionSelected = useMemo(
|
||||
() =>
|
||||
notificationSettings.multipleNotifications?.includes(ALL_SELECTED_VALUE),
|
||||
[notificationSettings.multipleNotifications],
|
||||
);
|
||||
|
||||
const spaceAggregationOptions = useMemo(() => {
|
||||
const allGroupBys = currentQuery.builder.queryData?.reduce<string[]>(
|
||||
(acc, query) => {
|
||||
@@ -21,15 +28,60 @@ function MultipleNotifications(): JSX.Element {
|
||||
[],
|
||||
);
|
||||
const uniqueGroupBys = [...new Set(allGroupBys)];
|
||||
return uniqueGroupBys.map((key) => ({
|
||||
const options = uniqueGroupBys.map((key) => ({
|
||||
label: key,
|
||||
value: key,
|
||||
disabled: isAllOptionSelected,
|
||||
'data-testid': 'multiple-notifications-select-option',
|
||||
}));
|
||||
}, [currentQuery.builder.queryData]);
|
||||
if (options.length > 0) {
|
||||
return [
|
||||
{
|
||||
label: 'All',
|
||||
value: ALL_SELECTED_VALUE,
|
||||
'data-testid': 'multiple-notifications-select-option',
|
||||
},
|
||||
...options,
|
||||
];
|
||||
}
|
||||
return options;
|
||||
}, [currentQuery.builder.queryData, isAllOptionSelected]);
|
||||
|
||||
const isMultipleNotificationsEnabled = spaceAggregationOptions.length > 0;
|
||||
|
||||
const onSelectChange = useCallback(
|
||||
(newSelectedOptions: string[]): void => {
|
||||
const currentSelectedOptions = notificationSettings.multipleNotifications;
|
||||
const allOptionLastSelected =
|
||||
!currentSelectedOptions?.includes(ALL_SELECTED_VALUE) &&
|
||||
newSelectedOptions.includes(ALL_SELECTED_VALUE);
|
||||
if (allOptionLastSelected) {
|
||||
setNotificationSettings({
|
||||
type: 'SET_MULTIPLE_NOTIFICATIONS',
|
||||
payload: [ALL_SELECTED_VALUE],
|
||||
});
|
||||
} else {
|
||||
setNotificationSettings({
|
||||
type: 'SET_MULTIPLE_NOTIFICATIONS',
|
||||
payload: newSelectedOptions,
|
||||
});
|
||||
}
|
||||
},
|
||||
[setNotificationSettings, notificationSettings.multipleNotifications],
|
||||
);
|
||||
|
||||
const groupByDescription = useMemo(() => {
|
||||
if (isAllOptionSelected) {
|
||||
return 'All = grouping of alerts is disabled';
|
||||
}
|
||||
if (notificationSettings.multipleNotifications?.length) {
|
||||
return `Alerts with same ${notificationSettings.multipleNotifications?.join(
|
||||
', ',
|
||||
)} will be grouped`;
|
||||
}
|
||||
return 'Empty = all matching alerts combined into one notification';
|
||||
}, [isAllOptionSelected, notificationSettings.multipleNotifications]);
|
||||
|
||||
const multipleNotificationsInput = useMemo(() => {
|
||||
const placeholder = isMultipleNotificationsEnabled
|
||||
? 'Select fields to group by (optional)'
|
||||
@@ -38,12 +90,7 @@ function MultipleNotifications(): JSX.Element {
|
||||
<div>
|
||||
<Select
|
||||
options={spaceAggregationOptions}
|
||||
onChange={(value): void => {
|
||||
setNotificationSettings({
|
||||
type: 'SET_MULTIPLE_NOTIFICATIONS',
|
||||
payload: value,
|
||||
});
|
||||
}}
|
||||
onChange={onSelectChange}
|
||||
value={notificationSettings.multipleNotifications}
|
||||
mode="multiple"
|
||||
placeholder={placeholder}
|
||||
@@ -54,11 +101,7 @@ function MultipleNotifications(): JSX.Element {
|
||||
/>
|
||||
{isMultipleNotificationsEnabled && (
|
||||
<Typography.Paragraph className="multiple-notifications-select-description">
|
||||
{notificationSettings.multipleNotifications?.length
|
||||
? `Alerts with same ${notificationSettings.multipleNotifications?.join(
|
||||
', ',
|
||||
)} will be grouped`
|
||||
: 'Empty = all matching alerts combined into one notification'}
|
||||
{groupByDescription}
|
||||
</Typography.Paragraph>
|
||||
)}
|
||||
</div>
|
||||
@@ -72,9 +115,10 @@ function MultipleNotifications(): JSX.Element {
|
||||
}
|
||||
return input;
|
||||
}, [
|
||||
groupByDescription,
|
||||
isMultipleNotificationsEnabled,
|
||||
notificationSettings.multipleNotifications,
|
||||
setNotificationSettings,
|
||||
onSelectChange,
|
||||
spaceAggregationOptions,
|
||||
]);
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import { ALL_SELECTED_VALUE } from 'container/CreateAlertV2/constants';
|
||||
import * as createAlertContext from 'container/CreateAlertV2/context';
|
||||
import {
|
||||
INITIAL_ALERT_THRESHOLD_STATE,
|
||||
@@ -28,6 +29,7 @@ jest.mock('hooks/queryBuilder/useQueryBuilder', () => ({
|
||||
}));
|
||||
|
||||
const TEST_QUERY = 'test-query';
|
||||
const TEST_QUERY_2 = 'test-query-2';
|
||||
const TEST_GROUP_BY_FIELDS = [{ key: 'service' }, { key: 'environment' }];
|
||||
const TRUE = 'true';
|
||||
const FALSE = 'false';
|
||||
@@ -151,7 +153,7 @@ describe('MultipleNotifications', () => {
|
||||
groupBy: [{ key: 'http.status_code' }],
|
||||
},
|
||||
{
|
||||
queryName: 'test-query-2',
|
||||
queryName: TEST_QUERY_2,
|
||||
groupBy: [{ key: 'service' }],
|
||||
},
|
||||
],
|
||||
@@ -167,6 +169,99 @@ describe('MultipleNotifications', () => {
|
||||
expect(
|
||||
screen.getByRole('option', { name: 'http.status_code' }),
|
||||
).toBeInTheDocument();
|
||||
expect(screen.getByRole('option', { name: 'service' })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('selecting the "all" option shows correct group by description', () => {
|
||||
useQueryBuilder.mockReturnValue({
|
||||
currentQuery: {
|
||||
builder: {
|
||||
queryData: [
|
||||
{
|
||||
queryName: TEST_QUERY_2,
|
||||
groupBy: [{ key: 'service' }],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
||||
jest.spyOn(createAlertContext, 'useCreateAlertState').mockReturnValue(
|
||||
createMockAlertContextState({
|
||||
notificationSettings: {
|
||||
...INITIAL_NOTIFICATION_SETTINGS_STATE,
|
||||
multipleNotifications: [ALL_SELECTED_VALUE],
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
render(<MultipleNotifications />);
|
||||
|
||||
expect(
|
||||
screen.getByText('All = grouping of alerts is disabled'),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('selecting "all" option should disable selection of other options', async () => {
|
||||
useQueryBuilder.mockReturnValue({
|
||||
currentQuery: {
|
||||
builder: {
|
||||
queryData: [
|
||||
{
|
||||
queryName: TEST_QUERY_2,
|
||||
groupBy: [{ key: 'service' }],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
render(<MultipleNotifications />);
|
||||
|
||||
const select = screen.getByRole(COMBOBOX_ROLE);
|
||||
await userEvent.click(select);
|
||||
|
||||
const serviceOption = screen.getAllByTestId(
|
||||
'multiple-notifications-select-option',
|
||||
);
|
||||
expect(serviceOption).toHaveLength(2);
|
||||
expect(serviceOption[0]).not.toHaveClass('ant-select-item-option-disabled');
|
||||
expect(serviceOption[1]).toHaveClass('ant-select-item-option-disabled');
|
||||
});
|
||||
|
||||
it('selecting "all" option should remove all other selected options', async () => {
|
||||
useQueryBuilder.mockReturnValue({
|
||||
currentQuery: {
|
||||
builder: {
|
||||
queryData: [
|
||||
{
|
||||
queryName: TEST_QUERY_2,
|
||||
groupBy: [{ key: 'service' }],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
||||
jest.spyOn(createAlertContext, 'useCreateAlertState').mockReturnValue(
|
||||
createMockAlertContextState({
|
||||
notificationSettings: {
|
||||
...INITIAL_NOTIFICATION_SETTINGS_STATE,
|
||||
multipleNotifications: ['service'],
|
||||
},
|
||||
setNotificationSettings: mockSetNotificationSettings,
|
||||
}),
|
||||
);
|
||||
|
||||
render(<MultipleNotifications />);
|
||||
const select = screen.getByRole(COMBOBOX_ROLE);
|
||||
await userEvent.click(select);
|
||||
|
||||
const serviceOption = screen.getAllByTestId(
|
||||
'multiple-notifications-select-option',
|
||||
);
|
||||
expect(serviceOption).toHaveLength(2);
|
||||
await userEvent.click(serviceOption[0]);
|
||||
expect(mockSetNotificationSettings).toHaveBeenCalledWith({
|
||||
type: 'SET_MULTIPLE_NOTIFICATIONS',
|
||||
payload: [ALL_SELECTED_VALUE],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -35,24 +35,21 @@ function ChartPreview({ alertDef }: ChartPreviewProps): JSX.Element {
|
||||
|
||||
const yAxisUnit = alertState.yAxisUnit || '';
|
||||
|
||||
const fetchYAxisUnit =
|
||||
const shouldUpdateYAxisUnit =
|
||||
!isEditMode && alertType === AlertTypes.METRICS_BASED_ALERT;
|
||||
|
||||
const selectedQueryName = thresholdState.selectedQuery;
|
||||
const { yAxisUnit: initialYAxisUnit, isLoading } = useGetYAxisUnit(
|
||||
selectedQueryName,
|
||||
{
|
||||
enabled: fetchYAxisUnit,
|
||||
},
|
||||
);
|
||||
|
||||
// Every time a new metric is selected, set the y-axis unit to its unit value if present
|
||||
// Only for metrics-based alerts
|
||||
// Only for metrics-based alerts in create mode
|
||||
useEffect(() => {
|
||||
if (fetchYAxisUnit) {
|
||||
if (shouldUpdateYAxisUnit) {
|
||||
setAlertState({ type: 'SET_Y_AXIS_UNIT', payload: initialYAxisUnit });
|
||||
}
|
||||
}, [initialYAxisUnit, setAlertState, fetchYAxisUnit]);
|
||||
}, [initialYAxisUnit, setAlertState, shouldUpdateYAxisUnit]);
|
||||
|
||||
const headline = (
|
||||
<div className="chart-preview-headline">
|
||||
|
||||
@@ -72,3 +72,5 @@ export const defaultPostableAlertRuleV2: PostableAlertRuleV2 = {
|
||||
alert: 'TEST_ALERT',
|
||||
evaluation: defaultEvaluation,
|
||||
};
|
||||
|
||||
export const ALL_SELECTED_VALUE = '__all__';
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { renderHook } from '@testing-library/react';
|
||||
import { ReduceOperators } from 'types/common/queryBuilder';
|
||||
|
||||
import { usePrefillAlertConditions } from '../usePrefillAlertConditions';
|
||||
|
||||
@@ -55,7 +56,7 @@ const mockStagedQuery = {
|
||||
builder: {
|
||||
queryData: [
|
||||
{
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -84,10 +85,10 @@ describe('usePrefillAlertConditions', () => {
|
||||
builder: {
|
||||
queryData: [
|
||||
{
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
},
|
||||
{
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -102,10 +103,10 @@ describe('usePrefillAlertConditions', () => {
|
||||
builder: {
|
||||
queryData: [
|
||||
{
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
},
|
||||
{
|
||||
reduceTo: 'sum',
|
||||
reduceTo: ReduceOperators.SUM,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@@ -6,6 +6,8 @@ import saveAlertApi from 'api/alerts/save';
|
||||
import testAlertApi from 'api/alerts/testAlert';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import { getInvolvedQueriesInTraceOperator } from 'components/QueryBuilderV2/QueryV2/TraceOperator/utils/utils';
|
||||
import YAxisUnitSelector from 'components/YAxisUnitSelector';
|
||||
import { YAxisSource } from 'components/YAxisUnitSelector/types';
|
||||
import { ALERTS_DATA_SOURCE_MAP } from 'constants/alerts';
|
||||
import { FeatureKeys } from 'constants/features';
|
||||
import { QueryParams } from 'constants/query';
|
||||
@@ -14,9 +16,9 @@ import { REACT_QUERY_KEY } from 'constants/reactQueryKeys';
|
||||
import ROUTES from 'constants/routes';
|
||||
import QueryTypeTag from 'container/NewWidget/LeftContainer/QueryTypeTag';
|
||||
import PlotTag from 'container/NewWidget/LeftContainer/WidgetGraph/PlotTag';
|
||||
import { BuilderUnitsFilter } from 'container/QueryBuilder/filters';
|
||||
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
||||
import { useShareBuilderUrl } from 'hooks/queryBuilder/useShareBuilderUrl';
|
||||
import useGetYAxisUnit from 'hooks/useGetYAxisUnit';
|
||||
import { useNotifications } from 'hooks/useNotifications';
|
||||
import { useSafeNavigate } from 'hooks/useSafeNavigate';
|
||||
import useUrlQuery from 'hooks/useUrlQuery';
|
||||
@@ -230,16 +232,18 @@ function FormAlertRules({
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const ruleType =
|
||||
detectionMethod === AlertDetectionTypes.ANOMALY_DETECTION_ALERT
|
||||
? AlertDetectionTypes.ANOMALY_DETECTION_ALERT
|
||||
: AlertDetectionTypes.THRESHOLD_ALERT;
|
||||
if (detectionMethod) {
|
||||
const ruleType =
|
||||
detectionMethod === AlertDetectionTypes.ANOMALY_DETECTION_ALERT
|
||||
? AlertDetectionTypes.ANOMALY_DETECTION_ALERT
|
||||
: AlertDetectionTypes.THRESHOLD_ALERT;
|
||||
|
||||
queryParams.set(QueryParams.ruleType, ruleType);
|
||||
queryParams.set(QueryParams.ruleType, ruleType);
|
||||
|
||||
const generatedUrl = `${location.pathname}?${queryParams.toString()}`;
|
||||
const generatedUrl = `${location.pathname}?${queryParams.toString()}`;
|
||||
|
||||
safeNavigate(generatedUrl);
|
||||
safeNavigate(generatedUrl);
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [detectionMethod]);
|
||||
|
||||
@@ -481,7 +485,7 @@ function FormAlertRules({
|
||||
chQueries: mapQueryDataToApi(currentQuery.clickhouse_sql, 'name').data,
|
||||
queryType: currentQuery.queryType,
|
||||
panelType: panelType || initQuery.panelType,
|
||||
unit: currentQuery.unit,
|
||||
unit: yAxisUnit,
|
||||
}),
|
||||
},
|
||||
};
|
||||
@@ -500,6 +504,7 @@ function FormAlertRules({
|
||||
alertType,
|
||||
initQuery,
|
||||
panelType,
|
||||
yAxisUnit,
|
||||
]);
|
||||
|
||||
const saveRule = useCallback(async () => {
|
||||
@@ -525,8 +530,7 @@ function FormAlertRules({
|
||||
if (response.statusCode === 200) {
|
||||
logData = {
|
||||
status: 'success',
|
||||
statusMessage:
|
||||
!ruleId || isEmpty(ruleId) ? t('rule_created') : t('rule_edited'),
|
||||
statusMessage: isNewRule ? t('rule_created') : t('rule_edited'),
|
||||
};
|
||||
|
||||
notifications.success({
|
||||
@@ -578,7 +582,7 @@ function FormAlertRules({
|
||||
dataSource: ALERTS_DATA_SOURCE_MAP[postableAlert?.alertType as AlertTypes],
|
||||
channelNames: postableAlert?.preferredChannels,
|
||||
broadcastToAll: postableAlert?.broadcastToAll,
|
||||
isNewRule: !ruleId || isEmpty(ruleId),
|
||||
isNewRule,
|
||||
ruleId,
|
||||
queryType: currentQuery.queryType,
|
||||
alertId: postableAlert?.id,
|
||||
@@ -663,7 +667,7 @@ function FormAlertRules({
|
||||
dataSource: ALERTS_DATA_SOURCE_MAP[alertDef?.alertType as AlertTypes],
|
||||
channelNames: postableAlert?.preferredChannels,
|
||||
broadcastToAll: postableAlert?.broadcastToAll,
|
||||
isNewRule: !ruleId || isEmpty(ruleId),
|
||||
isNewRule,
|
||||
ruleId,
|
||||
queryType: currentQuery.queryType,
|
||||
status: statusResponse.status,
|
||||
@@ -735,8 +739,6 @@ function FormAlertRules({
|
||||
alertDef?.broadcastToAll ||
|
||||
(alertDef.preferredChannels && alertDef.preferredChannels.length > 0);
|
||||
|
||||
const isRuleCreated = !ruleId || isEmpty(ruleId);
|
||||
|
||||
function handleRedirection(option: AlertTypes): void {
|
||||
let url;
|
||||
if (
|
||||
@@ -751,7 +753,7 @@ function FormAlertRules({
|
||||
if (url) {
|
||||
logEvent('Alert: Check example alert clicked', {
|
||||
dataSource: ALERTS_DATA_SOURCE_MAP[alertDef?.alertType as AlertTypes],
|
||||
isNewRule: !ruleId || isEmpty(ruleId),
|
||||
isNewRule,
|
||||
ruleId,
|
||||
queryType: currentQuery.queryType,
|
||||
link: url,
|
||||
@@ -761,7 +763,7 @@ function FormAlertRules({
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (!isRuleCreated) {
|
||||
if (!isNewRule) {
|
||||
logEvent('Alert: Edit page visited', {
|
||||
ruleId,
|
||||
dataSource: ALERTS_DATA_SOURCE_MAP[alertType as AlertTypes],
|
||||
@@ -786,6 +788,24 @@ function FormAlertRules({
|
||||
featureFlags?.find((flag) => flag.name === FeatureKeys.ANOMALY_DETECTION)
|
||||
?.active || false;
|
||||
|
||||
// Only update automatically when creating a new metrics-based alert rule
|
||||
const shouldUpdateYAxisUnit = useMemo(
|
||||
() => isNewRule && alertType === AlertTypes.METRICS_BASED_ALERT,
|
||||
[isNewRule, alertType],
|
||||
);
|
||||
|
||||
const { yAxisUnit: initialYAxisUnit, isLoading } = useGetYAxisUnit(
|
||||
alertDef.condition.selectedQueryName,
|
||||
);
|
||||
|
||||
// Every time a new metric is selected, set the y-axis unit to its unit
|
||||
// Only for metrics-based alerts in create mode
|
||||
useEffect(() => {
|
||||
if (shouldUpdateYAxisUnit) {
|
||||
setYAxisUnit(initialYAxisUnit || '');
|
||||
}
|
||||
}, [initialYAxisUnit, shouldUpdateYAxisUnit]);
|
||||
|
||||
return (
|
||||
<>
|
||||
{Element}
|
||||
@@ -793,7 +813,7 @@ function FormAlertRules({
|
||||
<div
|
||||
id="top"
|
||||
className={`form-alert-rules-container ${
|
||||
isRuleCreated ? 'create-mode' : 'edit-mode'
|
||||
isNewRule ? 'create-mode' : 'edit-mode'
|
||||
}`}
|
||||
>
|
||||
<div className="overview-header">
|
||||
@@ -841,9 +861,12 @@ function FormAlertRules({
|
||||
</div>
|
||||
|
||||
<StepContainer>
|
||||
<BuilderUnitsFilter
|
||||
<YAxisUnitSelector
|
||||
value={yAxisUnit}
|
||||
initialValue={initialYAxisUnit}
|
||||
onChange={onUnitChangeHandler}
|
||||
yAxisUnit={yAxisUnit}
|
||||
source={YAxisSource.ALERTS}
|
||||
loading={isLoading}
|
||||
/>
|
||||
</StepContainer>
|
||||
|
||||
@@ -921,7 +944,7 @@ function FormAlertRules({
|
||||
type="default"
|
||||
onClick={onCancelHandler}
|
||||
>
|
||||
{(!ruleId || isEmpty(ruleId)) && t('button_cancelchanges')}
|
||||
{isNewRule && t('button_cancelchanges')}
|
||||
{ruleId && !isEmpty(ruleId) && t('button_discard')}
|
||||
</ActionButton>
|
||||
</ButtonContainer>
|
||||
|
||||
@@ -8,7 +8,7 @@ import { Provider } from 'react-redux';
|
||||
import store from 'store';
|
||||
import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
import { EQueryType } from 'types/common/dashboard';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
import { DataSource, ReduceOperators } from 'types/common/queryBuilder';
|
||||
|
||||
import {
|
||||
MENUITEM_KEYS_VS_LABELS,
|
||||
@@ -68,7 +68,7 @@ const mockProps: WidgetGraphComponentProps = {
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'last',
|
||||
reduceTo: ReduceOperators.LAST,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'count_distinct',
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Query } from 'types/api/queryBuilder/queryBuilderData';
|
||||
import { EQueryType } from 'types/common/dashboard';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
import { DataSource, ReduceOperators } from 'types/common/queryBuilder';
|
||||
|
||||
import { getBarStepIntervalPoints, updateBarStepInterval } from '../utils';
|
||||
|
||||
@@ -126,7 +126,7 @@ describe('GridCardLayout Utils', () => {
|
||||
limit: null,
|
||||
offset: 0,
|
||||
pageSize: 0,
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
legend: '',
|
||||
},
|
||||
],
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { ReduceOperators } from 'types/common/queryBuilder';
|
||||
|
||||
/* eslint-disable sonarjs/no-duplicate-string */
|
||||
export const tableDataMultipleQueriesSuccessResponse = {
|
||||
columns: [
|
||||
@@ -131,7 +133,7 @@ export const widgetQueryWithLegend = {
|
||||
},
|
||||
],
|
||||
legend: 'p99',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
},
|
||||
{
|
||||
dataSource: 'metrics',
|
||||
@@ -158,7 +160,7 @@ export const widgetQueryWithLegend = {
|
||||
orderBy: [],
|
||||
groupBy: [],
|
||||
legend: '',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
},
|
||||
],
|
||||
queryFormulas: [],
|
||||
@@ -374,7 +376,7 @@ export const widgetQueryQBv5MultiAggregations = {
|
||||
},
|
||||
],
|
||||
legend: 'p99',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
},
|
||||
{
|
||||
dataSource: 'metrics',
|
||||
@@ -414,7 +416,7 @@ export const widgetQueryQBv5MultiAggregations = {
|
||||
},
|
||||
],
|
||||
legend: '',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
},
|
||||
{
|
||||
dataSource: 'metrics',
|
||||
@@ -454,7 +456,7 @@ export const widgetQueryQBv5MultiAggregations = {
|
||||
},
|
||||
],
|
||||
legend: 'max',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
},
|
||||
],
|
||||
queryFormulas: [],
|
||||
|
||||
@@ -4,7 +4,7 @@ import { PANEL_TYPES } from 'constants/queryBuilder';
|
||||
import { GetQueryResultsProps } from 'lib/dashboard/getQueryResults';
|
||||
import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
import { EQueryType } from 'types/common/dashboard';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
import { DataSource, ReduceOperators } from 'types/common/queryBuilder';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
export const clusterWidgetInfo = [
|
||||
@@ -177,7 +177,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -216,7 +216,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'B',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'min',
|
||||
@@ -255,7 +255,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'C',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'max',
|
||||
@@ -294,7 +294,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'D',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -367,7 +367,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -406,7 +406,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'B',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'min',
|
||||
@@ -445,7 +445,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'C',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'max',
|
||||
@@ -484,7 +484,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'D',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -570,7 +570,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'max',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'latest',
|
||||
@@ -656,7 +656,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'max',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'latest',
|
||||
@@ -742,7 +742,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'last',
|
||||
reduceTo: ReduceOperators.LAST,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'latest',
|
||||
@@ -794,7 +794,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'B',
|
||||
reduceTo: 'last',
|
||||
reduceTo: ReduceOperators.LAST,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -892,7 +892,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'last',
|
||||
reduceTo: ReduceOperators.LAST,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'max',
|
||||
@@ -944,7 +944,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'B',
|
||||
reduceTo: 'last',
|
||||
reduceTo: ReduceOperators.LAST,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'max',
|
||||
@@ -996,7 +996,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'C',
|
||||
reduceTo: 'last',
|
||||
reduceTo: ReduceOperators.LAST,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'max',
|
||||
@@ -1048,7 +1048,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'D',
|
||||
reduceTo: 'last',
|
||||
reduceTo: ReduceOperators.LAST,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'max',
|
||||
@@ -1164,7 +1164,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'last',
|
||||
reduceTo: ReduceOperators.LAST,
|
||||
spaceAggregation: 'avg',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -1210,7 +1210,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'B',
|
||||
reduceTo: 'last',
|
||||
reduceTo: ReduceOperators.LAST,
|
||||
spaceAggregation: 'avg',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -1256,7 +1256,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'C',
|
||||
reduceTo: 'last',
|
||||
reduceTo: ReduceOperators.LAST,
|
||||
spaceAggregation: 'avg',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -1366,7 +1366,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'last',
|
||||
reduceTo: ReduceOperators.LAST,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'max',
|
||||
@@ -1418,7 +1418,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'B',
|
||||
reduceTo: 'last',
|
||||
reduceTo: ReduceOperators.LAST,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'max',
|
||||
@@ -1470,7 +1470,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'C',
|
||||
reduceTo: 'last',
|
||||
reduceTo: ReduceOperators.LAST,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'max',
|
||||
@@ -1522,7 +1522,7 @@ export const getClusterMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'D',
|
||||
reduceTo: 'last',
|
||||
reduceTo: ReduceOperators.LAST,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'max',
|
||||
|
||||
@@ -4,7 +4,7 @@ import { PANEL_TYPES } from 'constants/queryBuilder';
|
||||
import { GetQueryResultsProps } from 'lib/dashboard/getQueryResults';
|
||||
import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
import { EQueryType } from 'types/common/dashboard';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
import { DataSource, ReduceOperators } from 'types/common/queryBuilder';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
export const daemonSetWidgetInfo = [
|
||||
@@ -126,7 +126,7 @@ export const getDaemonSetMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -176,7 +176,7 @@ export const getDaemonSetMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'B',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -226,7 +226,7 @@ export const getDaemonSetMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'C',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -310,7 +310,7 @@ export const getDaemonSetMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -360,7 +360,7 @@ export const getDaemonSetMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'B',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -410,7 +410,7 @@ export const getDaemonSetMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'C',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -507,7 +507,7 @@ export const getDaemonSetMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'rate',
|
||||
@@ -604,7 +604,7 @@ export const getDaemonSetMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'increase',
|
||||
|
||||
@@ -4,7 +4,7 @@ import { PANEL_TYPES } from 'constants/queryBuilder';
|
||||
import { GetQueryResultsProps } from 'lib/dashboard/getQueryResults';
|
||||
import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
import { EQueryType } from 'types/common/dashboard';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
import { DataSource, ReduceOperators } from 'types/common/queryBuilder';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
export const deploymentWidgetInfo = [
|
||||
@@ -111,7 +111,7 @@ export const getDeploymentMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -150,7 +150,7 @@ export const getDeploymentMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'B',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -189,7 +189,7 @@ export const getDeploymentMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'C',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -262,7 +262,7 @@ export const getDeploymentMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -301,7 +301,7 @@ export const getDeploymentMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'B',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -340,7 +340,7 @@ export const getDeploymentMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'C',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -426,7 +426,7 @@ export const getDeploymentMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'rate',
|
||||
@@ -512,7 +512,7 @@ export const getDeploymentMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'increase',
|
||||
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
TagFilterItem,
|
||||
} from 'types/api/queryBuilder/queryBuilderData';
|
||||
import { EQueryType } from 'types/common/dashboard';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
import { DataSource, ReduceOperators } from 'types/common/queryBuilder';
|
||||
import { nanoToMilli } from 'utils/timeUtils';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
@@ -73,7 +73,7 @@ export const getEntityEventsOrLogsQueryPayload = (
|
||||
],
|
||||
groupBy: [],
|
||||
legend: '',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
offset: 0,
|
||||
pageSize: 100,
|
||||
},
|
||||
@@ -223,7 +223,7 @@ export const getEntityTracesQueryPayload = (
|
||||
],
|
||||
groupBy: [],
|
||||
legend: '',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
},
|
||||
],
|
||||
queryFormulas: [],
|
||||
|
||||
@@ -4,7 +4,7 @@ import { PANEL_TYPES } from 'constants/queryBuilder';
|
||||
import { GetQueryResultsProps } from 'lib/dashboard/getQueryResults';
|
||||
import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
import { EQueryType } from 'types/common/dashboard';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
import { DataSource, ReduceOperators } from 'types/common/queryBuilder';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
export const jobWidgetInfo = [
|
||||
@@ -101,7 +101,7 @@ export const getJobMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -185,7 +185,7 @@ export const getJobMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -282,7 +282,7 @@ export const getJobMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'rate',
|
||||
@@ -379,7 +379,7 @@ export const getJobMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'increase',
|
||||
|
||||
@@ -4,7 +4,7 @@ import { PANEL_TYPES } from 'constants/queryBuilder';
|
||||
import { GetQueryResultsProps } from 'lib/dashboard/getQueryResults';
|
||||
import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
import { EQueryType } from 'types/common/dashboard';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
import { DataSource, ReduceOperators } from 'types/common/queryBuilder';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
export const namespaceWidgetInfo = [
|
||||
@@ -185,7 +185,7 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -224,7 +224,7 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'B',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'latest',
|
||||
@@ -263,7 +263,7 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'C',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'min',
|
||||
@@ -302,7 +302,7 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'D',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'max',
|
||||
@@ -375,7 +375,7 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -414,7 +414,7 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'B',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'latest',
|
||||
@@ -453,7 +453,7 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'C',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -492,7 +492,7 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'D',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -531,7 +531,7 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'E',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'min',
|
||||
@@ -570,7 +570,7 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'F',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'max',
|
||||
@@ -650,7 +650,7 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
limit: 20,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -730,7 +730,7 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
limit: 10,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -816,7 +816,7 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'rate',
|
||||
@@ -902,7 +902,7 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'increase',
|
||||
@@ -982,7 +982,7 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'last',
|
||||
reduceTo: ReduceOperators.LAST,
|
||||
spaceAggregation: 'max',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'latest',
|
||||
@@ -1028,7 +1028,7 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'B',
|
||||
reduceTo: 'last',
|
||||
reduceTo: ReduceOperators.LAST,
|
||||
spaceAggregation: 'max',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'latest',
|
||||
@@ -1074,7 +1074,7 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'C',
|
||||
reduceTo: 'last',
|
||||
reduceTo: ReduceOperators.LAST,
|
||||
spaceAggregation: 'max',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'latest',
|
||||
@@ -1160,7 +1160,7 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'last',
|
||||
reduceTo: ReduceOperators.LAST,
|
||||
spaceAggregation: 'max',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'latest',
|
||||
@@ -1212,7 +1212,7 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'B',
|
||||
reduceTo: 'last',
|
||||
reduceTo: ReduceOperators.LAST,
|
||||
spaceAggregation: 'max',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'latest',
|
||||
@@ -1292,7 +1292,7 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'last',
|
||||
reduceTo: ReduceOperators.LAST,
|
||||
spaceAggregation: 'max',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'latest',
|
||||
@@ -1338,7 +1338,7 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'B',
|
||||
reduceTo: 'last',
|
||||
reduceTo: ReduceOperators.LAST,
|
||||
spaceAggregation: 'max',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'latest',
|
||||
@@ -1384,7 +1384,7 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'C',
|
||||
reduceTo: 'last',
|
||||
reduceTo: ReduceOperators.LAST,
|
||||
spaceAggregation: 'max',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'latest',
|
||||
@@ -1430,7 +1430,7 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'D',
|
||||
reduceTo: 'last',
|
||||
reduceTo: ReduceOperators.LAST,
|
||||
spaceAggregation: 'max',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'latest',
|
||||
@@ -1510,7 +1510,7 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'last',
|
||||
reduceTo: ReduceOperators.LAST,
|
||||
spaceAggregation: 'max',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'latest',
|
||||
@@ -1556,7 +1556,7 @@ export const getNamespaceMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'B',
|
||||
reduceTo: 'last',
|
||||
reduceTo: ReduceOperators.LAST,
|
||||
spaceAggregation: 'max',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
|
||||
@@ -4,7 +4,7 @@ import { PANEL_TYPES } from 'constants/queryBuilder';
|
||||
import { GetQueryResultsProps } from 'lib/dashboard/getQueryResults';
|
||||
import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
import { EQueryType } from 'types/common/dashboard';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
import { DataSource, ReduceOperators } from 'types/common/queryBuilder';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
export const nodeWidgetInfo = [
|
||||
@@ -178,7 +178,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -217,7 +217,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'B',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'max',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'latest',
|
||||
@@ -256,7 +256,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'C',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'latest',
|
||||
@@ -295,7 +295,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'D',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'max',
|
||||
@@ -334,7 +334,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'E',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'min',
|
||||
@@ -407,7 +407,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -446,7 +446,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'B',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'max',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'latest',
|
||||
@@ -485,7 +485,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'C',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'latest',
|
||||
@@ -524,7 +524,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'D',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'max',
|
||||
@@ -563,7 +563,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'E',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'min',
|
||||
@@ -602,7 +602,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'F',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -641,7 +641,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'G',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -714,7 +714,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -753,7 +753,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'B',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'max',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'latest',
|
||||
@@ -792,7 +792,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'C',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'latest',
|
||||
@@ -878,7 +878,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -917,7 +917,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'B',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'max',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'latest',
|
||||
@@ -956,7 +956,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'C',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'latest',
|
||||
@@ -1049,7 +1049,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
limit: 10,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -1129,7 +1129,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
limit: 10,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -1215,7 +1215,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'increase',
|
||||
@@ -1301,7 +1301,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'rate',
|
||||
@@ -1374,7 +1374,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -1413,7 +1413,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'B',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -1452,7 +1452,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'C',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -1525,7 +1525,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -1564,7 +1564,7 @@ export const getNodeMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'B',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
|
||||
@@ -4,7 +4,7 @@ import { PANEL_TYPES } from 'constants/queryBuilder';
|
||||
import { GetQueryResultsProps } from 'lib/dashboard/getQueryResults';
|
||||
import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
import { EQueryType } from 'types/common/dashboard';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
import { DataSource, ReduceOperators } from 'types/common/queryBuilder';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
export const podWidgetInfo = [
|
||||
@@ -228,7 +228,7 @@ export const getPodMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -278,7 +278,7 @@ export const getPodMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'B',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'max',
|
||||
@@ -328,7 +328,7 @@ export const getPodMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'C',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'min',
|
||||
@@ -412,7 +412,7 @@ export const getPodMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -462,7 +462,7 @@ export const getPodMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'B',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -512,7 +512,7 @@ export const getPodMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'C',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'max',
|
||||
@@ -562,7 +562,7 @@ export const getPodMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'D',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'min',
|
||||
@@ -612,7 +612,7 @@ export const getPodMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'E',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'max',
|
||||
@@ -662,7 +662,7 @@ export const getPodMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'F',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'min',
|
||||
@@ -746,7 +746,7 @@ export const getPodMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -796,7 +796,7 @@ export const getPodMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'B',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'max',
|
||||
@@ -846,7 +846,7 @@ export const getPodMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'C',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'min',
|
||||
@@ -930,7 +930,7 @@ export const getPodMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -980,7 +980,7 @@ export const getPodMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'B',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -1030,7 +1030,7 @@ export const getPodMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'C',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'max',
|
||||
@@ -1080,7 +1080,7 @@ export const getPodMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'D',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'max',
|
||||
@@ -1130,7 +1130,7 @@ export const getPodMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'E',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'min',
|
||||
@@ -1180,7 +1180,7 @@ export const getPodMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'F',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'min',
|
||||
@@ -1264,7 +1264,7 @@ export const getPodMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -1314,7 +1314,7 @@ export const getPodMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'B',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'avg',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -1405,7 +1405,7 @@ export const getPodMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -1496,7 +1496,7 @@ export const getPodMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -1587,7 +1587,7 @@ export const getPodMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -1644,7 +1644,7 @@ export const getPodMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'B',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'max',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'latest',
|
||||
@@ -1701,7 +1701,7 @@ export const getPodMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'C',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'max',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'latest',
|
||||
@@ -1805,7 +1805,7 @@ export const getPodMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -1862,7 +1862,7 @@ export const getPodMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'B',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -1919,7 +1919,7 @@ export const getPodMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'C',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -2010,7 +2010,7 @@ export const getPodMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -2067,7 +2067,7 @@ export const getPodMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'B',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'max',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'latest',
|
||||
@@ -2124,7 +2124,7 @@ export const getPodMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'C',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'max',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'latest',
|
||||
@@ -2234,7 +2234,7 @@ export const getPodMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'rate',
|
||||
@@ -2331,7 +2331,7 @@ export const getPodMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'increase',
|
||||
@@ -2415,7 +2415,7 @@ export const getPodMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -2465,7 +2465,7 @@ export const getPodMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'B',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -2515,7 +2515,7 @@ export const getPodMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'C',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
|
||||
@@ -4,7 +4,7 @@ import { PANEL_TYPES } from 'constants/queryBuilder';
|
||||
import { GetQueryResultsProps } from 'lib/dashboard/getQueryResults';
|
||||
import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
import { EQueryType } from 'types/common/dashboard';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
import { DataSource, ReduceOperators } from 'types/common/queryBuilder';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
export const statefulSetWidgetInfo = [
|
||||
@@ -139,7 +139,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -189,7 +189,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'B',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'latest',
|
||||
@@ -239,7 +239,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'C',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'latest',
|
||||
@@ -309,7 +309,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'avg',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -359,7 +359,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'B',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'avg',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -429,7 +429,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -479,7 +479,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'B',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'latest',
|
||||
@@ -529,7 +529,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'C',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'latest',
|
||||
@@ -599,7 +599,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'avg',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -649,7 +649,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'B',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'avg',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -732,7 +732,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'rate',
|
||||
@@ -815,7 +815,7 @@ export const getStatefulSetMetricsQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'increase',
|
||||
|
||||
@@ -4,7 +4,7 @@ import { PANEL_TYPES } from 'constants/queryBuilder';
|
||||
import { GetQueryResultsProps } from 'lib/dashboard/getQueryResults';
|
||||
import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
import { EQueryType } from 'types/common/dashboard';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
import { DataSource, ReduceOperators } from 'types/common/queryBuilder';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
export const volumeWidgetInfo = [
|
||||
@@ -141,7 +141,7 @@ export const getVolumeQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'sum',
|
||||
reduceTo: ReduceOperators.SUM,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -233,7 +233,7 @@ export const getVolumeQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'sum',
|
||||
reduceTo: ReduceOperators.SUM,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -324,7 +324,7 @@ export const getVolumeQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'sum',
|
||||
reduceTo: ReduceOperators.SUM,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -416,7 +416,7 @@ export const getVolumeQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'sum',
|
||||
reduceTo: ReduceOperators.SUM,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -508,7 +508,7 @@ export const getVolumeQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'sum',
|
||||
reduceTo: ReduceOperators.SUM,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
|
||||
@@ -29,8 +29,8 @@ import useComponentPermission from 'hooks/useComponentPermission';
|
||||
import useDebouncedFn from 'hooks/useDebouncedFunction';
|
||||
import useInterval from 'hooks/useInterval';
|
||||
import { useNotifications } from 'hooks/useNotifications';
|
||||
import { useSafeNavigate } from 'hooks/useSafeNavigate';
|
||||
import useUrlQuery from 'hooks/useUrlQuery';
|
||||
import history from 'lib/history';
|
||||
import { mapQueryDataFromApi } from 'lib/newQueryBuilder/queryBuilderMappers/mapQueryDataFromApi';
|
||||
import { useAppContext } from 'providers/App/App';
|
||||
import { useCallback, useState } from 'react';
|
||||
@@ -50,6 +50,7 @@ const { Search } = Input;
|
||||
|
||||
function ListAlert({ allAlertRules, refetch }: ListAlertProps): JSX.Element {
|
||||
const { t } = useTranslation('common');
|
||||
const { safeNavigate } = useSafeNavigate();
|
||||
const { user } = useAppContext();
|
||||
const [addNewAlert, action] = useComponentPermission(
|
||||
['add_new_alert', 'action'],
|
||||
@@ -112,7 +113,8 @@ function ListAlert({ allAlertRules, refetch }: ListAlertProps): JSX.Element {
|
||||
number: allAlertRules?.length,
|
||||
layout: 'new',
|
||||
});
|
||||
history.push(`${ROUTES.ALERTS_NEW}?showNewCreateAlertsPage=true`);
|
||||
params.set(QueryParams.showNewCreateAlertsPage, 'true');
|
||||
safeNavigate(`${ROUTES.ALERT_TYPE_SELECTION}?${params.toString()}`);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
@@ -121,7 +123,7 @@ function ListAlert({ allAlertRules, refetch }: ListAlertProps): JSX.Element {
|
||||
number: allAlertRules?.length,
|
||||
layout: 'classic',
|
||||
});
|
||||
history.push(ROUTES.ALERTS_NEW);
|
||||
safeNavigate(ROUTES.ALERT_TYPE_SELECTION);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
@@ -161,7 +163,7 @@ function ListAlert({ allAlertRules, refetch }: ListAlertProps): JSX.Element {
|
||||
if (openInNewTab) {
|
||||
window.open(`${ROUTES.ALERT_OVERVIEW}?${params.toString()}`, '_blank');
|
||||
} else {
|
||||
history.push(`${ROUTES.ALERT_OVERVIEW}?${params.toString()}`);
|
||||
safeNavigate(`${ROUTES.ALERT_OVERVIEW}?${params.toString()}`);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -190,7 +192,7 @@ function ListAlert({ allAlertRules, refetch }: ListAlertProps): JSX.Element {
|
||||
setTimeout(() => {
|
||||
const clonedAlert = refetchData.payload[refetchData.payload.length - 1];
|
||||
params.set(QueryParams.ruleId, String(clonedAlert.id));
|
||||
history.push(`${ROUTES.EDIT_ALERTS}?${params.toString()}`);
|
||||
safeNavigate(`${ROUTES.EDIT_ALERTS}?${params.toString()}`);
|
||||
}, 2000);
|
||||
}
|
||||
if (status === 'error') {
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
} from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
import { Query, TagFilter } from 'types/api/queryBuilder/queryBuilderData';
|
||||
import { EQueryType } from 'types/common/dashboard';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
import { DataSource, ReduceOperators } from 'types/common/queryBuilder';
|
||||
|
||||
export const mockLog: ILog = {
|
||||
id: 'test-log-id',
|
||||
@@ -54,7 +54,7 @@ export const mockQuery: Query = {
|
||||
op: 'AND',
|
||||
},
|
||||
expression: 'A',
|
||||
reduceTo: 'sum',
|
||||
reduceTo: ReduceOperators.SUM,
|
||||
},
|
||||
],
|
||||
queryFormulas: [],
|
||||
|
||||
@@ -3,7 +3,7 @@ import { PANEL_TYPES } from 'constants/queryBuilder';
|
||||
import { GetQueryResultsProps } from 'lib/dashboard/getQueryResults';
|
||||
import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
import { EQueryType } from 'types/common/dashboard';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
import { DataSource, ReduceOperators } from 'types/common/queryBuilder';
|
||||
|
||||
export const getPodQueryPayload = (
|
||||
clusterName: string,
|
||||
@@ -114,7 +114,7 @@ export const getPodQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -191,7 +191,7 @@ export const getPodQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -268,7 +268,7 @@ export const getPodQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'sum',
|
||||
reduceTo: ReduceOperators.SUM,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -325,7 +325,7 @@ export const getPodQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'B',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'latest',
|
||||
@@ -409,7 +409,7 @@ export const getPodQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'sum',
|
||||
reduceTo: ReduceOperators.SUM,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -466,7 +466,7 @@ export const getPodQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'B',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'latest',
|
||||
@@ -553,7 +553,7 @@ export const getPodQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'sum',
|
||||
reduceTo: ReduceOperators.SUM,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -614,7 +614,7 @@ export const getPodQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'B',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'latest',
|
||||
@@ -702,7 +702,7 @@ export const getPodQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'sum',
|
||||
reduceTo: ReduceOperators.SUM,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -763,7 +763,7 @@ export const getPodQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'B',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'latest',
|
||||
@@ -851,7 +851,7 @@ export const getPodQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'sum',
|
||||
reduceTo: ReduceOperators.SUM,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -912,7 +912,7 @@ export const getPodQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'B',
|
||||
reduceTo: 'sum',
|
||||
reduceTo: ReduceOperators.SUM,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -1001,7 +1001,7 @@ export const getPodQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'sum',
|
||||
reduceTo: ReduceOperators.SUM,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'rate',
|
||||
@@ -1122,7 +1122,7 @@ export const getNodeQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'sum',
|
||||
reduceTo: ReduceOperators.SUM,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'rate',
|
||||
@@ -1171,7 +1171,7 @@ export const getNodeQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'B',
|
||||
reduceTo: 'sum',
|
||||
reduceTo: ReduceOperators.SUM,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -1260,7 +1260,7 @@ export const getNodeQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'sum',
|
||||
reduceTo: ReduceOperators.SUM,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -1309,7 +1309,7 @@ export const getNodeQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'B',
|
||||
reduceTo: 'sum',
|
||||
reduceTo: ReduceOperators.SUM,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -1412,7 +1412,7 @@ export const getNodeQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'sum',
|
||||
reduceTo: ReduceOperators.SUM,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'rate',
|
||||
@@ -1493,7 +1493,7 @@ export const getNodeQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'sum',
|
||||
reduceTo: ReduceOperators.SUM,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -1554,7 +1554,7 @@ export const getNodeQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'B',
|
||||
reduceTo: 'sum',
|
||||
reduceTo: ReduceOperators.SUM,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -1675,7 +1675,7 @@ export const getHostQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'rate',
|
||||
@@ -1716,7 +1716,7 @@ export const getHostQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'B',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'rate',
|
||||
@@ -1792,7 +1792,7 @@ export const getHostQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -1853,7 +1853,7 @@ export const getHostQueryPayload = (
|
||||
limit: 30,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -1894,7 +1894,7 @@ export const getHostQueryPayload = (
|
||||
limit: 30,
|
||||
orderBy: [],
|
||||
queryName: 'B',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -1935,7 +1935,7 @@ export const getHostQueryPayload = (
|
||||
limit: 30,
|
||||
orderBy: [],
|
||||
queryName: 'C',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -2017,7 +2017,7 @@ export const getHostQueryPayload = (
|
||||
limit: 30,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'rate',
|
||||
@@ -2093,7 +2093,7 @@ export const getHostQueryPayload = (
|
||||
limit: 30,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'rate',
|
||||
@@ -2169,7 +2169,7 @@ export const getHostQueryPayload = (
|
||||
limit: 30,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'rate',
|
||||
@@ -2245,7 +2245,7 @@ export const getHostQueryPayload = (
|
||||
limit: 30,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'rate',
|
||||
@@ -2321,7 +2321,7 @@ export const getHostQueryPayload = (
|
||||
limit: 30,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -2382,7 +2382,7 @@ export const getHostQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'rate',
|
||||
@@ -2464,7 +2464,7 @@ export const getHostQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'rate',
|
||||
@@ -2539,7 +2539,7 @@ export const getHostQueryPayload = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'max',
|
||||
|
||||
@@ -6,7 +6,11 @@ import { cleanup, render, screen, waitFor } from 'tests/test-utils';
|
||||
import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
import { Query, QueryState } from 'types/api/queryBuilder/queryBuilderData';
|
||||
import { EQueryType } from 'types/common/dashboard';
|
||||
import { DataSource, QueryBuilderContextType } from 'types/common/queryBuilder';
|
||||
import {
|
||||
DataSource,
|
||||
QueryBuilderContextType,
|
||||
ReduceOperators,
|
||||
} from 'types/common/queryBuilder';
|
||||
import { explorerViewToPanelType } from 'utils/explorerUtils';
|
||||
|
||||
import LogExplorerQuerySection from './index';
|
||||
@@ -166,7 +170,7 @@ const createMockQuery = (filterExpression?: string): Query => ({
|
||||
orderBy: [{ columnName: 'timestamp', order: 'desc' }],
|
||||
pageSize: 0,
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
stepInterval: 60,
|
||||
},
|
||||
],
|
||||
|
||||
@@ -66,7 +66,7 @@ describe('useInitialQuery - Priority-Based Resource Filtering', () => {
|
||||
queryName: 'A',
|
||||
expression: 'A',
|
||||
disabled: false,
|
||||
reduceTo: 'avg' as ReduceOperators,
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
legend: '',
|
||||
},
|
||||
],
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
IBuilderQuery,
|
||||
} from 'types/api/queryBuilder/queryBuilderData';
|
||||
import { EQueryType } from 'types/common/dashboard';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
import { DataSource, ReduceOperators } from 'types/common/queryBuilder';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
|
||||
interface GetWidgetQueryProps {
|
||||
@@ -101,7 +101,7 @@ export const getTotalLogSizeWidgetData = (): Widgets =>
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'sum',
|
||||
reduceTo: ReduceOperators.SUM,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'increase',
|
||||
@@ -138,7 +138,7 @@ export const getTotalTraceSizeWidgetData = (): Widgets =>
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'sum',
|
||||
reduceTo: ReduceOperators.SUM,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'increase',
|
||||
@@ -175,7 +175,7 @@ export const getTotalMetricDatapointCountWidgetData = (): Widgets =>
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'sum',
|
||||
reduceTo: ReduceOperators.SUM,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'increase',
|
||||
@@ -212,7 +212,7 @@ export const getLogCountWidgetData = (): Widgets =>
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'increase',
|
||||
@@ -249,7 +249,7 @@ export const getLogSizeWidgetData = (): Widgets =>
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'increase',
|
||||
@@ -286,7 +286,7 @@ export const getSpanCountWidgetData = (): Widgets =>
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'increase',
|
||||
@@ -323,7 +323,7 @@ export const getSpanSizeWidgetData = (): Widgets =>
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'increase',
|
||||
@@ -360,7 +360,7 @@ export const getMetricCountWidgetData = (): Widgets =>
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'increase',
|
||||
|
||||
@@ -9,6 +9,7 @@ import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData';
|
||||
import {
|
||||
MetricAggregateOperator,
|
||||
QueryBuilderData,
|
||||
ReduceOperators,
|
||||
Temporality,
|
||||
} from 'types/common/queryBuilder';
|
||||
|
||||
@@ -51,7 +52,7 @@ export const getQueryBuilderQueries = ({
|
||||
items: filterItems[index],
|
||||
op: 'AND',
|
||||
},
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: spaceAggregateOperators[index],
|
||||
timeAggregation: timeAggregateOperators[index],
|
||||
dataSource,
|
||||
@@ -95,7 +96,7 @@ export const getQueryBuilderQuerieswithFormula = ({
|
||||
aggregateAttribute: autocompleteData[index],
|
||||
queryName: alphabet[index],
|
||||
expression: alphabet[index],
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
filters: {
|
||||
items: additionalItems[index],
|
||||
op: 'AND',
|
||||
|
||||
@@ -4,7 +4,7 @@ import { SpaceAggregation, TimeAggregation } from 'api/v5/v5';
|
||||
import { initialQueriesMap } from 'constants/queryBuilder';
|
||||
import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
import { Query } from 'types/api/queryBuilder/queryBuilderData';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
import { DataSource, ReduceOperators } from 'types/common/queryBuilder';
|
||||
|
||||
export function formatTimestampToReadableDate(timestamp: string): string {
|
||||
const date = new Date(timestamp);
|
||||
@@ -114,7 +114,7 @@ export function getMetricDetailsQuery(
|
||||
metricName,
|
||||
timeAggregation: timeAggregation as TimeAggregation,
|
||||
spaceAggregation: spaceAggregation as SpaceAggregation,
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
temporality: '',
|
||||
},
|
||||
],
|
||||
|
||||
@@ -3,7 +3,7 @@ import { useFullScreenHandle } from 'react-full-screen';
|
||||
import Description from './DashboardDescription';
|
||||
import GridGraphs from './GridGraphs';
|
||||
|
||||
function NewDashboard(): JSX.Element {
|
||||
function DashboardContainer(): JSX.Element {
|
||||
const handle = useFullScreenHandle();
|
||||
return (
|
||||
<div>
|
||||
@@ -13,4 +13,4 @@ function NewDashboard(): JSX.Element {
|
||||
);
|
||||
}
|
||||
|
||||
export default NewDashboard;
|
||||
export default DashboardContainer;
|
||||
|
||||
@@ -20,6 +20,16 @@
|
||||
width: 32px;
|
||||
}
|
||||
}
|
||||
|
||||
.y-axis-unit-selector-v2 {
|
||||
flex-direction: row !important;
|
||||
align-items: center;
|
||||
gap: 24px !important;
|
||||
|
||||
.y-axis-unit-selector-component {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.lightMode {
|
||||
|
||||
@@ -7,18 +7,19 @@ import { isEmpty } from 'lodash-es';
|
||||
import { Dispatch, SetStateAction, useCallback, useEffect } from 'react';
|
||||
import { ColumnUnit } from 'types/api/dashboard/getAll';
|
||||
|
||||
import YAxisUnitSelector from '../YAxisUnitSelector';
|
||||
import YAxisUnitSelectorV2 from '../DashboardYAxisUnitSelectorWrapper';
|
||||
|
||||
interface ColumnUnitSelectorProps {
|
||||
columnUnits: ColumnUnit;
|
||||
setColumnUnits: Dispatch<SetStateAction<ColumnUnit>>;
|
||||
isNewDashboard: boolean;
|
||||
}
|
||||
|
||||
export function ColumnUnitSelector(
|
||||
props: ColumnUnitSelectorProps,
|
||||
): JSX.Element {
|
||||
const { currentQuery } = useQueryBuilder();
|
||||
const { columnUnits, setColumnUnits } = props;
|
||||
const { columnUnits, setColumnUnits, isNewDashboard } = props;
|
||||
|
||||
const aggregationQueries = useGetQueryLabels(currentQuery);
|
||||
|
||||
@@ -71,19 +72,22 @@ export function ColumnUnitSelector(
|
||||
return (
|
||||
<section className="column-unit-selector">
|
||||
<Typography.Text className="heading">Column Units</Typography.Text>
|
||||
{aggregationQueries.map(({ value, label }) => (
|
||||
<YAxisUnitSelector
|
||||
value={columnUnits[value] || ''}
|
||||
onSelect={(unitValue: string): void =>
|
||||
handleColumnUnitSelect(value, unitValue)
|
||||
}
|
||||
fieldLabel={label}
|
||||
key={value}
|
||||
handleClear={(): void => {
|
||||
handleColumnUnitSelect(value, '');
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
{aggregationQueries.map(({ value, label }) => {
|
||||
const baseQueryName = value.split('.')[0];
|
||||
return (
|
||||
<YAxisUnitSelectorV2
|
||||
value={columnUnits[value] || ''}
|
||||
onSelect={(unitValue: string): void =>
|
||||
handleColumnUnitSelect(value, unitValue)
|
||||
}
|
||||
fieldLabel={label}
|
||||
key={value}
|
||||
selectedQueryName={baseQueryName}
|
||||
// Update the column unit value automatically only in create mode
|
||||
shouldUpdateYAxisUnit={isNewDashboard}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import { QueryBuilderProvider } from 'providers/QueryBuilder';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { render } from 'tests/test-utils';
|
||||
import { Query } from 'types/api/queryBuilder/queryBuilderData';
|
||||
import { ReduceOperators } from 'types/common/queryBuilder';
|
||||
|
||||
import { ColumnUnitSelector } from '../ColumnUnitSelector';
|
||||
|
||||
@@ -42,7 +43,7 @@ const compositeQueryParam = {
|
||||
},
|
||||
],
|
||||
legend: '',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
},
|
||||
],
|
||||
queryFormulas: [
|
||||
@@ -98,7 +99,12 @@ describe('Column unit selector panel unit test', () => {
|
||||
(useLocation as jest.Mock).mockReturnValue(mockLocation);
|
||||
const { getByText } = render(
|
||||
<QueryBuilderProvider>
|
||||
<ColumnUnitSelector columnUnits={{}} setColumnUnits={(): void => {}} />,
|
||||
<ColumnUnitSelector
|
||||
columnUnits={{}}
|
||||
setColumnUnits={(): void => {}}
|
||||
isNewDashboard={false}
|
||||
/>
|
||||
,
|
||||
</QueryBuilderProvider>,
|
||||
);
|
||||
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
import { Typography } from 'antd';
|
||||
import YAxisUnitSelectorComponent from 'components/YAxisUnitSelector';
|
||||
import { YAxisSource } from 'components/YAxisUnitSelector/types';
|
||||
import useGetYAxisUnit from 'hooks/useGetYAxisUnit';
|
||||
import { Dispatch, SetStateAction, useEffect } from 'react';
|
||||
|
||||
type OnSelectType = Dispatch<SetStateAction<string>> | ((val: string) => void);
|
||||
|
||||
/**
|
||||
* Wrapper component for the y-axis unit selector for dashboards.
|
||||
*/
|
||||
function DashboardYAxisUnitSelectorWrapper({
|
||||
value,
|
||||
onSelect,
|
||||
fieldLabel,
|
||||
shouldUpdateYAxisUnit,
|
||||
selectedQueryName,
|
||||
}: {
|
||||
value: string;
|
||||
onSelect: OnSelectType;
|
||||
fieldLabel: string;
|
||||
shouldUpdateYAxisUnit: boolean;
|
||||
selectedQueryName?: string;
|
||||
}): JSX.Element {
|
||||
const { yAxisUnit: initialYAxisUnit, isLoading } = useGetYAxisUnit(
|
||||
selectedQueryName,
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (shouldUpdateYAxisUnit) {
|
||||
onSelect(initialYAxisUnit || '');
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [initialYAxisUnit, shouldUpdateYAxisUnit]);
|
||||
|
||||
return (
|
||||
<div className="y-axis-unit-selector-v2">
|
||||
<Typography.Text className="heading">{fieldLabel}</Typography.Text>
|
||||
<YAxisUnitSelectorComponent
|
||||
value={value}
|
||||
onChange={onSelect}
|
||||
initialValue={initialYAxisUnit}
|
||||
source={YAxisSource.DASHBOARDS}
|
||||
loading={isLoading}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
DashboardYAxisUnitSelectorWrapper.defaultProps = {
|
||||
selectedQueryName: undefined,
|
||||
};
|
||||
|
||||
export default DashboardYAxisUnitSelectorWrapper;
|
||||
@@ -191,7 +191,8 @@
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.y-axis-unit-selector {
|
||||
.y-axis-unit-selector,
|
||||
.y-axis-unit-selector-v2 {
|
||||
margin-top: 16px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -224,6 +225,21 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.y-axis-unit-selector-v2 {
|
||||
.y-axis-unit-selector-component {
|
||||
.ant-select {
|
||||
width: 100%;
|
||||
border-radius: 2px;
|
||||
|
||||
.ant-select-selector {
|
||||
border: 1px solid var(--bg-slate-400);
|
||||
background: var(--bg-ink-300);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.soft-min-max {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -444,6 +460,17 @@
|
||||
}
|
||||
}
|
||||
|
||||
.y-axis-unit-selector-v2 {
|
||||
.y-axis-unit-selector-component {
|
||||
.ant-select {
|
||||
.ant-select-selector {
|
||||
border: 1px solid var(--bg-vanilla-300);
|
||||
background: var(--bg-vanilla-300);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.fill-gaps {
|
||||
border: 1px solid var(--bg-vanilla-300);
|
||||
background: var(--bg-vanilla-300);
|
||||
@@ -472,7 +499,8 @@
|
||||
color: var(--bg-ink-400);
|
||||
}
|
||||
|
||||
.y-axis-unit-selector {
|
||||
.y-axis-unit-selector,
|
||||
.y-axis-unit-selector-v2 {
|
||||
.heading {
|
||||
color: var(--bg-ink-400);
|
||||
}
|
||||
|
||||
@@ -15,6 +15,9 @@ const findCategoryByName = (
|
||||
|
||||
type OnSelectType = Dispatch<SetStateAction<string>> | ((val: string) => void);
|
||||
|
||||
/**
|
||||
* @deprecated Use DashboardYAxisUnitSelectorWrapper instead.
|
||||
*/
|
||||
function YAxisUnitSelector({
|
||||
value,
|
||||
onSelect,
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { UniversalYAxisUnit } from 'components/YAxisUnitSelector/types';
|
||||
import * as getYAxisUnitHooks from 'hooks/useGetYAxisUnit';
|
||||
|
||||
import DashboardYAxisUnitSelectorWrapper from '../DashboardYAxisUnitSelectorWrapper';
|
||||
|
||||
describe('YAxisUnitSelectorV2', () => {
|
||||
const mockUseGetYAxisUnit = jest.spyOn(getYAxisUnitHooks, 'default');
|
||||
const onSelect = jest.fn();
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
mockUseGetYAxisUnit.mockReturnValue({
|
||||
yAxisUnit: UniversalYAxisUnit.BYTES,
|
||||
isLoading: false,
|
||||
isError: false,
|
||||
});
|
||||
});
|
||||
|
||||
it('should render the selector with correct label and value', () => {
|
||||
render(
|
||||
<DashboardYAxisUnitSelectorWrapper
|
||||
value={UniversalYAxisUnit.BYTES}
|
||||
onSelect={onSelect}
|
||||
fieldLabel="Bytes label"
|
||||
shouldUpdateYAxisUnit={false}
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(screen.getByText('Bytes label')).toBeInTheDocument();
|
||||
expect(screen.getByText('Bytes (B)')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should call onSelect when showWarning is true and useGetYAxisUnit is called and provides the correct value', () => {
|
||||
mockUseGetYAxisUnit.mockReturnValueOnce({
|
||||
yAxisUnit: UniversalYAxisUnit.SECONDS,
|
||||
isLoading: false,
|
||||
isError: false,
|
||||
});
|
||||
render(
|
||||
<DashboardYAxisUnitSelectorWrapper
|
||||
value={UniversalYAxisUnit.BYTES}
|
||||
onSelect={onSelect}
|
||||
fieldLabel="Bytes label"
|
||||
shouldUpdateYAxisUnit
|
||||
/>,
|
||||
);
|
||||
expect(onSelect).toHaveBeenCalledWith(UniversalYAxisUnit.SECONDS);
|
||||
});
|
||||
|
||||
it('should not call onSelect when showWarning is false', () => {
|
||||
render(
|
||||
<DashboardYAxisUnitSelectorWrapper
|
||||
value={UniversalYAxisUnit.BYTES}
|
||||
onSelect={onSelect}
|
||||
fieldLabel="Bytes label"
|
||||
shouldUpdateYAxisUnit={false}
|
||||
/>,
|
||||
);
|
||||
expect(onSelect).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should call onSelect when yAxisUnit is undefined even if showWarning is true', () => {
|
||||
mockUseGetYAxisUnit.mockReturnValueOnce({
|
||||
yAxisUnit: undefined,
|
||||
isLoading: false,
|
||||
isError: false,
|
||||
});
|
||||
render(
|
||||
<DashboardYAxisUnitSelectorWrapper
|
||||
value={UniversalYAxisUnit.BYTES}
|
||||
onSelect={onSelect}
|
||||
fieldLabel="Bytes label"
|
||||
shouldUpdateYAxisUnit
|
||||
/>,
|
||||
);
|
||||
expect(onSelect).toHaveBeenCalledWith('');
|
||||
});
|
||||
});
|
||||
@@ -168,6 +168,7 @@ describe('RightContainer - Alerts Section', () => {
|
||||
contextLinks: { linksData: [] },
|
||||
setContextLinks: jest.fn(),
|
||||
enableDrillDown: false,
|
||||
isNewDashboard: false,
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
|
||||
@@ -67,11 +67,11 @@ import {
|
||||
panelTypeVsYAxisUnit,
|
||||
} from './constants';
|
||||
import ContextLinks from './ContextLinks';
|
||||
import DashboardYAxisUnitSelectorWrapper from './DashboardYAxisUnitSelectorWrapper';
|
||||
import LegendColors from './LegendColors/LegendColors';
|
||||
import ThresholdSelector from './Threshold/ThresholdSelector';
|
||||
import { ThresholdProps } from './Threshold/types';
|
||||
import { timePreferance } from './timeItems';
|
||||
import YAxisUnitSelector from './YAxisUnitSelector';
|
||||
|
||||
const { TextArea } = Input;
|
||||
const { Option } = Select;
|
||||
@@ -129,6 +129,7 @@ function RightContainer({
|
||||
contextLinks,
|
||||
setContextLinks,
|
||||
enableDrillDown = false,
|
||||
isNewDashboard,
|
||||
}: RightContainerProps): JSX.Element {
|
||||
const { selectedDashboard } = useDashboard();
|
||||
const [inputValue, setInputValue] = useState(title);
|
||||
@@ -348,11 +349,12 @@ function RightContainer({
|
||||
<ColumnUnitSelector
|
||||
columnUnits={columnUnits}
|
||||
setColumnUnits={setColumnUnits}
|
||||
isNewDashboard={isNewDashboard}
|
||||
/>
|
||||
)}
|
||||
|
||||
{allowYAxisUnit && (
|
||||
<YAxisUnitSelector
|
||||
<DashboardYAxisUnitSelectorWrapper
|
||||
onSelect={setYAxisUnit}
|
||||
value={yAxisUnit || ''}
|
||||
fieldLabel={
|
||||
@@ -361,6 +363,8 @@ function RightContainer({
|
||||
? 'Unit'
|
||||
: 'Y Axis Unit'
|
||||
}
|
||||
// Only update the y-axis unit value automatically in create mode
|
||||
shouldUpdateYAxisUnit={isNewDashboard}
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -612,6 +616,7 @@ export interface RightContainerProps {
|
||||
contextLinks: ContextLinksData;
|
||||
setContextLinks: Dispatch<SetStateAction<ContextLinksData>>;
|
||||
enableDrillDown?: boolean;
|
||||
isNewDashboard: boolean;
|
||||
}
|
||||
|
||||
RightContainer.defaultProps = {
|
||||
|
||||
@@ -860,6 +860,7 @@ function NewWidget({
|
||||
contextLinks={contextLinks}
|
||||
setContextLinks={setContextLinks}
|
||||
enableDrillDown={enableDrillDown}
|
||||
isNewDashboard={isNewDashboard}
|
||||
/>
|
||||
</OverlayScrollbar>
|
||||
</RightContainerWrapper>
|
||||
|
||||
@@ -18,7 +18,7 @@ import { MetricRangePayloadProps } from 'types/api/metrics/getQueryRange';
|
||||
import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
import { Query } from 'types/api/queryBuilder/queryBuilderData';
|
||||
import { EQueryType } from 'types/common/dashboard';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
import { DataSource, ReduceOperators } from 'types/common/queryBuilder';
|
||||
|
||||
const enum ApplicationLogsType {
|
||||
FROM_LOG_FILE = 'from-log-file',
|
||||
@@ -68,7 +68,7 @@ export default function LogsConnectionStatus(): JSX.Element {
|
||||
],
|
||||
groupBy: [],
|
||||
legend: '',
|
||||
reduceTo: 'sum',
|
||||
reduceTo: ReduceOperators.SUM,
|
||||
offset: 0,
|
||||
pageSize: 100,
|
||||
timeAggregation: '',
|
||||
|
||||
@@ -316,6 +316,7 @@
|
||||
"application performance monitoring",
|
||||
"java",
|
||||
"java agent",
|
||||
"java-agent",
|
||||
"java apm",
|
||||
"java application",
|
||||
"java instrumentation",
|
||||
@@ -596,7 +597,8 @@
|
||||
"traces",
|
||||
"tracing",
|
||||
"ts",
|
||||
"typescript"
|
||||
"typescript",
|
||||
"react native"
|
||||
],
|
||||
"id": "javascript",
|
||||
"imgUrl": "/Logos/javascript.svg",
|
||||
@@ -1982,6 +1984,7 @@
|
||||
],
|
||||
"module": "logs",
|
||||
"relatedSearchKeywords": [
|
||||
"amazon",
|
||||
"aws",
|
||||
"aws lambda logs",
|
||||
"aws lambda nodejs logs",
|
||||
@@ -2057,6 +2060,8 @@
|
||||
"java logs to signoz",
|
||||
"java observability",
|
||||
"logging",
|
||||
"java-agent",
|
||||
"java agent",
|
||||
"logs",
|
||||
"opentelemetry",
|
||||
"otel",
|
||||
@@ -2064,7 +2069,9 @@
|
||||
"otel logs java",
|
||||
"otel-java-sdk",
|
||||
"sdk",
|
||||
"structured logging java"
|
||||
"structured logging java",
|
||||
"Logback",
|
||||
"log4j"
|
||||
],
|
||||
"link": "/docs/userguide/collecting_application_logs_otel_sdk_java/"
|
||||
},
|
||||
@@ -2280,6 +2287,7 @@
|
||||
],
|
||||
"module": "logs",
|
||||
"relatedSearchKeywords": [
|
||||
"amazon",
|
||||
"aws",
|
||||
"aws ec2",
|
||||
"aws ec2 log collection",
|
||||
@@ -2347,6 +2355,7 @@
|
||||
],
|
||||
"module": "infra-monitoring-hosts",
|
||||
"relatedSearchKeywords": [
|
||||
"amazon",
|
||||
"aws",
|
||||
"aws container service",
|
||||
"aws ecs",
|
||||
@@ -2410,6 +2419,7 @@
|
||||
],
|
||||
"module": "infra-monitoring-k8s",
|
||||
"relatedSearchKeywords": [
|
||||
"amazon",
|
||||
"aws",
|
||||
"aws eks",
|
||||
"aws kubernetes",
|
||||
@@ -2472,6 +2482,7 @@
|
||||
],
|
||||
"module": "logs",
|
||||
"relatedSearchKeywords": [
|
||||
"amazon",
|
||||
"aws",
|
||||
"aws elb",
|
||||
"aws elb logs",
|
||||
@@ -2503,6 +2514,7 @@
|
||||
],
|
||||
"module": "logs",
|
||||
"relatedSearchKeywords": [
|
||||
"amazon",
|
||||
"aws",
|
||||
"aws vpc logs",
|
||||
"collect vpc logs",
|
||||
@@ -2533,6 +2545,7 @@
|
||||
],
|
||||
"module": "dashboards",
|
||||
"relatedSearchKeywords": [
|
||||
"amazon",
|
||||
"amazon rds",
|
||||
"aws",
|
||||
"aws database",
|
||||
@@ -2598,6 +2611,7 @@
|
||||
],
|
||||
"module": "dashboards",
|
||||
"relatedSearchKeywords": [
|
||||
"amazon",
|
||||
"aws",
|
||||
"aws lambda",
|
||||
"aws lambda insights",
|
||||
@@ -4431,6 +4445,7 @@
|
||||
"vuejs",
|
||||
"nuxtjs",
|
||||
"svelte",
|
||||
"sveltekit",
|
||||
"nextjs"
|
||||
],
|
||||
"link": "/docs/frontend-monitoring/web-vitals-with-metrics/"
|
||||
@@ -4464,6 +4479,7 @@
|
||||
"vuejs",
|
||||
"nuxtjs",
|
||||
"svelte",
|
||||
"sveltekit",
|
||||
"nextjs"
|
||||
],
|
||||
"link": "/docs/frontend-monitoring/web-vitals-with-traces/"
|
||||
@@ -4504,6 +4520,7 @@
|
||||
"vuejs",
|
||||
"nuxtjs",
|
||||
"svelte",
|
||||
"sveltekit",
|
||||
"nextjs"
|
||||
],
|
||||
"link": "/docs/frontend-monitoring/document-load/"
|
||||
@@ -5412,6 +5429,7 @@
|
||||
"vuejs",
|
||||
"nuxtjs",
|
||||
"svelte",
|
||||
"sveltekit",
|
||||
"nextjs"
|
||||
],
|
||||
"link": "/docs/frontend-monitoring/sending-logs-with-opentelemetry/"
|
||||
@@ -5441,6 +5459,7 @@
|
||||
"vuejs",
|
||||
"nuxtjs",
|
||||
"svelte",
|
||||
"sveltekit",
|
||||
"nextjs"
|
||||
],
|
||||
"link": "/docs/frontend-monitoring/sending-traces-with-opentelemetry/"
|
||||
@@ -5470,6 +5489,7 @@
|
||||
"vuejs",
|
||||
"nuxtjs",
|
||||
"svelte",
|
||||
"sveltekit",
|
||||
"nextjs"
|
||||
],
|
||||
"link": "/docs/frontend-monitoring/sending-metrics-with-opentelemetry/"
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { ReduceOperators } from 'types/common/queryBuilder';
|
||||
|
||||
export const tablePanelWidgetQuery = {
|
||||
id: '727533b0-7718-4f99-a1db-a1875649325c',
|
||||
title: '',
|
||||
@@ -56,7 +58,7 @@ export const tablePanelWidgetQuery = {
|
||||
},
|
||||
],
|
||||
legend: 'latency-per-service',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
},
|
||||
],
|
||||
queryFormulas: [],
|
||||
@@ -245,7 +247,7 @@ export const tablePanelQueryResponse = {
|
||||
},
|
||||
],
|
||||
legend: '',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { ReduceOperators } from 'types/common/queryBuilder';
|
||||
|
||||
export const valuePanelWidget = {
|
||||
id: 'b8b93086-ef01-47bf-9044-1e7abd583be4',
|
||||
title: 'signoz latency in ms',
|
||||
@@ -49,7 +51,7 @@ export const valuePanelWidget = {
|
||||
orderBy: [],
|
||||
groupBy: [],
|
||||
legend: '',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
},
|
||||
],
|
||||
queryFormulas: [],
|
||||
@@ -229,7 +231,7 @@ export const valuePanelQueryResponse = {
|
||||
orderBy: [],
|
||||
groupBy: [],
|
||||
legend: '',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { MetricType } from 'api/metricsExplorer/getMetricsList';
|
||||
import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData';
|
||||
import { ReduceOperators } from 'types/common/queryBuilder';
|
||||
|
||||
import { ReduceToFilter } from './ReduceToFilter';
|
||||
|
||||
@@ -37,7 +38,15 @@ describe('ReduceToFilter', () => {
|
||||
render(
|
||||
<ReduceToFilter
|
||||
query={baseQuery({
|
||||
aggregations: [{ reduceTo: 'sum' } as any],
|
||||
aggregations: [
|
||||
{
|
||||
reduceTo: ReduceOperators.SUM,
|
||||
metricName: 'test',
|
||||
temporality: '',
|
||||
timeAggregation: 'sum',
|
||||
spaceAggregation: 'sum',
|
||||
},
|
||||
],
|
||||
aggregateAttribute: { key: 'test', type: MetricType.SUM },
|
||||
})}
|
||||
onChange={mockOnChange}
|
||||
@@ -51,7 +60,7 @@ describe('ReduceToFilter', () => {
|
||||
render(
|
||||
<ReduceToFilter
|
||||
query={baseQuery({
|
||||
reduceTo: 'max',
|
||||
reduceTo: ReduceOperators.MAX,
|
||||
aggregateAttribute: { key: 'test', type: MetricType.GAUGE },
|
||||
})}
|
||||
onChange={mockOnChange}
|
||||
@@ -60,29 +69,4 @@ describe('ReduceToFilter', () => {
|
||||
|
||||
expect(screen.getByText('Max of values in timeframe')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('updates to sum when aggregateAttribute.type is SUM', async () => {
|
||||
const { rerender } = render(
|
||||
<ReduceToFilter
|
||||
query={baseQuery({
|
||||
aggregateAttribute: { key: 'test', type: MetricType.GAUGE },
|
||||
})}
|
||||
onChange={mockOnChange}
|
||||
/>,
|
||||
);
|
||||
|
||||
rerender(
|
||||
<ReduceToFilter
|
||||
query={baseQuery({
|
||||
aggregateAttribute: { key: 'test2', type: MetricType.SUM },
|
||||
})}
|
||||
onChange={mockOnChange}
|
||||
/>,
|
||||
);
|
||||
|
||||
const reduceToFilterText = (await screen.findByText(
|
||||
'Sum of values in timeframe',
|
||||
)) as HTMLElement;
|
||||
expect(reduceToFilterText).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { Select } from 'antd';
|
||||
import { MetricType } from 'api/metricsExplorer/getMetricsList';
|
||||
import { REDUCE_TO_VALUES } from 'constants/queryBuilder';
|
||||
import { memo, useEffect, useRef, useState } from 'react';
|
||||
import { memo, useEffect, useState } from 'react';
|
||||
import { MetricAggregation } from 'types/api/v5/queryRange';
|
||||
// ** Types
|
||||
import { ReduceOperators } from 'types/common/queryBuilder';
|
||||
@@ -13,10 +12,9 @@ export const ReduceToFilter = memo(function ReduceToFilter({
|
||||
query,
|
||||
onChange,
|
||||
}: ReduceToFilterProps): JSX.Element {
|
||||
const isMounted = useRef<boolean>(false);
|
||||
const [currentValue, setCurrentValue] = useState<
|
||||
SelectOption<ReduceOperators, string>
|
||||
>(REDUCE_TO_VALUES[2]); // default to avg
|
||||
>(REDUCE_TO_VALUES[2]);
|
||||
|
||||
const handleChange = (
|
||||
newValue: SelectOption<ReduceOperators, string>,
|
||||
@@ -27,30 +25,16 @@ export const ReduceToFilter = memo(function ReduceToFilter({
|
||||
|
||||
useEffect(
|
||||
() => {
|
||||
if (!isMounted.current) {
|
||||
const reduceToValue =
|
||||
(query.aggregations?.[0] as MetricAggregation)?.reduceTo || query.reduceTo;
|
||||
const reduceToValue =
|
||||
(query.aggregations?.[0] as MetricAggregation)?.reduceTo || query.reduceTo;
|
||||
|
||||
setCurrentValue(
|
||||
REDUCE_TO_VALUES.find((option) => option.value === reduceToValue) ||
|
||||
REDUCE_TO_VALUES[2],
|
||||
);
|
||||
isMounted.current = true;
|
||||
return;
|
||||
}
|
||||
|
||||
const aggregationAttributeType = query.aggregateAttribute?.type as
|
||||
| MetricType
|
||||
| undefined;
|
||||
|
||||
if (aggregationAttributeType === MetricType.SUM) {
|
||||
handleChange(REDUCE_TO_VALUES[1]);
|
||||
} else {
|
||||
handleChange(REDUCE_TO_VALUES[2]);
|
||||
}
|
||||
setCurrentValue(
|
||||
REDUCE_TO_VALUES.find((option) => option.value === reduceToValue) ||
|
||||
REDUCE_TO_VALUES[2],
|
||||
);
|
||||
},
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
[query.aggregateAttribute?.key],
|
||||
[(query.aggregations?.[0] as MetricAggregation)?.reduceTo, query.reduceTo],
|
||||
);
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { ReduceOperators } from 'types/common/queryBuilder';
|
||||
|
||||
/* eslint-disable sonarjs/no-duplicate-string */
|
||||
export const QueryTableProps: any = {
|
||||
props: {
|
||||
@@ -130,7 +132,7 @@ export const QueryTableProps: any = {
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'rate',
|
||||
@@ -284,7 +286,7 @@ export const WidgetHeaderProps: any = {
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'rate',
|
||||
@@ -613,7 +615,7 @@ export const WidgetHeaderProps: any = {
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'rate',
|
||||
|
||||
@@ -4,7 +4,7 @@ import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
import { TagFilter } from 'types/api/queryBuilder/queryBuilderData';
|
||||
import { Filter } from 'types/api/v5/queryRange';
|
||||
import { EQueryType } from 'types/common/dashboard';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
import { DataSource, ReduceOperators } from 'types/common/queryBuilder';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
/**
|
||||
@@ -55,7 +55,7 @@ export const getSpanLogsQueryPayload = (
|
||||
],
|
||||
groupBy: [],
|
||||
legend: '',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
offset: 0,
|
||||
pageSize: 100,
|
||||
},
|
||||
|
||||
@@ -7,7 +7,11 @@ import {
|
||||
} from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
import { Query, TagFilter } from 'types/api/queryBuilder/queryBuilderData';
|
||||
import { EQueryType } from 'types/common/dashboard';
|
||||
import { DataSource, LogsAggregatorOperator } from 'types/common/queryBuilder';
|
||||
import {
|
||||
DataSource,
|
||||
LogsAggregatorOperator,
|
||||
ReduceOperators,
|
||||
} from 'types/common/queryBuilder';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
|
||||
export const getTraceToLogsQuery = (
|
||||
@@ -58,7 +62,7 @@ export const getTraceToLogsQuery = (
|
||||
legend: '',
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
stepInterval: getStep({
|
||||
start: minTime,
|
||||
end: maxTime,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
import { DataSource, ReduceOperators } from 'types/common/queryBuilder';
|
||||
|
||||
export const BASE_FILTER_QUERY: IBuilderQuery = {
|
||||
queryName: 'A',
|
||||
@@ -32,7 +32,7 @@ export const BASE_FILTER_QUERY: IBuilderQuery = {
|
||||
],
|
||||
groupBy: [],
|
||||
legend: '',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
offset: 0,
|
||||
selectColumns: [],
|
||||
};
|
||||
|
||||
@@ -6,7 +6,11 @@ import {
|
||||
DataTypes,
|
||||
} from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData';
|
||||
import { DataSource, MetricAggregateOperator } from 'types/common/queryBuilder';
|
||||
import {
|
||||
DataSource,
|
||||
MetricAggregateOperator,
|
||||
ReduceOperators,
|
||||
} from 'types/common/queryBuilder';
|
||||
|
||||
import { useQueryBuilder } from '../useQueryBuilder';
|
||||
import { useQueryOperations } from '../useQueryBuilderOperations';
|
||||
@@ -54,7 +58,7 @@ describe('useQueryBuilderOperations - Empty Aggregate Attribute Type', () => {
|
||||
stepInterval: 60,
|
||||
expression: '',
|
||||
disabled: false,
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
legend: '',
|
||||
};
|
||||
|
||||
@@ -189,6 +193,7 @@ describe('useQueryBuilderOperations - Empty Aggregate Attribute Type', () => {
|
||||
metricName: 'new_sum_metric',
|
||||
temporality: '',
|
||||
spaceAggregation: MetricAggregateOperator.SUM,
|
||||
reduceTo: ReduceOperators.SUM,
|
||||
},
|
||||
],
|
||||
}),
|
||||
@@ -208,6 +213,7 @@ describe('useQueryBuilderOperations - Empty Aggregate Attribute Type', () => {
|
||||
metricName: 'original_sum_metric',
|
||||
temporality: '',
|
||||
spaceAggregation: MetricAggregateOperator.SUM,
|
||||
reduceTo: ReduceOperators.SUM,
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -240,6 +246,7 @@ describe('useQueryBuilderOperations - Empty Aggregate Attribute Type', () => {
|
||||
metricName: 'new_sum_metric',
|
||||
temporality: '',
|
||||
spaceAggregation: MetricAggregateOperator.SUM,
|
||||
reduceTo: ReduceOperators.SUM,
|
||||
},
|
||||
],
|
||||
}),
|
||||
@@ -261,6 +268,7 @@ describe('useQueryBuilderOperations - Empty Aggregate Attribute Type', () => {
|
||||
metricName: 'original_gauge',
|
||||
temporality: '',
|
||||
spaceAggregation: '',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -291,6 +299,7 @@ describe('useQueryBuilderOperations - Empty Aggregate Attribute Type', () => {
|
||||
metricName: '',
|
||||
temporality: '',
|
||||
spaceAggregation: MetricAggregateOperator.SUM,
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -316,6 +325,7 @@ describe('useQueryBuilderOperations - Empty Aggregate Attribute Type', () => {
|
||||
metricName: 'new_gauge',
|
||||
temporality: '',
|
||||
spaceAggregation: MetricAggregateOperator.AVG,
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
},
|
||||
],
|
||||
}),
|
||||
|
||||
@@ -43,7 +43,11 @@ import {
|
||||
HandleChangeQueryDataV5,
|
||||
UseQueryOperations,
|
||||
} from 'types/common/operations.types';
|
||||
import { DataSource, MetricAggregateOperator } from 'types/common/queryBuilder';
|
||||
import {
|
||||
DataSource,
|
||||
MetricAggregateOperator,
|
||||
ReduceOperators,
|
||||
} from 'types/common/queryBuilder';
|
||||
import { SelectOption } from 'types/common/select';
|
||||
import { getFormatedLegend } from 'utils/getFormatedLegend';
|
||||
|
||||
@@ -318,6 +322,7 @@ export const useQueryOperations: UseQueryOperations = ({
|
||||
metricName: newQuery.aggregateAttribute?.key || '',
|
||||
temporality: '',
|
||||
spaceAggregation: MetricAggregateOperator.SUM,
|
||||
reduceTo: ReduceOperators.SUM,
|
||||
},
|
||||
];
|
||||
} else if (newQuery.aggregateAttribute?.type === ATTRIBUTE_TYPES.GAUGE) {
|
||||
@@ -327,6 +332,7 @@ export const useQueryOperations: UseQueryOperations = ({
|
||||
metricName: newQuery.aggregateAttribute?.key || '',
|
||||
temporality: '',
|
||||
spaceAggregation: MetricAggregateOperator.AVG,
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
},
|
||||
];
|
||||
} else if (
|
||||
@@ -340,6 +346,7 @@ export const useQueryOperations: UseQueryOperations = ({
|
||||
metricName: newQuery.aggregateAttribute?.key || '',
|
||||
temporality: '',
|
||||
spaceAggregation: MetricAggregateOperator.P90,
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
},
|
||||
];
|
||||
} else {
|
||||
@@ -349,6 +356,7 @@ export const useQueryOperations: UseQueryOperations = ({
|
||||
metricName: newQuery.aggregateAttribute?.key || '',
|
||||
temporality: '',
|
||||
spaceAggregation: '',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@ import {
|
||||
useGetMetrics,
|
||||
} from 'container/MetricsExplorer/Explorer/utils';
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData';
|
||||
import { MetricAggregation } from 'types/api/v5/queryRange';
|
||||
import { EQueryType } from 'types/common/dashboard';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
|
||||
@@ -14,6 +16,19 @@ interface UseGetYAxisUnitResult {
|
||||
isError: boolean;
|
||||
}
|
||||
|
||||
function getMetricNameFromQueryData(queryData: IBuilderQuery): string | null {
|
||||
if (queryData.dataSource !== DataSource.METRICS) {
|
||||
return null;
|
||||
}
|
||||
if (queryData.aggregateAttribute?.key) {
|
||||
return queryData.aggregateAttribute?.key;
|
||||
}
|
||||
if (queryData.aggregations?.length && queryData.aggregations.length > 0) {
|
||||
return (queryData.aggregations?.[0] as MetricAggregation)?.metricName;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook to get the y-axis unit for a given metrics-based query.
|
||||
* @param selectedQueryName - The name of the query to get the y-axis unit for.
|
||||
@@ -45,19 +60,18 @@ function useGetYAxisUnit(
|
||||
// If a selected query name is provided, return the metric name for that query only
|
||||
if (selectedQueryName) {
|
||||
stagedQuery?.builder?.queryData?.forEach((query) => {
|
||||
if (
|
||||
query.queryName === selectedQueryName &&
|
||||
query.aggregateAttribute?.key
|
||||
) {
|
||||
currentMetricNames.push(query.aggregateAttribute?.key);
|
||||
const metricName = getMetricNameFromQueryData(query);
|
||||
if (query.queryName === selectedQueryName && metricName) {
|
||||
currentMetricNames.push(metricName);
|
||||
}
|
||||
});
|
||||
return currentMetricNames.length ? currentMetricNames : null;
|
||||
}
|
||||
// Else, return all metric names
|
||||
stagedQuery?.builder?.queryData?.forEach((query) => {
|
||||
if (query.aggregateAttribute?.key) {
|
||||
currentMetricNames.push(query.aggregateAttribute?.key);
|
||||
const metricName = getMetricNameFromQueryData(query);
|
||||
if (metricName) {
|
||||
currentMetricNames.push(metricName);
|
||||
}
|
||||
});
|
||||
return currentMetricNames.length ? currentMetricNames : null;
|
||||
|
||||
@@ -3,7 +3,7 @@ import { PANEL_TYPES } from 'constants/queryBuilder';
|
||||
import { ICompositeMetricQuery } from 'types/api/alerts/compositeQuery';
|
||||
import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
import { EQueryType } from 'types/common/dashboard';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
import { DataSource, ReduceOperators } from 'types/common/queryBuilder';
|
||||
|
||||
export const compositeQueryWithoutVariables = ({
|
||||
builderQueries: {
|
||||
@@ -26,7 +26,7 @@ export const compositeQueryWithoutVariables = ({
|
||||
limit: 0,
|
||||
offset: 0,
|
||||
pageSize: 0,
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
timeAggregation: 'rate',
|
||||
spaceAggregation: 'sum',
|
||||
ShiftBy: 0,
|
||||
@@ -57,7 +57,7 @@ export const stepIntervalUnchanged = {
|
||||
temporality: '',
|
||||
timeAggregation: 'count',
|
||||
spaceAggregation: 'sum',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
},
|
||||
],
|
||||
functions: [],
|
||||
@@ -70,7 +70,7 @@ export const stepIntervalUnchanged = {
|
||||
orderBy: [],
|
||||
groupBy: [],
|
||||
legend: '',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
source: '',
|
||||
offset: 0,
|
||||
pageSize: 0,
|
||||
@@ -149,7 +149,7 @@ export const compositeQueryWithVariables = ({
|
||||
limit: 0,
|
||||
offset: 0,
|
||||
pageSize: 0,
|
||||
reduceTo: 'sum',
|
||||
reduceTo: ReduceOperators.SUM,
|
||||
timeAggregation: 'rate',
|
||||
spaceAggregation: 'sum',
|
||||
ShiftBy: 0,
|
||||
@@ -180,7 +180,7 @@ export const replaceVariables = {
|
||||
temporality: '',
|
||||
timeAggregation: 'count',
|
||||
spaceAggregation: 'sum',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
},
|
||||
],
|
||||
functions: [],
|
||||
@@ -235,7 +235,7 @@ export const replaceVariables = {
|
||||
},
|
||||
],
|
||||
legend: '{{service_name}}-{{operation}}',
|
||||
reduceTo: 'sum',
|
||||
reduceTo: ReduceOperators.SUM,
|
||||
source: '',
|
||||
offset: 0,
|
||||
pageSize: 0,
|
||||
@@ -265,7 +265,7 @@ export const defaultOutput = {
|
||||
aggregations: [
|
||||
{
|
||||
metricName: '',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
temporality: '',
|
||||
timeAggregation: 'count',
|
||||
@@ -286,7 +286,7 @@ export const defaultOutput = {
|
||||
orderBy: [],
|
||||
pageSize: 0,
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
source: '',
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 240,
|
||||
@@ -324,7 +324,7 @@ export const compositeQueriesWithFunctions = ({
|
||||
limit: 0,
|
||||
offset: 0,
|
||||
pageSize: 0,
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'p90',
|
||||
ShiftBy: 0,
|
||||
},
|
||||
@@ -347,7 +347,7 @@ export const compositeQueriesWithFunctions = ({
|
||||
limit: 0,
|
||||
offset: 0,
|
||||
pageSize: 0,
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
timeAggregation: 'rate',
|
||||
spaceAggregation: 'sum',
|
||||
ShiftBy: 0,
|
||||
@@ -395,7 +395,7 @@ export const outputWithFunctions = {
|
||||
temporality: '',
|
||||
timeAggregation: 'count',
|
||||
spaceAggregation: 'sum',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
},
|
||||
],
|
||||
functions: [],
|
||||
@@ -408,7 +408,7 @@ export const outputWithFunctions = {
|
||||
orderBy: [],
|
||||
groupBy: [],
|
||||
legend: '',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
source: '',
|
||||
offset: 0,
|
||||
pageSize: 0,
|
||||
@@ -432,7 +432,7 @@ export const outputWithFunctions = {
|
||||
temporality: '',
|
||||
timeAggregation: 'count',
|
||||
spaceAggregation: 'sum',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
},
|
||||
],
|
||||
functions: [],
|
||||
@@ -445,7 +445,7 @@ export const outputWithFunctions = {
|
||||
orderBy: [],
|
||||
groupBy: [],
|
||||
legend: '',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
source: '',
|
||||
offset: 0,
|
||||
pageSize: 0,
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { ReduceOperators } from 'types/common/queryBuilder';
|
||||
|
||||
export const explorerView = {
|
||||
status: 'success',
|
||||
data: [
|
||||
@@ -60,7 +62,7 @@ export const explorerView = {
|
||||
order: 'desc',
|
||||
},
|
||||
],
|
||||
reduceTo: 'sum',
|
||||
reduceTo: ReduceOperators.SUM,
|
||||
ShiftBy: 0,
|
||||
},
|
||||
},
|
||||
@@ -116,7 +118,7 @@ export const explorerView = {
|
||||
order: 'desc',
|
||||
},
|
||||
],
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
timeAggregation: 'rate',
|
||||
spaceAggregation: 'sum',
|
||||
ShiftBy: 0,
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { ReduceOperators } from 'types/common/queryBuilder';
|
||||
|
||||
export const publishedPublicDashboardMeta = {
|
||||
status: 'success',
|
||||
data: {
|
||||
@@ -71,7 +73,7 @@ export const publicDashboardResponse = {
|
||||
aggregations: [
|
||||
{
|
||||
metricName: 'container.cpu.time',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
temporality: '',
|
||||
timeAggregation: 'rate',
|
||||
|
||||
56
frontend/src/pages/AlertTypeSelection/AlertTypeSelection.tsx
Normal file
56
frontend/src/pages/AlertTypeSelection/AlertTypeSelection.tsx
Normal file
@@ -0,0 +1,56 @@
|
||||
import { Row } from 'antd';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import { QueryParams } from 'constants/query';
|
||||
import ROUTES from 'constants/routes';
|
||||
import SelectAlertType from 'container/CreateAlertRule/SelectAlertType';
|
||||
import { AlertDetectionTypes } from 'container/FormAlertRules';
|
||||
import { useSafeNavigate } from 'hooks/useSafeNavigate';
|
||||
import useUrlQuery from 'hooks/useUrlQuery';
|
||||
import { useCallback, useEffect } from 'react';
|
||||
import { AlertTypes } from 'types/api/alerts/alertTypes';
|
||||
|
||||
function AlertTypeSelectionPage(): JSX.Element {
|
||||
const { safeNavigate } = useSafeNavigate();
|
||||
const queryParams = useUrlQuery();
|
||||
|
||||
useEffect(() => {
|
||||
logEvent('Alert: New alert data source selection page visited', {});
|
||||
}, []);
|
||||
|
||||
const handleSelectType = useCallback(
|
||||
(type: AlertTypes): void => {
|
||||
// For anamoly based alert, we need to set the ruleType to anomaly_rule
|
||||
// and alertType to metrics_based_alert
|
||||
if (type === AlertTypes.ANOMALY_BASED_ALERT) {
|
||||
queryParams.set(
|
||||
QueryParams.ruleType,
|
||||
AlertDetectionTypes.ANOMALY_DETECTION_ALERT,
|
||||
);
|
||||
queryParams.set(QueryParams.alertType, AlertTypes.METRICS_BASED_ALERT);
|
||||
// For other alerts, we need to set the ruleType to threshold_rule
|
||||
// and alertType to the selected type
|
||||
} else {
|
||||
queryParams.set(QueryParams.ruleType, AlertDetectionTypes.THRESHOLD_ALERT);
|
||||
queryParams.set(QueryParams.alertType, type);
|
||||
}
|
||||
|
||||
const showNewCreateAlertsPageFlag = queryParams.get(
|
||||
QueryParams.showNewCreateAlertsPage,
|
||||
);
|
||||
if (showNewCreateAlertsPageFlag === 'true') {
|
||||
queryParams.set(QueryParams.showNewCreateAlertsPage, 'true');
|
||||
}
|
||||
|
||||
safeNavigate(`${ROUTES.ALERTS_NEW}?${queryParams.toString()}`);
|
||||
},
|
||||
[queryParams, safeNavigate],
|
||||
);
|
||||
|
||||
return (
|
||||
<Row wrap={false}>
|
||||
<SelectAlertType onSelect={handleSelectType} />
|
||||
</Row>
|
||||
);
|
||||
}
|
||||
|
||||
export default AlertTypeSelectionPage;
|
||||
@@ -0,0 +1,184 @@
|
||||
import { fireEvent, render, screen } from '@testing-library/react';
|
||||
import { FeatureKeys } from 'constants/features';
|
||||
import { QueryParams } from 'constants/query';
|
||||
import { AlertDetectionTypes } from 'container/FormAlertRules';
|
||||
import { getAppContextMockState } from 'container/RoutingPolicies/__tests__/testUtils';
|
||||
import * as navigateHooks from 'hooks/useSafeNavigate';
|
||||
import * as useUrlQueryHooks from 'hooks/useUrlQuery';
|
||||
import * as appHooks from 'providers/App/App';
|
||||
import { AlertTypes } from 'types/api/alerts/alertTypes';
|
||||
|
||||
import AlertTypeSelection from '../AlertTypeSelection';
|
||||
|
||||
const useUrlQuerySpy = jest.spyOn(useUrlQueryHooks, 'default');
|
||||
const useSafeNavigateSpy = jest.spyOn(navigateHooks, 'useSafeNavigate');
|
||||
const useAppContextSpy = jest.spyOn(appHooks, 'useAppContext');
|
||||
|
||||
const mockSetUrlQuery = jest.fn();
|
||||
const mockSafeNavigate = jest.fn();
|
||||
const mockToString = jest.fn();
|
||||
const mockGetUrlQuery = jest.fn();
|
||||
|
||||
describe('AlertTypeSelection', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
useAppContextSpy.mockReturnValue(getAppContextMockState());
|
||||
useUrlQuerySpy.mockReturnValue(({
|
||||
set: mockSetUrlQuery,
|
||||
toString: mockToString,
|
||||
get: mockGetUrlQuery,
|
||||
} as Partial<URLSearchParams>) as URLSearchParams);
|
||||
useSafeNavigateSpy.mockReturnValue({
|
||||
safeNavigate: mockSafeNavigate,
|
||||
});
|
||||
});
|
||||
|
||||
it('should render all alert type options when anomaly detection is enabled', () => {
|
||||
useAppContextSpy.mockReturnValue({
|
||||
...getAppContextMockState({}),
|
||||
featureFlags: [
|
||||
{
|
||||
name: FeatureKeys.ANOMALY_DETECTION,
|
||||
active: true,
|
||||
usage: 0,
|
||||
usage_limit: -1,
|
||||
route: '',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
render(<AlertTypeSelection />);
|
||||
|
||||
expect(screen.getByText('metric_based_alert')).toBeInTheDocument();
|
||||
expect(screen.getByText('log_based_alert')).toBeInTheDocument();
|
||||
expect(screen.getByText('traces_based_alert')).toBeInTheDocument();
|
||||
expect(screen.getByText('exceptions_based_alert')).toBeInTheDocument();
|
||||
expect(screen.getByText('anomaly_based_alert')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render all alert type options except anomaly based alert when anomaly detection is disabled', () => {
|
||||
render(<AlertTypeSelection />);
|
||||
|
||||
expect(screen.getByText('metric_based_alert')).toBeInTheDocument();
|
||||
expect(screen.getByText('log_based_alert')).toBeInTheDocument();
|
||||
expect(screen.getByText('traces_based_alert')).toBeInTheDocument();
|
||||
expect(screen.getByText('exceptions_based_alert')).toBeInTheDocument();
|
||||
expect(screen.queryByText('anomaly_based_alert')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should navigate to metrics based alert with correct params', () => {
|
||||
render(<AlertTypeSelection />);
|
||||
fireEvent.click(screen.getByText('metric_based_alert'));
|
||||
|
||||
expect(mockSetUrlQuery).toHaveBeenCalledTimes(2);
|
||||
expect(mockSetUrlQuery).toHaveBeenCalledWith(
|
||||
QueryParams.ruleType,
|
||||
AlertDetectionTypes.THRESHOLD_ALERT,
|
||||
);
|
||||
expect(mockSetUrlQuery).toHaveBeenCalledWith(
|
||||
QueryParams.alertType,
|
||||
AlertTypes.METRICS_BASED_ALERT,
|
||||
);
|
||||
expect(mockSafeNavigate).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should navigate to anomaly based alert with correct params', () => {
|
||||
useAppContextSpy.mockReturnValue({
|
||||
...getAppContextMockState({}),
|
||||
featureFlags: [
|
||||
{
|
||||
name: FeatureKeys.ANOMALY_DETECTION,
|
||||
active: true,
|
||||
usage: 0,
|
||||
usage_limit: -1,
|
||||
route: '',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
render(<AlertTypeSelection />);
|
||||
fireEvent.click(screen.getByText('anomaly_based_alert'));
|
||||
|
||||
expect(mockSetUrlQuery).toHaveBeenCalledTimes(2);
|
||||
expect(mockSetUrlQuery).toHaveBeenCalledWith(
|
||||
QueryParams.ruleType,
|
||||
AlertDetectionTypes.ANOMALY_DETECTION_ALERT,
|
||||
);
|
||||
expect(mockSetUrlQuery).toHaveBeenCalledWith(
|
||||
QueryParams.alertType,
|
||||
AlertTypes.METRICS_BASED_ALERT,
|
||||
);
|
||||
expect(mockSafeNavigate).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should navigate to log based alert with correct params', () => {
|
||||
render(<AlertTypeSelection />);
|
||||
fireEvent.click(screen.getByText('log_based_alert'));
|
||||
|
||||
expect(mockSetUrlQuery).toHaveBeenCalledTimes(2);
|
||||
expect(mockSetUrlQuery).toHaveBeenCalledWith(
|
||||
QueryParams.ruleType,
|
||||
AlertDetectionTypes.THRESHOLD_ALERT,
|
||||
);
|
||||
expect(mockSetUrlQuery).toHaveBeenCalledWith(
|
||||
QueryParams.alertType,
|
||||
AlertTypes.LOGS_BASED_ALERT,
|
||||
);
|
||||
expect(mockSafeNavigate).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should navigate to traces based alert with correct params', () => {
|
||||
render(<AlertTypeSelection />);
|
||||
fireEvent.click(screen.getByText('traces_based_alert'));
|
||||
expect(mockSetUrlQuery).toHaveBeenCalledTimes(2);
|
||||
expect(mockSetUrlQuery).toHaveBeenCalledWith(
|
||||
QueryParams.ruleType,
|
||||
AlertDetectionTypes.THRESHOLD_ALERT,
|
||||
);
|
||||
expect(mockSetUrlQuery).toHaveBeenCalledWith(
|
||||
QueryParams.alertType,
|
||||
AlertTypes.TRACES_BASED_ALERT,
|
||||
);
|
||||
expect(mockSafeNavigate).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should navigate to exceptions based alert with correct params', () => {
|
||||
render(<AlertTypeSelection />);
|
||||
fireEvent.click(screen.getByText('exceptions_based_alert'));
|
||||
expect(mockSetUrlQuery).toHaveBeenCalledTimes(2);
|
||||
expect(mockSetUrlQuery).toHaveBeenCalledWith(
|
||||
QueryParams.ruleType,
|
||||
AlertDetectionTypes.THRESHOLD_ALERT,
|
||||
);
|
||||
expect(mockSetUrlQuery).toHaveBeenCalledWith(
|
||||
QueryParams.alertType,
|
||||
AlertTypes.EXCEPTIONS_BASED_ALERT,
|
||||
);
|
||||
expect(mockSafeNavigate).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should navigate to new create alerts page with correct params if showNewCreateAlertsPage is true', () => {
|
||||
useUrlQuerySpy.mockReturnValue(({
|
||||
set: mockSetUrlQuery,
|
||||
toString: mockToString,
|
||||
get: mockGetUrlQuery.mockReturnValue('true'),
|
||||
} as Partial<URLSearchParams>) as URLSearchParams);
|
||||
|
||||
render(<AlertTypeSelection />);
|
||||
fireEvent.click(screen.getByText('metric_based_alert'));
|
||||
expect(mockSetUrlQuery).toHaveBeenCalledTimes(3);
|
||||
expect(mockSetUrlQuery).toHaveBeenCalledWith(
|
||||
QueryParams.ruleType,
|
||||
AlertDetectionTypes.THRESHOLD_ALERT,
|
||||
);
|
||||
expect(mockSetUrlQuery).toHaveBeenCalledWith(
|
||||
QueryParams.alertType,
|
||||
AlertTypes.METRICS_BASED_ALERT,
|
||||
);
|
||||
expect(mockSetUrlQuery).toHaveBeenCalledWith(
|
||||
QueryParams.showNewCreateAlertsPage,
|
||||
'true',
|
||||
);
|
||||
expect(mockSafeNavigate).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
3
frontend/src/pages/AlertTypeSelection/index.tsx
Normal file
3
frontend/src/pages/AlertTypeSelection/index.tsx
Normal file
@@ -0,0 +1,3 @@
|
||||
import AlertTypeSelectionPage from './AlertTypeSelection';
|
||||
|
||||
export default AlertTypeSelectionPage;
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
DataTypes,
|
||||
} from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
import { TagFilterItem } from 'types/api/queryBuilder/queryBuilderData';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
import { DataSource, ReduceOperators } from 'types/common/queryBuilder';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
export const celeryOverviewRequestRateWidgetData = (
|
||||
@@ -42,7 +42,7 @@ export const celeryOverviewRequestRateWidgetData = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'rate',
|
||||
@@ -95,7 +95,7 @@ export const celeryOverviewErrorRateWidgetData = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'rate',
|
||||
@@ -135,7 +135,7 @@ export const celeryOverviewAvgLatencyWidgetData = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'p95',
|
||||
@@ -178,7 +178,7 @@ export const celeryOverviewRequestRateGraphData = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: getStepInterval(startTime, endTime),
|
||||
timeAggregation: 'rate',
|
||||
@@ -238,7 +238,7 @@ export const celeryOverviewErrorRateGraphData = (
|
||||
orderBy: [],
|
||||
groupBy: groupByFilter ? [groupByFilter] : [],
|
||||
legend: '',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
},
|
||||
{
|
||||
dataSource: DataSource.TRACES,
|
||||
@@ -278,7 +278,7 @@ export const celeryOverviewErrorRateGraphData = (
|
||||
orderBy: [],
|
||||
groupBy: groupByFilter ? [groupByFilter] : [],
|
||||
legend: '',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
},
|
||||
{
|
||||
dataSource: DataSource.TRACES,
|
||||
@@ -305,7 +305,7 @@ export const celeryOverviewErrorRateGraphData = (
|
||||
orderBy: [],
|
||||
groupBy: groupByFilter ? [groupByFilter] : [],
|
||||
legend: '',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
},
|
||||
{
|
||||
queryName: 'F1',
|
||||
@@ -358,7 +358,7 @@ export const celeryOverviewAvgLatencyGraphData = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'C',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: getStepInterval(startTime, endTime),
|
||||
timeAggregation: 'p90',
|
||||
@@ -385,7 +385,7 @@ export const celeryOverviewAvgLatencyGraphData = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'D',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: getStepInterval(startTime, endTime),
|
||||
timeAggregation: 'p95',
|
||||
@@ -412,7 +412,7 @@ export const celeryOverviewAvgLatencyGraphData = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'E',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: getStepInterval(startTime, endTime),
|
||||
timeAggregation: 'p99',
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Typography } from 'antd';
|
||||
import { AxiosError } from 'axios';
|
||||
import NotFound from 'components/NotFound';
|
||||
import Spinner from 'components/Spinner';
|
||||
import NewDashboard from 'container/NewDashboard';
|
||||
import DashboardContainer from 'container/NewDashboard';
|
||||
import { useDashboard } from 'providers/Dashboard/Dashboard';
|
||||
import { useEffect } from 'react';
|
||||
import { ErrorType } from 'types/common';
|
||||
@@ -35,7 +35,7 @@ function DashboardPage(): JSX.Element {
|
||||
return <Spinner tip="Loading.." />;
|
||||
}
|
||||
|
||||
return <NewDashboard />;
|
||||
return <DashboardContainer />;
|
||||
}
|
||||
|
||||
export default DashboardPage;
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
IBuilderQuery,
|
||||
} from 'types/api/queryBuilder/queryBuilderData';
|
||||
import { EQueryType } from 'types/common/dashboard';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
import { DataSource, ReduceOperators } from 'types/common/queryBuilder';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
|
||||
interface GetWidgetQueryProps {
|
||||
@@ -111,7 +111,7 @@ export const getRequestTimesWidgetData = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'avg',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -146,7 +146,7 @@ export const getBrokerCountWidgetData = (dotMetricsEnabled: boolean): Widgets =>
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'avg',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'sum',
|
||||
@@ -185,7 +185,7 @@ export const getProducerFetchRequestPurgatoryWidgetData = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'avg',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -229,7 +229,7 @@ export const getBrokerNetworkThroughputWidgetData = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'avg',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -271,7 +271,7 @@ export const getIoWaitTimeWidgetData = (dotMetricsEnabled: boolean): Widgets =>
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'rate',
|
||||
@@ -314,7 +314,7 @@ export const getRequestResponseWidgetData = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'avg',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -344,7 +344,7 @@ export const getRequestResponseWidgetData = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'B',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'avg',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -387,7 +387,7 @@ export const getAverageRequestLatencyWidgetData = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'avg',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -437,7 +437,7 @@ export const getKafkaProducerByteRateWidgetData = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'avg',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -482,7 +482,7 @@ export const getBytesConsumedWidgetData = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'avg',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -545,7 +545,7 @@ export const getConsumerOffsetWidgetData = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'avg',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -595,7 +595,7 @@ export const getConsumerGroupMemberWidgetData = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'sum',
|
||||
@@ -656,7 +656,7 @@ export const getConsumerLagByGroupWidgetData = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'avg',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -706,7 +706,7 @@ export const getConsumerFetchRateWidgetData = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'avg',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -749,7 +749,7 @@ export const getMessagesConsumedWidgetData = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'avg',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -790,7 +790,7 @@ export const getJvmGCCountWidgetData = (dotMetricsEnabled: boolean): Widgets =>
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'rate',
|
||||
@@ -833,7 +833,7 @@ export const getJvmGcCollectionsElapsedWidgetData = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'rate',
|
||||
@@ -878,7 +878,7 @@ export const getCpuRecentUtilizationWidgetData = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'avg',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -917,7 +917,7 @@ export const getJvmMemoryHeapWidgetData = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'avg',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -965,7 +965,7 @@ export const getPartitionCountPerTopicWidgetData = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'sum',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'sum',
|
||||
@@ -1020,7 +1020,7 @@ export const getCurrentOffsetPartitionWidgetData = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'avg',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -1076,7 +1076,7 @@ export const getOldestOffsetWidgetData = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'avg',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
@@ -1132,7 +1132,7 @@ export const getInsyncReplicasWidgetData = (
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'avg',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'avg',
|
||||
|
||||
@@ -15,7 +15,7 @@ import { ErrorResponse, SuccessResponse } from 'types/api';
|
||||
import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
import { TagFilterItem } from 'types/api/queryBuilder/queryBuilderData';
|
||||
import { EQueryType } from 'types/common/dashboard';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
import { DataSource, ReduceOperators } from 'types/common/queryBuilder';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
|
||||
export const KAFKA_SETUP_DOC_LINK =
|
||||
@@ -148,7 +148,7 @@ export function getWidgetQuery({
|
||||
limit: null,
|
||||
orderBy: [],
|
||||
queryName: 'A',
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
spaceAggregation: 'avg',
|
||||
stepInterval: 60,
|
||||
timeAggregation: 'max',
|
||||
|
||||
@@ -60,6 +60,7 @@ import {
|
||||
IsDefaultQueryProps,
|
||||
QueryBuilderContextType,
|
||||
QueryBuilderData,
|
||||
ReduceOperators,
|
||||
} from 'types/common/queryBuilder';
|
||||
import { sanitizeOrderByForExplorer } from 'utils/sanitizeOrderBy';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
@@ -329,7 +330,7 @@ export function QueryBuilderProvider({
|
||||
// set to default values
|
||||
orderBy: [],
|
||||
limit: null,
|
||||
reduceTo: 'avg',
|
||||
reduceTo: ReduceOperators.AVG,
|
||||
};
|
||||
},
|
||||
[],
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
// ===================== Base Types =====================
|
||||
|
||||
import { ReduceOperators } from 'types/common/queryBuilder';
|
||||
|
||||
import { Warning } from '..';
|
||||
|
||||
export type Step = string | number; // Duration string (e.g., "30s") or seconds as number
|
||||
@@ -190,7 +192,7 @@ export interface MetricAggregation {
|
||||
temporality: Temporality;
|
||||
timeAggregation: TimeAggregation;
|
||||
spaceAggregation: SpaceAggregation;
|
||||
reduceTo?: string;
|
||||
reduceTo?: ReduceOperators;
|
||||
}
|
||||
|
||||
export interface SecondaryAggregation {
|
||||
|
||||
@@ -219,7 +219,13 @@ export type PanelTypeKeys =
|
||||
| 'TRACE'
|
||||
| 'EMPTY_WIDGET';
|
||||
|
||||
export type ReduceOperators = 'last' | 'sum' | 'avg' | 'max' | 'min';
|
||||
export enum ReduceOperators {
|
||||
LAST = 'last',
|
||||
SUM = 'sum',
|
||||
AVG = 'avg',
|
||||
MAX = 'max',
|
||||
MIN = 'min',
|
||||
}
|
||||
|
||||
export type QueryBuilderData = {
|
||||
queryData: IBuilderQuery[];
|
||||
|
||||
@@ -127,4 +127,5 @@ export const routePermission: Record<keyof typeof ROUTES, ROLES[]> = {
|
||||
METER: ['ADMIN', 'EDITOR', 'VIEWER'],
|
||||
METER_EXPLORER_VIEWS: ['ADMIN', 'EDITOR', 'VIEWER'],
|
||||
PUBLIC_DASHBOARD: ['ADMIN', 'EDITOR', 'VIEWER'],
|
||||
ALERT_TYPE_SELECTION: ['ADMIN', 'EDITOR'],
|
||||
};
|
||||
|
||||
2
go.mod
2
go.mod
@@ -54,7 +54,7 @@ require (
|
||||
github.com/smartystreets/goconvey v1.8.1
|
||||
github.com/soheilhy/cmux v0.1.5
|
||||
github.com/spf13/cobra v1.10.1
|
||||
github.com/srikanthccv/ClickHouse-go-mock v0.12.0
|
||||
github.com/srikanthccv/ClickHouse-go-mock v0.13.0
|
||||
github.com/stretchr/testify v1.11.1
|
||||
github.com/swaggest/jsonschema-go v0.3.78
|
||||
github.com/swaggest/rest v0.2.75
|
||||
|
||||
4
go.sum
4
go.sum
@@ -964,8 +964,8 @@ github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3A
|
||||
github.com/spf13/viper v1.13.0/go.mod h1:Icm2xNL3/8uyh/wFuB1jI7TiTNKp8632Nwegu+zgdYw=
|
||||
github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4=
|
||||
github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4=
|
||||
github.com/srikanthccv/ClickHouse-go-mock v0.12.0 h1:KUzaWTwuqMc2uf5FylM/oAcTFdE2DdZjvISm9V0/NAA=
|
||||
github.com/srikanthccv/ClickHouse-go-mock v0.12.0/go.mod h1:1oUmLtXEXOyS0EEWVKlKEfLfv9y02agCMAvD3tVnhlo=
|
||||
github.com/srikanthccv/ClickHouse-go-mock v0.13.0 h1:/b7DQphGkh29ocNtLh4DGmQxQYA0CfHz65Wy2zAH2GM=
|
||||
github.com/srikanthccv/ClickHouse-go-mock v0.13.0/go.mod h1:LiiyBUdXNwB/1DE9rgK/8q9qjVYsTzg6WXQ/3mU3TeY=
|
||||
github.com/stoewer/go-strcase v1.3.0 h1:g0eASXYtp+yvN9fK8sH94oCIk0fau9uV1/ZdJ0AVEzs=
|
||||
github.com/stoewer/go-strcase v1.3.0/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
|
||||
1836
pkg/alertmanager/mocks/mocks.go
Normal file
1836
pkg/alertmanager/mocks/mocks.go
Normal file
File diff suppressed because it is too large
Load Diff
@@ -172,7 +172,6 @@ func (module *module) GetByUser(ctx context.Context, userID valuer.UUID, name pr
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if storableUserPreference != nil {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user