Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions e2e_tests/pages/dashboards/mysql/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import PXCGaleraNodesCompare from './pxcGaleraNodesCompare';
import MySQLUserDetails from './mysqlUserDetails';
import MysqlGroupReplicationSummary from './mysqlGroupReplicationSummary';
import MysqlMyRocksDetails from './mysqlMyRocksDetails';
import MysqlPerformanceSchemaDetails from './mysqlPerformanceSchemaDetails';
import MysqlReplicationSummary from './mysqlReplicationSummary';
import HaproxyInstanceSummary from './haproxyInstanceSummary';
import MysqlWaitEventAnalysesDetails from './mysqlWaitEventAnalysesDetails';
Expand All @@ -22,6 +23,7 @@ export const MysqlDashboards = {
mysqlInstancesCompare: new MySQLInstancesCompare(),
mysqlInstanceSummary: new MysqlInstanceSummary(),
mysqlMyRocksDetails: new MysqlMyRocksDetails(),
mysqlPerformanceSchemaDetails: new MysqlPerformanceSchemaDetails(),
mysqlReplicationSummary: new MysqlReplicationSummary(),
mysqlUserDetails: new MySQLUserDetails(),
mysqlWaitEventAnalysesDetails: new MysqlWaitEventAnalysesDetails(),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { GrafanaPanel } from '@interfaces/grafanaPanel';
import DashboardInterface from '@interfaces/dashboard';

export default class MysqlPerformanceSchemaDetails implements DashboardInterface {
url = 'graph/d/mysql-performance-schema/mysql-performance-schema-details';
// Primary memory panel: mysql_perf_schema_memory_events_used_bytes. Populated whenever
// memory instruments are enabled server-side (default on PS/MySQL 8.0+), so it must
// render real data end-to-end (collector -> VictoriaMetrics -> panel).
memoryCurrentUsedPanel = 'Memory Usage — Current Bytes Used (Top 15 by Event)';
// Panels added in PMM-12279 (perf_schema.memory_events collector -> memory panels).
// Names are copied verbatim from the dashboard JSON; the first one uses an em dash (U+2014).
memoryMetrics: GrafanaPanel[] = [
{ name: 'Memory Usage — Current Bytes Used (Top 15 by Event)', type: 'timeSeries' },
{ name: 'Memory Allocation Rate (Top 10 by Event)', type: 'timeSeries' },
{ name: 'Memory Free Rate (Top 10 by Event)', type: 'timeSeries' },
];
metrics: GrafanaPanel[] = [
{ name: 'Performance Schema File IO (Events)', type: 'timeSeries' },
{ name: 'Performance Schema File IO (Load)', type: 'timeSeries' },
{ name: 'Performance Schema File IO (Bytes)', type: 'timeSeries' },
{ name: 'Performance Schema Status Variables (Events)', type: 'timeSeries' },
{ name: 'Performance Schema Waits (Events)', type: 'timeSeries' },
{ name: 'Performance Schema Waits (Load)', type: 'timeSeries' },
{ name: 'Index Access Operations (Load)', type: 'timeSeries' },
{ name: 'Table Access Operations (Load)', type: 'timeSeries' },
{ name: 'Performance Schema SQL & External Locks (Events)', type: 'timeSeries' },
{ name: 'Performance Schema SQL and External Locks (Seconds)', type: 'timeSeries' },
{ name: 'MySQL Uptime', type: 'stat' },
{ name: 'Version', type: 'text' },
{ name: 'Current QPS', type: 'stat' },
{ name: 'File Handlers Used', type: 'stat' },
{ name: 'Table Open Cache Miss Ratio', type: 'stat' },
{ name: 'Table Open Cache Size', type: 'stat' },
{ name: 'Table Definition Cache Size', type: 'stat' },
{ name: 'Service', type: 'text' },
{ name: 'MySQL Connections', type: 'timeSeries' },
{ name: 'MySQL Client Thread Activity', type: 'timeSeries' },
{ name: 'MySQL Handlers', type: 'timeSeries' },
{ name: 'Top Command Counters', type: 'timeSeries' },
{ name: 'Process States', type: 'timeSeries' },
{ name: 'MySQL Network Traffic', type: 'timeSeries' },
{ name: 'System Uptime', type: 'stat' },
{ name: 'Load Average', type: 'stat' },
{ name: 'RAM', type: 'stat' },
{ name: 'Memory Available', type: 'stat' },
{ name: 'Virtual Memory', type: 'stat' },
{ name: 'Disk Space', type: 'stat' },
{ name: 'Min Space Available', type: 'stat' },
{ name: 'Node', type: 'text' },
{ name: 'CPU Usage', type: 'timeSeries' },
{ name: 'CPU Saturation and Max Core Usage', type: 'timeSeries' },
{ name: 'Disk I/O and Swap Activity', type: 'timeSeries' },
{ name: 'Network Traffic', type: 'timeSeries' },
...this.memoryMetrics,
];
// The two rate panels only plot series whose alloc/free rate is > 0, so under low load
// they can legitimately be empty. They are allow-listed here for any full-dashboard
// verifyAllPanelsHaveData() check; the feature test asserts data on memoryCurrentUsedPanel.
noDataMetrics: string[] = [
'Memory Allocation Rate (Top 10 by Event)',
'Memory Free Rate (Top 10 by Event)',
];
metricsWithData = this.metrics.filter((metric) => !this.noDataMetrics.includes(metric.name));
}
26 changes: 26 additions & 0 deletions e2e_tests/tests/dashboards/mysql/mysqlDashboards.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,3 +186,29 @@ pmmTest(
await dashboard.verifyPanelValues(dashboard.mysql.mysqlMyRocksDetails.metricsWithData);
},
);

// TODO: replace PMM-T0000 with the Zephyr test-case id reserved for PMM-12279.
pmmTest(
'PMM-T0000 - Verify Performance Schema Memory panels on MySQL Performance Schema Details Dashboard (PMM-12279) @pmm-ps-integration',
Comment on lines +190 to +192

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Replace the placeholder Zephyr ID before merge.

PMM-T0000 does not provide test-case traceability. Replace it with the reserved Zephyr ID.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@e2e_tests/tests/dashboards/mysql/mysqlDashboards.test.ts` around lines 190 -
192, Update the test title in pmmTest for PMM-12279 by replacing the PMM-T0000
placeholder with the reserved Zephyr test-case ID. Keep the rest of the title
and test behavior unchanged.

async ({ api, dashboard, page, urlHelper }) => {
const { service_name } = await api.inventoryApi.getServiceDetailsByRegex('ps_pmm');

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n -i -C 4 \
  'ps_pmm|query[-_]?source.*perfschema|perfschema.*query[-_]?source|mysql.*8(\.0)?' \
  . -g '!node_modules/**' -g '!dist/**' -g '!build/**'

Repository: percona/pmm-qa

Length of output: 50371


🏁 Script executed:

set -euo pipefail

printf '%s\n' '--- target test ---'
sed -n '150,225p' e2e_tests/tests/dashboards/mysql/mysqlDashboards.test.ts

printf '%s\n' '--- service selector implementation and usages ---'
rg -n -C 6 'getServiceDetailsByRegex|ps_pmm' e2e_tests --glob '*.ts' --glob '*.yml'

printf '%s\n' '--- environment/setup references for the default ps_pmm service ---'
rg -n -i -C 5 'mysql_service_name|service_name.*ps|ps[_-]pmm|mysql_version|query-source=perfschema' \
  qa-integration package_tests e2e_tests --glob '*.yml' --glob '*.yaml' --glob '*.ts' --glob '*.sh' \
  | head -n 500

Repository: percona/pmm-qa

Length of output: 50370


🏁 Script executed:

set -euo pipefail

printf '%s\n' '--- Percona Server setup ---'
sed -n '1,240p' qa-integration/pmm_qa/percona_server_for_mysql/percona-server-setup.yml

printf '%s\n' '--- Percona Server setup files and version/service-name definitions ---'
rg -n -C 4 'ps_version|query_source|service_name|pmm-admin add mysql|container_prefix|mysql_version' \
  qa-integration/pmm_qa/percona_server_for_mysql \
  qa-integration/pmm_qa --glob '*.yml' --glob '*.yaml' --glob '*.j2' --glob '*.sh' \
  | head -n 800

printf '%s\n' '--- test configuration and database matrix ---'
rg -n -i -C 4 'pmm-ps-integration|percona.*mysql|ps_version|QUERY_SOURCE|SETUP_TYPE|mysql.*8.0|mysql.*5.7' \
  e2e_tests package.json playwright.config.* qa-integration --glob '*.ts' --glob '*.js' --glob '*.json' \
  --glob '*.yml' --glob '*.yaml' --glob '*.env*' --glob '*.sh' \
  | head -n 800

Repository: percona/pmm-qa

Length of output: 50371


🏁 Script executed:

set -euo pipefail

printf '%s\n' '--- callers of the Percona Server setup ---'
rg -n -C 6 'percona-server-setup\.yml|percona_server_for_mysql|PS_VERSION|QUERY_SOURCE|SETUP_TYPE' \
  .github qa-integration scripts Makefile* package.json 2>/dev/null \
  | head -n 1000

printf '%s\n' '--- all setup entry points and workflow environment ---'
git ls-files | rg '(^|/)(workflows|.*workflow.*|.*setup.*|.*config.*)' \
  | rg -i 'ya?ml$|json$|sh$|ts$|js$' \
  | head -n 300

printf '%s\n' '--- exact collector prerequisite references ---'
rg -n -i -C 6 'memory_events|perf_schema.*memory|memory.*perf_schema|query.?source|8\.0\+' \
  e2e_tests qa-integration .github --glob '*.ts' --glob '*.yml' --glob '*.yaml' --glob '*.sh' \
  | head -n 1000

Repository: percona/pmm-qa

Length of output: 50370


🏁 Script executed:

set -euo pipefail

printf '%s\n' '--- PS framework registration and argument forwarding ---'
sed -n '1,150p' qa-integration/pmm_qa/pmm-framework/lib/config.sh
rg -n -C 8 'PS\b|PS_VERSION|QUERY_SOURCE|database.*ps|ansible.*percona|percona-server-setup' \
  qa-integration/pmm_qa/pmm-framework \
  qa-integration/pmm_qa/scripts \
  .github/workflows/runner-e2e-tests-playwright.yml \
  | head -n 1000

printf '%s\n' '--- inventory response shape and service fields ---'
sed -n '1,120p' e2e_tests/api/inventory.api.ts
rg -n -C 4 'interface GetService|type GetService|query.?source|query_source|service_type|service_name' \
  e2e_tests --glob '*.ts' | head -n 600

printf '%s\n' '--- deterministic setup/selector verifier ---'
python3 - <<'PY'
from pathlib import Path
import re

setup = Path("qa-integration/pmm_qa/percona_server_for_mysql/percona-server-setup.yml").read_text()
workflow = Path(".github/workflows/fb-e2e-suite.yml").read_text()
test = Path("e2e_tests/tests/dashboards/mysql/mysqlDashboards.test.ts").read_text()

assert "getServiceDetailsByRegex('ps_pmm')" in test
assert "SETUP_TYPE=replication" in workflow
assert "SETUP_TYPE=gr,QUERY_SOURCE=slowlog" in workflow

prefix = "ps_pmm{suffix}_{version}_"
for setup_type, query_source in [("replication", "perfschema"), ("gr", "slowlog")]:
    suffix = f"_{setup_type}"
    name = prefix.format(suffix=suffix, version="8_0") + "1_12345"
    assert re.search(r"ps_pmm", name)
    print(f"{name}: query_source={query_source}, matches ps_pmm=True")

print("The workflow creates both a perfschema service and a slowlog service.")
print("The test regex matches both service-name families.")
print("The selector does not constrain query_source or MySQL version.")
PY

Repository: percona/pmm-qa

Length of output: 50373


Select a service with the required collector configuration.

getServiceDetailsByRegex('ps_pmm') can select the group-replication service configured with slowlog, or a MySQL 5.7 service. Select or validate a MySQL 8.0+ service configured with query-source=perfschema before checking the memory panels.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@e2e_tests/tests/dashboards/mysql/mysqlDashboards.test.ts` at line 194, Update
the service selection around getServiceDetailsByRegex to choose or validate a
MySQL 8.0+ service configured with query-source=perfschema, rather than relying
on the ambiguous ps_pmm match. Ensure the selected service has the required
collector configuration before performing the memory-panel checks.


await page.goto(
urlHelper.buildUrlWithParameters(dashboard.mysql.mysqlPerformanceSchemaDetails.url, {
from: 'now-15m',
refresh: '5s',
serviceName: service_name,
}),
);

// Feature under test: the "Performance Schema Memory" row and its three panels are present.
await dashboard.verifyMetricsPresent(dashboard.mysql.mysqlPerformanceSchemaDetails.memoryMetrics);

// End-to-end proof (perf_schema.memory_events collector -> VictoriaMetrics -> panel):
// Current Bytes Used is populated whenever memory instruments are enabled server-side,
// which is the default on PS/MySQL 8.0+, so it must render real data.
await dashboard.verifyNamedPanelsHaveData([
dashboard.mysql.mysqlPerformanceSchemaDetails.memoryCurrentUsedPanel,
]);
},
);