diff --git a/.github/workflows/cypress-tests-qi-wlm-interaction.yml b/.github/workflows/cypress-tests-qi-wlm-interaction.yml
new file mode 100644
index 00000000..7ecd3489
--- /dev/null
+++ b/.github/workflows/cypress-tests-qi-wlm-interaction.yml
@@ -0,0 +1,205 @@
+name: Cypress e2e integration tests workflow for QI-WLM interaction
+on:
+ pull_request:
+ branches:
+ - "*"
+ push:
+ branches:
+ - "*"
+env:
+ OPENSEARCH_DASHBOARDS_VERSION: 'main'
+ QUERY_INSIGHTS_BRANCH: 'main'
+ GRADLE_VERSION: '7.6.1'
+ CYPRESS_VIDEO: true
+ CYPRESS_SCREENSHOT_ON_RUN_FAILURE: true
+
+jobs:
+ tests:
+ name: Run Cypress E2E tests for QI-WLM interaction
+ timeout-minutes: 90
+ strategy:
+ fail-fast: false
+ matrix:
+ os: [ubuntu-latest]
+ include:
+ - os: ubuntu-latest
+ cypress_cache_folder: ~/.cache/Cypress
+ runs-on: ${{ matrix.os }}
+ env:
+ CI: 1
+ TERM: xterm
+ steps:
+
+ - name: Set up JDK
+ uses: actions/setup-java@v4
+ with:
+ java-version: 21
+ distribution: temurin
+
+ - name: Checkout Query Insights
+ uses: actions/checkout@v4
+ with:
+ path: query-insights
+ repository: opensearch-project/query-insights
+ ref: ${{ env.QUERY_INSIGHTS_BRANCH }}
+
+ - name: Checkout OpenSearch
+ uses: actions/checkout@v4
+ with:
+ path: OpenSearch
+ repository: opensearch-project/OpenSearch
+ ref: ${{ env.OPENSEARCH_BRANCH }}
+
+ - name: Fetch OpenSearch version from build.gradle
+ run: |
+ cd query-insights
+ opensearch_version=$(node -e "
+ const fs = require('fs');
+ const gradleFile = fs.readFileSync('build.gradle', 'utf-8');
+ const match = gradleFile.match(/opensearch_version\\s*=\\s*System\\.getProperty\\(['\"][^'\"]+['\"],\\s*['\"]([^'\"]+)['\"]\\)/);
+ console.log(match ? match[1] : 'No version found');
+ ")
+ echo "OPENSEARCH_VERSION=$opensearch_version" >> $GITHUB_ENV
+ echo "PLUGIN_VERSION=$opensearch_version" >> $GITHUB_ENV
+ shell: bash
+
+ - name: Build Required Plugins
+ run: |
+ cd OpenSearch
+ ./gradlew :modules:autotagging-commons:assemble
+ ./gradlew :plugins:workload-management:assemble
+
+ - name: Copy Plugins to Query Insights
+ run: |
+ mkdir -p query-insights/plugins
+ find OpenSearch/modules/autotagging-commons/build/distributions/ -name "*.zip" -exec cp {} query-insights/plugins/ \;
+ find OpenSearch/plugins/workload-management/build/distributions/ -name "*.zip" -exec cp {} query-insights/plugins/ \;
+
+ - name: Set up Gradle
+ uses: gradle/gradle-build-action@v2
+ with:
+ gradle-version: ${{ env.GRADLE_VERSION }}
+
+ - name: Run OpenSearch with Query Insights plugin
+ run: |
+ cd query-insights
+ ./gradlew run -Dopensearch.version=${{ env.OPENSEARCH_VERSION }} &
+
+ echo "Waiting for OpenSearch to start..."
+ for i in {1..60}; do
+ if curl -s http://localhost:9200/_cluster/health > /dev/null 2>&1; then
+ echo "OpenSearch is ready!"
+ break
+ fi
+ echo "Attempt $i/60: OpenSearch not ready yet, waiting 10 seconds..."
+ sleep 10
+ done
+
+ curl -s http://localhost:9200/_cluster/health || (echo "OpenSearch failed to start" && exit 1)
+
+ echo -e "\nEnabling WLM mode:"
+ curl -X PUT "http://localhost:9200/_cluster/settings" \
+ -H 'Content-Type: application/json' \
+ -d '{"persistent":{"wlm.workload_group.mode":"enabled"}}' | jq '.'
+ shell: bash
+
+ - name: Checkout OpenSearch-Dashboards
+ uses: actions/checkout@v4
+ with:
+ repository: opensearch-project/OpenSearch-Dashboards
+ path: OpenSearch-Dashboards
+ ref: ${{ env.OPENSEARCH_DASHBOARDS_VERSION }}
+
+ - name: Checkout Query Insights Dashboards plugin
+ uses: actions/checkout@v4
+ with:
+ path: OpenSearch-Dashboards/plugins/query-insights-dashboards
+
+ - name: Setup Node
+ uses: actions/setup-node@v3
+ with:
+ node-version-file: './OpenSearch-Dashboards/.nvmrc'
+ registry-url: 'https://registry.npmjs.org'
+
+ - name: Install Yarn
+ shell: bash
+ run: |
+ YARN_VERSION=$(node -p "require('./OpenSearch-Dashboards/package.json').engines.yarn")
+ npm i -g yarn@$YARN_VERSION
+
+ - name: Bootstrap plugin/OpenSearch-Dashboards
+ run: |
+ cd OpenSearch-Dashboards/plugins/query-insights-dashboards
+ yarn osd bootstrap --single-version=loose
+
+ - name: Run OpenSearch-Dashboards server
+ run: |
+ cd OpenSearch-Dashboards
+ export NODE_OPTIONS="--max-old-space-size=6144 --dns-result-order=ipv4first"
+ nohup yarn start --no-base-path --no-watch --server.host="0.0.0.0" > dashboards.log 2>&1 &
+ sleep 10
+ shell: bash
+
+ - name: Wait for OpenSearch-Dashboards to be ready
+ run: |
+ echo "Waiting for OpenSearch-Dashboards to start..."
+ max_attempts=150
+ attempt=0
+ while [ $attempt -lt $max_attempts ]; do
+ if curl -s -f http://localhost:5601/api/status > /dev/null 2>&1; then
+ echo "OpenSearch-Dashboards is ready!"
+ sleep 45
+ break
+ fi
+ attempt=$((attempt + 1))
+ echo "Attempt $attempt/$max_attempts: waiting 10 seconds..."
+ sleep 10
+ done
+ shell: bash
+
+ - name: Install Cypress
+ run: |
+ cd OpenSearch-Dashboards/plugins/query-insights-dashboards
+ npx cypress install
+ shell: bash
+
+ - name: Cache Cypress
+ uses: actions/cache@v4
+ with:
+ path: ${{ matrix.cypress_cache_folder }}
+ key: cypress-cache-v2-${{ matrix.os }}-${{ hashFiles('OpenSearch-Dashboards/plugins/query-insights-dashboards/package.json') }}
+
+ - name: Create WLM workload groups
+ run: |
+ curl -s -H 'Content-Type: application/json' \
+ -X PUT 'http://localhost:9200/_wlm/workload_group' \
+ -d '{"name":"analytics_group","resiliency_mode":"soft","resource_limits":{"cpu":0.3,"memory":0.3}}'
+
+ curl -s -H 'Content-Type: application/json' \
+ -X PUT 'http://localhost:9200/_wlm/workload_group' \
+ -d '{"name":"search_group","resiliency_mode":"soft","resource_limits":{"cpu":0.2,"memory":0.2}}'
+
+ - name: Cypress tests
+ uses: cypress-io/github-action@v5
+ with:
+ working-directory: OpenSearch-Dashboards/plugins/query-insights-dashboards
+ command: yarn run cypress run --config defaultCommandTimeout=120000,requestTimeout=120000,responseTimeout=120000,pageLoadTimeout=180000,taskTimeout=120000,execTimeout=120000 --spec cypress/e2e/qi-wlm-interaction/**/*
+ wait-on: 'http://localhost:5601'
+ wait-on-timeout: 1200
+ browser: chrome
+ env:
+ CYPRESS_CACHE_FOLDER: ${{ matrix.cypress_cache_folder }}
+ CI: true
+ timeout-minutes: 120
+
+ - uses: actions/upload-artifact@v4
+ if: failure()
+ with:
+ name: cypress-screenshots-qi-wlm-interaction-${{ matrix.os }}
+ path: OpenSearch-Dashboards/plugins/query-insights-dashboards/cypress/screenshots
+
+ - uses: actions/upload-artifact@v4
+ if: always()
+ with:
+ name: cypress-videos-qi-wlm-interaction-${{ matrix.os }}
+ path: OpenSearch-Dashboards/plugins/query-insights-dashboards/cypress/videos
\ No newline at end of file
diff --git a/.github/workflows/cypress-tests-wlm-no-security.yml b/.github/workflows/cypress-tests-wlm-no-security.yml
new file mode 100644
index 00000000..1f3c959f
--- /dev/null
+++ b/.github/workflows/cypress-tests-wlm-no-security.yml
@@ -0,0 +1,220 @@
+name: Cypress e2e integration tests workflow for WLM without security
+on:
+ pull_request:
+ branches:
+ - "*"
+ push:
+ branches:
+ - "*"
+env:
+ OPENSEARCH_DASHBOARDS_VERSION: 'main'
+ QUERY_INSIGHTS_BRANCH: 'main'
+ GRADLE_VERSION: '7.6.1'
+ CYPRESS_VIDEO: true
+ CYPRESS_SCREENSHOT_ON_RUN_FAILURE: true
+
+jobs:
+ tests:
+ name: Run Cypress E2E tests for WLM without security
+ timeout-minutes: 90
+ strategy:
+ fail-fast: false
+ matrix:
+ os: [ubuntu-latest]
+ include:
+ - os: ubuntu-latest
+ cypress_cache_folder: ~/.cache/Cypress
+ runs-on: ${{ matrix.os }}
+ env:
+ CI: 1
+ TERM: xterm
+ steps:
+
+ - name: Set up JDK
+ uses: actions/setup-java@v4
+ with:
+ java-version: 21
+ distribution: temurin
+
+ - name: Checkout Query Insights
+ uses: actions/checkout@v4
+ with:
+ path: query-insights
+ repository: opensearch-project/query-insights
+ ref: ${{ env.QUERY_INSIGHTS_BRANCH }}
+
+ - name: Checkout OpenSearch
+ uses: actions/checkout@v4
+ with:
+ path: OpenSearch
+ repository: opensearch-project/OpenSearch
+ ref: ${{ env.OPENSEARCH_BRANCH }}
+
+ - name: Fetch OpenSearch version from build.gradle
+ run: |
+ cd query-insights
+ if [ -f "build.gradle" ]; then
+ echo "build.gradle file exists!"
+ else
+ echo "build.gradle file not found!"
+ exit 1
+ fi
+
+ opensearch_version=$(node -e "
+ const fs = require('fs');
+ const gradleFile = fs.readFileSync('build.gradle', 'utf-8');
+ const match = gradleFile.match(/opensearch_version\\s*=\\s*System\\.getProperty\\(['\"][^'\"]+['\"],\\s*['\"]([^'\"]+)['\"]\\)/);
+ console.log(match ? match[1] : 'No version found');
+ ")
+
+ echo "OPENSEARCH_VERSION=$opensearch_version" >> $GITHUB_ENV
+ echo "PLUGIN_VERSION=$opensearch_version" >> $GITHUB_ENV
+ echo "Using OpenSearch version: $opensearch_version"
+ shell: bash
+
+ - name: Build Required Plugins
+ run: |
+ cd OpenSearch
+ ./gradlew :modules:autotagging-commons:assemble
+ ./gradlew :plugins:workload-management:assemble
+
+ - name: Copy Plugins to Query Insights
+ run: |
+ mkdir -p query-insights/plugins
+ find OpenSearch/modules/autotagging-commons/build/distributions/ -name "*.zip" -exec cp {} query-insights/plugins/ \;
+ find OpenSearch/plugins/workload-management/build/distributions/ -name "*.zip" -exec cp {} query-insights/plugins/ \;
+
+ - name: Set up Gradle
+ uses: gradle/gradle-build-action@v2
+ with:
+ gradle-version: ${{ env.GRADLE_VERSION }}
+
+ - name: Run OpenSearch with Query Insights plugin
+ run: |
+ cd query-insights
+ ./gradlew run -Dopensearch.version=${{ env.OPENSEARCH_VERSION }} &
+
+ echo "Waiting for OpenSearch to start..."
+ for i in {1..60}; do
+ if curl -s http://localhost:9200/_cluster/health > /dev/null 2>&1; then
+ echo "OpenSearch is ready!"
+ break
+ fi
+ echo "Attempt $i/60: OpenSearch not ready yet, waiting 10 seconds..."
+ sleep 10
+ done
+
+ curl -s http://localhost:9200/_cluster/health || (echo "OpenSearch failed to start" && exit 1)
+
+ echo -e "\nEnabling WLM mode:"
+ curl -X PUT "http://localhost:9200/_cluster/settings" \
+ -H 'Content-Type: application/json' \
+ -d '{"persistent":{"wlm.workload_group.mode":"enabled"}}' | jq '.'
+
+ echo -e "\nTesting WLM stats endpoint:"
+ curl -s http://localhost:9200/_wlm/workload_group | jq '.'
+ shell: bash
+
+ - name: Checkout OpenSearch-Dashboards
+ uses: actions/checkout@v4
+ with:
+ repository: opensearch-project/OpenSearch-Dashboards
+ path: OpenSearch-Dashboards
+ ref: ${{ env.OPENSEARCH_DASHBOARDS_VERSION }}
+
+ - name: Checkout Query Insights Dashboards plugin
+ uses: actions/checkout@v4
+ with:
+ path: OpenSearch-Dashboards/plugins/query-insights-dashboards
+
+ - name: Setup Node
+ uses: actions/setup-node@v3
+ with:
+ node-version-file: './OpenSearch-Dashboards/.nvmrc'
+ registry-url: 'https://registry.npmjs.org'
+
+ - name: Install Yarn
+ shell: bash
+ run: |
+ YARN_VERSION=$(node -p "require('./OpenSearch-Dashboards/package.json').engines.yarn")
+ echo "Installing yarn@$YARN_VERSION"
+ npm i -g yarn@$YARN_VERSION
+
+ - name: Bootstrap plugin/OpenSearch-Dashboards
+ run: |
+ cd OpenSearch-Dashboards/plugins/query-insights-dashboards
+ yarn osd bootstrap --single-version=loose
+
+ - name: Run OpenSearch-Dashboards server
+ run: |
+ cd OpenSearch-Dashboards
+ export NODE_OPTIONS="--max-old-space-size=6144 --dns-result-order=ipv4first"
+ echo "Starting Dashboards..."
+ nohup yarn start --no-base-path --no-watch --server.host="0.0.0.0" > dashboards.log 2>&1 &
+ sleep 10
+ shell: bash
+
+ - name: Wait for OpenSearch-Dashboards to be ready
+ run: |
+ echo "Waiting for OpenSearch-Dashboards to start..."
+ max_attempts=150
+ attempt=0
+ while [ $attempt -lt $max_attempts ]; do
+ if curl -s -f http://localhost:5601/api/status > /dev/null 2>&1; then
+ echo "OpenSearch-Dashboards is ready!"
+ sleep 45
+ break
+ fi
+ attempt=$((attempt + 1))
+ echo "Attempt $attempt/$max_attempts: OpenSearch-Dashboards not ready yet, waiting 10 seconds..."
+ sleep 10
+ done
+ if [ $attempt -eq $max_attempts ]; then
+ echo "OpenSearch-Dashboards failed to start within timeout"
+ exit 1
+ fi
+ shell: bash
+
+ - name: Install Cypress
+ run: |
+ cd OpenSearch-Dashboards/plugins/query-insights-dashboards
+ npx cypress install
+ shell: bash
+
+ - name: Cache Cypress
+ id: cache-cypress
+ uses: actions/cache@v4
+ with:
+ path: ${{ matrix.cypress_cache_folder }}
+ key: cypress-cache-v2-${{ matrix.os }}-${{ hashFiles('OpenSearch-Dashboards/plugins/query-insights-dashboards/package.json') }}
+
+ - name: Create WLM workload group
+ run: |
+ curl -s -H 'Content-Type: application/json' \
+ -X PUT 'http://localhost:9200/_wlm/workload_group' \
+ -d '{"name":"test_group","resiliency_mode":"soft","resource_limits":{"cpu":0.1,"memory":0.1}}'
+
+ - name: Cypress tests
+ uses: cypress-io/github-action@v5
+ with:
+ working-directory: OpenSearch-Dashboards/plugins/query-insights-dashboards
+ command: yarn run cypress run --config defaultCommandTimeout=120000,requestTimeout=120000,responseTimeout=120000,pageLoadTimeout=180000,taskTimeout=120000,execTimeout=120000 --spec cypress/e2e/wlm-no-security/**/*
+ wait-on: 'http://localhost:5601'
+ wait-on-timeout: 1200
+ browser: chrome
+ env:
+ CYPRESS_CACHE_FOLDER: ${{ matrix.cypress_cache_folder }}
+ CI: true
+ timeout-minutes: 120
+
+ - uses: actions/upload-artifact@v4
+ if: failure()
+ with:
+ name: cypress-screenshots-wlm-no-security-${{ matrix.os }}
+ path: OpenSearch-Dashboards/plugins/query-insights-dashboards/cypress/screenshots
+
+ - uses: actions/upload-artifact@v4
+ if: always()
+ with:
+ name: cypress-videos-wlm-no-security-${{ matrix.os }}
+ path: OpenSearch-Dashboards/plugins/query-insights-dashboards/cypress/videos
\ No newline at end of file
diff --git a/.github/workflows/cypress-tests-wlm.yml b/.github/workflows/cypress-tests-wlm.yml
index 649e5a9e..e9bc98e2 100644
--- a/.github/workflows/cypress-tests-wlm.yml
+++ b/.github/workflows/cypress-tests-wlm.yml
@@ -1,4 +1,4 @@
-name: Cypress e2e integration tests workflow with security
+name: Cypress e2e integration tests workflow for WLM with security
on:
pull_request:
branches:
@@ -13,7 +13,7 @@ env:
OPENSEARCH_INITIAL_ADMIN_PASSWORD: "myStrongPassword123!"
jobs:
tests:
- name: Run Cypress E2E tests for WLM
+ name: Run Cypress E2E tests for WLM with security
timeout-minutes: 90
strategy:
fail-fast: false
@@ -267,7 +267,7 @@ jobs:
uses: cypress-io/github-action@v5
with:
working-directory: OpenSearch-Dashboards/plugins/query-insights-dashboards
- command: yarn run cypress run --config defaultCommandTimeout=120000,requestTimeout=120000,responseTimeout=120000,pageLoadTimeout=180000,taskTimeout=120000,execTimeout=120000,excludeSpecPattern=cypress/e2e/qi/**/*
+ command: yarn run cypress run --config defaultCommandTimeout=120000,requestTimeout=120000,responseTimeout=120000,pageLoadTimeout=180000,taskTimeout=120000,execTimeout=120000 --spec cypress/e2e/wlm/**/*
browser: chrome
env:
CYPRESS_CACHE_FOLDER: ${{ matrix.cypress_cache_folder }}
@@ -277,11 +277,11 @@ jobs:
- uses: actions/upload-artifact@v4
if: failure()
with:
- name: cypress-screenshots-${{ matrix.os }}
+ name: cypress-screenshots-wlm-security-${{ matrix.os }}
path: OpenSearch-Dashboards/plugins/query-insights-dashboards/cypress/screenshots
- uses: actions/upload-artifact@v4
if: always()
with:
- name: cypress-videos-${{ matrix.os }}
+ name: cypress-videos-wlm-security-${{ matrix.os }}
path: OpenSearch-Dashboards/plugins/query-insights-dashboards/cypress/videos
diff --git a/.github/workflows/cypress-tests.yml b/.github/workflows/cypress-tests.yml
index 24320621..ed51dab1 100644
--- a/.github/workflows/cypress-tests.yml
+++ b/.github/workflows/cypress-tests.yml
@@ -1,4 +1,4 @@
-name: Cypress e2e integration tests workflow
+name: Cypress e2e integration tests workflow for Query Insights
on:
pull_request:
branches:
@@ -288,7 +288,7 @@ jobs:
uses: cypress-io/github-action@v5
with:
working-directory: OpenSearch-Dashboards/plugins/query-insights-dashboards
- command: yarn run cypress run --config defaultCommandTimeout=120000,requestTimeout=120000,responseTimeout=120000,pageLoadTimeout=180000,taskTimeout=120000,execTimeout=120000,excludeSpecPattern=cypress/e2e/wlm/**/*
+ command: yarn run cypress run --config defaultCommandTimeout=120000,requestTimeout=120000,responseTimeout=120000,pageLoadTimeout=180000,taskTimeout=120000,execTimeout=120000 --spec cypress/e2e/qi/**/*
wait-on: 'http://localhost:5601'
wait-on-timeout: 1200
browser: chrome
@@ -300,11 +300,11 @@ jobs:
- uses: actions/upload-artifact@v4
if: failure()
with:
- name: cypress-screenshots-${{ matrix.os }}
+ name: cypress-screenshots-qi-${{ matrix.os }}
path: OpenSearch-Dashboards/plugins/query-insights-dashboards/cypress/screenshots
- uses: actions/upload-artifact@v4
if: always()
with:
- name: cypress-videos-${{ matrix.os }}
+ name: cypress-videos-qi-${{ matrix.os }}
path: OpenSearch-Dashboards/plugins/query-insights-dashboards/cypress/videos
diff --git a/common/constants.ts b/common/constants.ts
index 451c05d4..4a46c2d5 100644
--- a/common/constants.ts
+++ b/common/constants.ts
@@ -14,6 +14,7 @@ export const INDICES = 'Indices';
export const SEARCH_TYPE = 'Search Type';
export const NODE_ID = 'Coordinator Node ID';
export const TOTAL_SHARDS = 'Total Shards';
+export const WLM_GROUP = 'WLM Group';
export const GROUP_BY = 'Group by';
export const AVERAGE_LATENCY = 'Average Latency';
export const AVERAGE_CPU_TIME = 'Average CPU Time';
@@ -71,6 +72,7 @@ export const TOP_N_DISPLAY_LIMIT = 9;
export const DEFAULT_SHOW_LIVE_QUERIES_ON_ERROR = false;
export const WLM_GROUP_ID_PARAM = 'wlmGroupId';
export const ALL_WORKLOAD_GROUPS_TEXT = 'All workload groups';
+export const DEFAULT_WORKLOAD_GROUP = 'DEFAULT_WORKLOAD_GROUP';
export const CHART_COLORS = [
'#1f77b4',
'#ff7f0e',
diff --git a/cypress/e2e/qi-wlm-interaction/10_topN_queries_wlm.cy.js b/cypress/e2e/qi-wlm-interaction/10_topN_queries_wlm.cy.js
new file mode 100644
index 00000000..76be8de9
--- /dev/null
+++ b/cypress/e2e/qi-wlm-interaction/10_topN_queries_wlm.cy.js
@@ -0,0 +1,96 @@
+/*
+ * Copyright OpenSearch Contributors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+describe('Top N Queries - WLM Available', () => {
+ beforeEach(() => {
+ cy.intercept('GET', '/api/top_queries/latency**', {
+ fixture: 'stub_top_queries_query_only.json',
+ }).as('latency');
+ cy.intercept('GET', '/api/top_queries/cpu**', {
+ fixture: 'stub_top_queries_query_only.json',
+ }).as('cpu');
+ cy.intercept('GET', '/api/top_queries/memory**', {
+ fixture: 'stub_top_queries_query_only.json',
+ }).as('memory');
+ cy.intercept('GET', '/api/_wlm/workload_group', {
+ statusCode: 200,
+ body: {
+ workload_groups: [
+ { _id: '9mK2pL8QR7Vb4n1xC6dE2F', name: 'Analytics Team' },
+ { _id: '3zY5wT9NQ8Hj7m2sA4bG1X', name: 'Search Team' },
+ ],
+ },
+ }).as('wlmGroups');
+ cy.visit('/app/query-insights-dashboards#/queryInsights');
+ cy.wait(['@latency', '@cpu', '@memory', '@wlmGroups']);
+ cy.get('table', { timeout: 30000 }).should('be.visible');
+ });
+
+ it('displays correct number of queries from fixture', () => {
+ cy.get('table tbody tr').should('have.length', 3);
+ });
+
+ it('shows WLM Group column with correct values', () => {
+ cy.contains('WLM Group').should('be.visible');
+ cy.get('table tbody tr').eq(0).should('contain', 'DEFAULT_WORKLOAD_GROUP');
+ cy.get('table tbody tr').eq(1).should('contain', 'Analytics Team');
+ cy.get('table tbody tr').eq(2).should('contain', 'Search Team');
+ });
+
+ it('has WLM group filter button with options', () => {
+ cy.contains('button', 'WLM Group').should('be.visible').click({ force: true });
+ cy.get('.euiPopover__panel').should('be.visible');
+ cy.contains('DEFAULT_WORKLOAD_GROUP').should('be.visible');
+ cy.contains('Analytics Team').should('be.visible');
+ cy.contains('Search Team').should('be.visible');
+ });
+
+ it('filters by DEFAULT_WORKLOAD_GROUP', () => {
+ cy.contains('button', 'WLM Group').should('be.visible').click({ force: true });
+ cy.get('.euiPopover__panel').should('be.visible');
+ cy.contains('DEFAULT_WORKLOAD_GROUP').click({ force: true });
+ cy.get('table tbody tr').should('have.length', 1);
+ });
+
+ it('shows WLM group links when mapped', () => {
+ cy.get('table tbody tr').eq(0).find('button').should('contain', 'DEFAULT_WORKLOAD_GROUP');
+ cy.get('table tbody tr').eq(1).find('button').should('contain', 'Analytics Team');
+ cy.get('table tbody tr').eq(2).find('button').should('contain', 'Search Team');
+ });
+ it('shows dash for group type records', () => {
+ cy.intercept('GET', '/api/top_queries/latency**', {
+ body: {
+ ok: true,
+ response: {
+ top_queries: [
+ {
+ id: 'group-1',
+ group_by: 'SIMILARITY',
+ wlm_group_id: 'some-group-id',
+ measurements: { latency: { number: 100, count: 5 } },
+ },
+ ],
+ },
+ },
+ }).as('groupData');
+ cy.intercept('GET', '/api/_wlm/workload_group', {
+ statusCode: 200,
+ body: { workload_groups: [] },
+ }).as('wlmGroups2');
+ cy.reload();
+ cy.wait(['@groupData', '@wlmGroups2']);
+ cy.get('table tbody tr').eq(0).find('span').should('contain', '-');
+ });
+
+ it('shows dash for unmapped wlm_group_id', () => {
+ cy.intercept('GET', '/api/_wlm/workload_group', {
+ statusCode: 200,
+ body: { workload_groups: [] },
+ }).as('wlmGroups3');
+ cy.reload();
+ cy.wait(['@wlmGroups3']);
+ cy.get('table tbody tr').eq(2).find('span').should('contain', '-');
+ });
+});
diff --git a/cypress/e2e/qi-wlm-interaction/9_inflight_queries_wlm.cy.js b/cypress/e2e/qi-wlm-interaction/9_inflight_queries_wlm.cy.js
new file mode 100644
index 00000000..861d672c
--- /dev/null
+++ b/cypress/e2e/qi-wlm-interaction/9_inflight_queries_wlm.cy.js
@@ -0,0 +1,79 @@
+/*
+ * Copyright OpenSearch Contributors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+describe('Inflight Queries Dashboard - WLM Enabled', () => {
+ beforeEach(() => {
+ cy.intercept('GET', '/api/live_queries*', { fixture: 'stub_live_queries.json' }).as(
+ 'liveQueries'
+ );
+ cy.intercept('GET', '/api/_wlm/stats*', {
+ statusCode: 200,
+ body: {
+ node1: {
+ workload_groups: {
+ ANALYTICS_WORKLOAD_GROUP: {
+ total_completions: 10,
+ total_cancellations: 0,
+ total_rejections: 0,
+ },
+ },
+ },
+ },
+ }).as('wlmStats');
+ cy.intercept('GET', '/api/_wlm/workload_group*', {
+ statusCode: 200,
+ body: {
+ workload_groups: [{ _id: 'ANALYTICS_WORKLOAD_GROUP', name: 'Analytics Team' }],
+ },
+ }).as('wlmGroups');
+ cy.visit('/app/query-insights-dashboards#/LiveQueries');
+ cy.wait(['@liveQueries', '@wlmStats', '@wlmGroups']);
+ });
+
+ it('displays WLM group links when WLM is enabled', () => {
+ cy.get('table').should('exist');
+ cy.contains('WLM Group').should('be.visible');
+ cy.get('table tbody tr')
+ .first()
+ .within(() => {
+ cy.get('button')
+ .contains(/ANALYTICS_WORKLOAD_GROUP|DEFAULT_QUERY_GROUP|SEARCH_WORKLOAD_GROUP/)
+ .should('exist')
+ .and('be.visible');
+ });
+ });
+
+ it('calls different API when WLM group selection changes', () => {
+ cy.get('[aria-label="Workload group selector"]').select('ANALYTICS_WORKLOAD_GROUP');
+ cy.wait('@liveQueries');
+ cy.wait('@wlmStats');
+ });
+
+ it('displays total completion, cancellation, and rejection metrics correctly', () => {
+ cy.contains('Total completions').should('be.visible');
+ cy.contains('Total cancellations').should('be.visible');
+ cy.contains('Total rejections').should('be.visible');
+ cy.contains('Total completions')
+ .closest('.euiPanel')
+ .within(() => {
+ cy.get('h2').should('be.visible');
+ });
+ cy.contains('Total cancellations')
+ .closest('.euiPanel')
+ .within(() => {
+ cy.get('h2').should('be.visible');
+ });
+ cy.contains('Total rejections')
+ .closest('.euiPanel')
+ .within(() => {
+ cy.get('h2').should('be.visible');
+ });
+ });
+
+ it('shows workload group selector with mapped names', () => {
+ cy.contains('.euiBadge', 'Workload group').should('be.visible');
+ cy.get('[aria-label="Workload group selector"]').should('be.visible');
+ });
+});
diff --git a/cypress/e2e/qi/1_top_queries.cy.js b/cypress/e2e/qi/1_top_queries.cy.js
index 8d361d26..49a76df9 100644
--- a/cypress/e2e/qi/1_top_queries.cy.js
+++ b/cypress/e2e/qi/1_top_queries.cy.js
@@ -410,6 +410,7 @@ describe('Query Insights — Dynamic Columns with Intercepted Top Queries (MIXED
'Indices',
'Search Type',
'Coordinator Node ID',
+ 'WLM Group',
'Total Shards',
];
getHeaders().should('deep.equal', expected);
@@ -432,6 +433,7 @@ describe('Query Insights — Dynamic Columns with Intercepted Top Queries (MIXED
'Indices',
'Search Type',
'Coordinator Node ID',
+ 'WLM Group',
'Total Shards',
];
getHeaders().should('deep.equal', expected);
@@ -481,6 +483,7 @@ describe('Query Insights — Dynamic Columns with Intercepted Top Queries (MIXED
'Indices',
'Search Type',
'Coordinator Node ID',
+ 'WLM Group',
'Total Shards',
];
getHeaders().should('deep.equal', expected);
@@ -515,6 +518,7 @@ describe('Query Insights — Dynamic Columns (QUERY ONLY fixture)', () => {
'Indices',
'Search Type',
'Coordinator Node ID',
+ 'WLM Group',
'Total Shards',
];
getHeaders().should('deep.equal', expected);
diff --git a/cypress/e2e/qi/5_live_queries.cy.js b/cypress/e2e/qi/5_live_queries.cy.js
index 4ba1a0bf..815b37bd 100644
--- a/cypress/e2e/qi/5_live_queries.cy.js
+++ b/cypress/e2e/qi/5_live_queries.cy.js
@@ -348,115 +348,3 @@ describe('Inflight Queries Dashboard', () => {
});
});
});
-
-describe('Inflight Queries Dashboard - WLM Enabled', () => {
- beforeEach(() => {
- cy.fixture('stub_live_queries.json').then((stubResponse) => {
- cy.intercept('GET', '**/api/live_queries', {
- statusCode: 200,
- body: stubResponse,
- }).as('getLiveQueries');
- });
-
- // WLM stats
- cy.fixture('stub_wlm_stats.json').then((wlmStats) => {
- cy.intercept('GET', '**/api/_wlm/stats', {
- statusCode: 200,
- body: wlmStats.body,
- }).as('getWlmStats');
- });
-
- cy.intercept('GET', '**/api/_wlm/workload_group', {
- statusCode: 200,
- body: {
- workload_groups: [
- { _id: 'ANALYTICS_WORKLOAD_GROUP', name: 'ANALYTICS_WORKLOAD_GROUP' },
- { _id: 'DEFAULT_WORKLOAD_GROUP', name: 'DEFAULT_WORKLOAD_GROUP' },
- ],
- },
- }).as('getWorkloadGroups');
-
- cy.intercept('GET', '**/api/cluster/version', {
- statusCode: 200,
- body: { version: '3.3.0' },
- }).as('getClusterVersion');
-
- // Navigate AFTER all intercepts are ready, then wait initial snapshot
- cy.navigateToLiveQueries();
- });
-
- it('displays WLM group links when WLM is enabled', () => {
- cy.wait('@getWorkloadGroups');
-
- cy.get('tbody tr')
- .first()
- .within(() => {
- cy.contains('td', 'ANALYTICS_WORKLOAD_GROUP').click({ force: true });
- });
- });
-
- it('calls different API when WLM group selection changes', () => {
- // Robust spies that tolerate extra query params & any order
- cy.intercept('GET', /\/api\/live_queries\?(?=.*\bwlmGroupId=ANALYTICS_WORKLOAD_GROUP\b).*/).as(
- 'liveQueriesAnalytics'
- );
-
- cy.intercept('GET', /\/api\/live_queries\?(?=.*\bwlmGroupId=DEFAULT_WORKLOAD_GROUP\b).*/).as(
- 'liveQueriesDefault'
- );
-
- cy.get('#wlm-group-select').should('exist');
-
- // 1) Select ANALYTICS
- cy.get('#wlm-group-select').select('ANALYTICS_WORKLOAD_GROUP');
- cy.wait('@liveQueriesAnalytics')
- .its('request.url')
- .should((urlStr) => {
- const url = new URL(urlStr);
- expect(url.searchParams.get('wlmGroupId')).to.eq('ANALYTICS_WORKLOAD_GROUP');
- });
-
- // Component re-fetches groups after selection
- cy.wait('@getWorkloadGroups');
-
- // 2) Select DEFAULT
- cy.get('#wlm-group-select').select('DEFAULT_WORKLOAD_GROUP');
-
- cy.wait('@liveQueriesDefault')
- .its('request.url')
- .should((urlStr) => {
- const url = new URL(urlStr);
- expect(url.searchParams.get('wlmGroupId')).to.eq('DEFAULT_WORKLOAD_GROUP');
- });
- });
-
- it('displays total completion, cancellation, and rejection metrics correctly', () => {
- // Wait for version check to complete
- cy.wait('@getClusterVersion');
-
- // Wait for WLM groups to be fetched
- cy.wait('@getWorkloadGroups');
-
- // Wait for WLM stats to be fetched
- cy.wait('@getWlmStats');
-
- // Wait for the panels to be rendered with data
- cy.contains('Total completions', { timeout: 10000 })
- .closest('.euiPanel')
- .within(() => {
- cy.get('h2').should('contain.text', '300');
- });
-
- cy.contains('Total cancellations')
- .closest('.euiPanel')
- .within(() => {
- cy.get('h2').should('contain.text', '80');
- });
-
- cy.contains('Total rejections')
- .closest('.euiPanel')
- .within(() => {
- cy.get('h2').should('contain.text', '10');
- });
- });
-});
diff --git a/cypress/e2e/qi/6_WLM_main_wo_security.cy.js b/cypress/e2e/wlm-no-security/6_WLM_main.cy.js
similarity index 100%
rename from cypress/e2e/qi/6_WLM_main_wo_security.cy.js
rename to cypress/e2e/wlm-no-security/6_WLM_main.cy.js
diff --git a/cypress/e2e/qi/7_WLM_details_wo_security.cy.js b/cypress/e2e/wlm-no-security/7_WLM_details.cy.js
similarity index 100%
rename from cypress/e2e/qi/7_WLM_details_wo_security.cy.js
rename to cypress/e2e/wlm-no-security/7_WLM_details.cy.js
diff --git a/cypress/e2e/qi/8_WLM_create_wo_security.cy.js b/cypress/e2e/wlm-no-security/8_WLM_create.cy.js
similarity index 100%
rename from cypress/e2e/qi/8_WLM_create_wo_security.cy.js
rename to cypress/e2e/wlm-no-security/8_WLM_create.cy.js
diff --git a/cypress/fixtures/stub_top_queries.json b/cypress/fixtures/stub_top_queries.json
index 53e6ab1e..02b362bf 100644
--- a/cypress/fixtures/stub_top_queries.json
+++ b/cypress/fixtures/stub_top_queries.json
@@ -8,6 +8,7 @@
"search_type": "query_then_fetch",
"indices": [".kibana"],
"node_id": "UYKFun8PSAeJvkkt9cWf0w",
+ "wlm_group_id": "DEFAULT_WORKLOAD_GROUP",
"group_by": "NONE",
"total_shards": 1,
"labels": {
@@ -25,6 +26,7 @@
"search_type": "query_then_fetch",
"indices": [".kibana"],
"node_id": "UYKFun8PSAeJvkkt9cWf0w",
+ "wlm_group_id": "ANALYTICS_GROUP",
"group_by": "SIMILARITY",
"total_shards": 1,
"labels": {},
@@ -41,6 +43,7 @@
"search_type": "query_then_fetch",
"indices": ["my-index"],
"node_id": "UYKFun8PSAeJvkkt9cWf0w",
+ "wlm_group_id": "SEARCH_GROUP",
"group_by": "NONE",
"total_shards": 1,
"labels": {
@@ -58,6 +61,7 @@
"search_type": "query_then_fetch",
"indices": [".kibana"],
"node_id": "KINGun8PSAeJvkkt9cWf0w",
+ "wlm_group_id": "DEFAULT_WORKLOAD_GROUP",
"group_by": "NONE",
"total_shards": 1,
"labels": {
@@ -75,6 +79,7 @@
"search_type": "query_then_fetch",
"indices": [".kibana"],
"node_id": "KINGun8PSAeJvkkt9cWf0w",
+ "wlm_group_id": "ANALYTICS_GROUP",
"group_by": "SIMILARITY",
"total_shards": 1,
"labels": {
@@ -93,6 +98,7 @@
"search_type": "query_then_fetch",
"indices": [".kibana"],
"node_id": "KINGun8PSAeJvkkt9cWf0w",
+ "wlm_group_id": "SEARCH_GROUP",
"group_by": "SIMILARITY",
"total_shards": 1,
"labels": {},
@@ -109,6 +115,7 @@
"search_type": "query_then_fetch",
"indices": [".kibana"],
"node_id": "KINGun8PSAeJvkkt9cWf0w",
+ "wlm_group_id": "DEFAULT_WORKLOAD_GROUP",
"group_by": "SIMILARITY",
"total_shards": 1,
"labels": {},
@@ -125,6 +132,7 @@
"search_type": "query_then_fetch",
"indices": [".kibana"],
"node_id": "KINGun8PSAeJvkkt9cWf0w",
+ "wlm_group_id": "ANALYTICS_GROUP",
"group_by": "SIMILARITY",
"total_shards": 1,
"labels": {},
diff --git a/cypress/fixtures/stub_top_queries_group_only.json b/cypress/fixtures/stub_top_queries_group_only.json
index 323ab0be..b3601479 100644
--- a/cypress/fixtures/stub_top_queries_group_only.json
+++ b/cypress/fixtures/stub_top_queries_group_only.json
@@ -8,6 +8,7 @@
"search_type": "query_then_fetch",
"indices": [".kibana"],
"node_id": "UYKFun8PSAeJvkkt9cWf0w",
+ "wlm_group_id": "DEFAULT_WORKLOAD_GROUP",
"group_by": "SIMILARITY",
"total_shards": 1,
"labels": {},
@@ -24,6 +25,7 @@
"search_type": "query_then_fetch",
"indices": [".kibana"],
"node_id": "UYKFun8PSAeJvkkt9cWf0w",
+ "wlm_group_id": "ANALYTICS_GROUP",
"group_by": "SIMILARITY",
"total_shards": 1,
"labels": {
@@ -42,6 +44,7 @@
"search_type": "query_then_fetch",
"indices": [".kibana"],
"node_id": "UYKFun8PSAeJvkkt9cWf0w",
+ "wlm_group_id": "SEARCH_GROUP",
"group_by": "SIMILARITY",
"total_shards": 1,
"labels": {},
@@ -58,6 +61,7 @@
"search_type": "query_then_fetch",
"indices": [".kibana"],
"node_id": "UYKFun8PSAeJvkkt9cWf0w",
+ "wlm_group_id": "DEFAULT_WORKLOAD_GROUP",
"group_by": "SIMILARITY",
"total_shards": 1,
"labels": {},
@@ -74,6 +78,7 @@
"search_type": "query_then_fetch",
"indices": [".kibana"],
"node_id": "UYKFun8PSAeJvkkt9cWf0w",
+ "wlm_group_id": "ANALYTICS_GROUP",
"group_by": "SIMILARITY",
"total_shards": 1,
"labels": {},
diff --git a/cypress/fixtures/stub_top_queries_query_only.json b/cypress/fixtures/stub_top_queries_query_only.json
index 5de6164c..b7d49e65 100644
--- a/cypress/fixtures/stub_top_queries_query_only.json
+++ b/cypress/fixtures/stub_top_queries_query_only.json
@@ -8,6 +8,7 @@
"search_type": "query_then_fetch",
"indices": ["my-index"],
"node_id": "UYKFun8PSAeJvkkt9cWf0w",
+ "wlm_group_id": "DEFAULT_WORKLOAD_GROUP",
"group_by": "NONE",
"total_shards": 1,
"labels": {
@@ -25,6 +26,7 @@
"search_type": "query_then_fetch",
"indices": ["my-index"],
"node_id": "UYKFun8PSAeJvkkt9cWf0w",
+ "wlm_group_id": "9mK2pL8QR7Vb4n1xC6dE2F",
"group_by": "NONE",
"total_shards": 1,
"labels": {
@@ -42,6 +44,7 @@
"search_type": "query_then_fetch",
"indices": ["my-index"],
"node_id": "UYKFun8PSAeJvkkt9cWf0w",
+ "wlm_group_id": "3zY5wT9NQ8Hj7m2sA4bG1X",
"group_by": "NONE",
"total_shards": 1,
"labels": {
diff --git a/public/components/__snapshots__/app.test.tsx.snap b/public/components/__snapshots__/app.test.tsx.snap
index bec08721..677d3079 100644
--- a/public/components/__snapshots__/app.test.tsx.snap
+++ b/public/components/__snapshots__/app.test.tsx.snap
@@ -57,728 +57,6 @@ exports[`
| - - | -- - | -- - | -- - | -- - | -- - | -- - | -- - | -- - | -- - | -- - | -
|---|---|---|---|---|---|---|---|---|---|---|
|
-
-
- No items found
-
-
- |
- ||||||||||