Skip to content

feat(rta): extend Real-Time Analytics to MySQL#5509

Draft
theTibi wants to merge 8 commits into
mainfrom
rta-mysql-test
Draft

feat(rta): extend Real-Time Analytics to MySQL#5509
theTibi wants to merge 8 commits into
mainfrom
rta-mysql-test

Conversation

@theTibi

@theTibi theTibi commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Summary

Extends Real-Time Analytics (RTA) — previously MongoDB-only — to MySQL. Currently-running queries are collected from the MySQL sys schema processlist (sys.x$processlist, the machine-readable variant of sys.processlist), mirroring the existing MongoDB currentOp flow.

A user can start an RTA session for a MySQL service, see it in the Real-time sessions list, and watch live running queries (with elapsed time, host, and a details pane of MySQL-specific attributes) in the Real-time overview.

Changes

API / proto

  • query.proto: new QueryMySQLData payload added to the QueryData oneof (command, state, program name, rows examined/sent, full scan, db instance address, database, user).
  • realtimeanalytics.proto: ListServicesResponse now also returns mysql services.
  • inventory/agents.proto: new AGENT_TYPE_RTA_MYSQL_AGENT (20) and RTAMySQLAgent message, wired into List/Get agent responses.

Agent

  • New agent/agents/mysql/realtimeanalytics collector that periodically reads currently-running statements from sys.x$processlist and streams them to the server.
  • It selects the full processlist row and stores every column in query_raw_json, pretty-printed (numbers stay numbers, SQL NULLs become null) — mirroring how the MongoDB agent dumps the whole currentOp document.
  • Supervisor wiring for the new agent type.

Managed

  • RTAMySQLAgentType model with DSN / TLS-files / compatibility / agent-type wiring.
  • realtimeanalytics service: ListServices/StartSession support MySQL; getRTAAgentTypeForServiceType maps a MySQL service to the RTA MySQL agent.
  • rtaMySQLAgentConfig built-in agent state; converters and inventory gRPC server handle the new agent type.

UI

  • RTA types gain the QueryMySQLData payload and mysql available services.
  • QueryAndDetails renders MySQL-specific metrics (command, state, program name, rows examined/sent, full scan) and uses SQL syntax highlighting; the overview query cell and syntax highlighter gain SQL support; the Raw-data tab shows the complete, formatted processlist row.
  • A "Hide COMMIT" toolbar toggle filters bare transaction-control statements (COMMIT/ROLLBACK/BEGIN/START TRANSACTION), which can dominate the list under transactional workloads. Data is still collected; the toggle only affects the view.
  • Selection requests MySQL services; disclaimer updated to mention MySQL.

Testing

  • Verified end-to-end against a live PMM server with a Percona Server 8.0 instance under sysbench-style load: the MySQL service appears as RTA-capable, a session starts and reports RUNNING, and live queries from sys.x$processlist flow through to the overview/details/raw views with the MySQL payload populated; the Hide-COMMIT toggle removes transaction-control noise.
  • Go: affected packages build and go vet is clean; version unit tests pass.
  • UI: tsc passes and the RTA unit tests pass (added MySQL cases to QueryAndDetails plus queryLanguage/isTransactionControl unit tests).

Note: the generated swagger spec/clients were regenerated locally; maintainers may want to re-run make -C api gen with the pinned toolchain to normalize any formatting before merge.

@theTibi theTibi requested review from a team as code owners June 17, 2026 13:49
@theTibi theTibi requested review from 4nte, JiriCtvrtka, matejkubinec and mattiasimonato and removed request for a team June 17, 2026 13:49
@it-percona-cla

it-percona-cla commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

CLA assistant check
All committers have signed the CLA.

@theTibi theTibi marked this pull request as draft June 17, 2026 13:52
@codecov

codecov Bot commented Jun 17, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 16.92913% with 422 lines in your changes missing coverage. Please review.
✅ Project coverage is 43.22%. Comparing base (2478fef) to head (8b4f967).

Files with missing lines Patch % Lines
agent/agents/mysql/realtimeanalytics/mysql.go 32.46% 128 Missing and 1 partial ⚠️
admin/commands/inventory/change_agent_rta_mysql.go 0.00% 85 Missing ⚠️
managed/services/inventory/agents.go 0.00% 71 Missing ⚠️
admin/commands/inventory/add_agent_rta_mysql.go 0.00% 41 Missing ⚠️
agent/agents/mysql/realtimeanalytics/connection.go 0.00% 19 Missing ⚠️
managed/services/agents/mysql.go 0.00% 17 Missing ⚠️
managed/services/converters.go 0.00% 14 Missing ⚠️
admin/commands/inventory/list_agents.go 0.00% 11 Missing ⚠️
agent/agents/supervisor/supervisor.go 0.00% 10 Missing ⚠️
managed/services/realtimeanalytics/service.go 62.96% 9 Missing and 1 partial ⚠️
... and 5 more
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #5509      +/-   ##
==========================================
- Coverage   43.50%   43.22%   -0.29%     
==========================================
  Files         413      417       +4     
  Lines       42953    43450     +497     
==========================================
+ Hits        18687    18780      +93     
- Misses      22392    22795     +403     
- Partials     1874     1875       +1     
Flag Coverage Δ
admin 33.82% <0.00%> (-0.96%) ⬇️
agent 48.71% <28.18%> (-0.32%) ⬇️
managed 42.69% <15.89%> (-0.15%) ⬇️
vmproxy 72.22% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Comment on lines +34 to +39
// MySQL RTA shipped in 3.8.0 — an agent in [3.7.0, 3.8.0) supports MongoDB RTA but
// would not understand the MySQL builtin, so it must be reported as unsupported.
assert.False(t, isRtaFeatureSupported("3.7.0", models.MySQLServiceType))
assert.False(t, isRtaFeatureSupported("3.7.99", models.MySQLServiceType))
assert.True(t, isRtaFeatureSupported("3.8.0", models.MySQLServiceType))
assert.True(t, isRtaFeatureSupported("3.9.0", models.MySQLServiceType))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
// MySQL RTA shipped in 3.8.0 — an agent in [3.7.0, 3.8.0) supports MongoDB RTA but
// would not understand the MySQL builtin, so it must be reported as unsupported.
assert.False(t, isRtaFeatureSupported("3.7.0", models.MySQLServiceType))
assert.False(t, isRtaFeatureSupported("3.7.99", models.MySQLServiceType))
assert.True(t, isRtaFeatureSupported("3.8.0", models.MySQLServiceType))
assert.True(t, isRtaFeatureSupported("3.9.0", models.MySQLServiceType))
// MySQL RTA shipped in 3.9.0 — an agent in [3.7.0, 3.8.0) supports MongoDB RTA but
// would not understand the MySQL builtin, so it must be reported as unsupported.
assert.False(t, isRtaFeatureSupported("3.7.0", models.MySQLServiceType))
assert.False(t, isRtaFeatureSupported("3.7.99", models.MySQLServiceType))
assert.False(t, isRtaFeatureSupported("3.8.0", models.MySQLServiceType))
assert.True(t, isRtaFeatureSupported("3.9.0", models.MySQLServiceType))

}

return versionParsed.IsFeatureSupported(version.MongoDBRtaAgentSupportVersion)
return versionParsed.IsFeatureSupported(rtaMinAgentVersion(serviceType))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

what will be in result if someone calls this func with pmmAgentVersion='3.9.0', servicetype=Valkey?

defer cancel()

rows, err := m.db.QueryContext(queryCtx, currentQueriesSQL)
if err != nil {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

as I remember it is needed to separate errors:

  • NoRows -> result list is just empty - no need to produce error
  • other errors - return error

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good point to double-check. Here QueryContext (not QueryRow) is used, so it never returns sql.ErrNoRows — an empty processlist just yields zero rows.Next() iterations and we return an empty slice with a nil error, which is exactly the "empty list, no error" behaviour. The only way into this if err != nil branch is a real query failure.

What was genuinely off is the message: "not available or permission denied" was a misleading catch-all (it would mislabel e.g. a transient timeout), and it's now redundant since availability/permissions are validated up front by the startup preflight. I've reworded it to a neutral "failed to query sys.x$processlist: %w" and added a comment noting the empty-result semantics (a97f0c8).


Generated by Claude Code

return nil, "", err
}

// RTA agent needs only a single short-lived connection at a time.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

why short-lived? it needs long-lived

@maxkondr

Copy link
Copy Markdown
Contributor

More points missed:

  • API tests for new RTA agent
  • extending pmm-admin inventory add/change agent for new RTA agent

theTibi added 7 commits June 19, 2026 13:51
Adds MySQL support to Real-Time Analytics (RTA) alongside the existing
MongoDB implementation. Running queries are sourced from the sys schema
processlist (sys.x$processlist), mirroring the MongoDB currentOp flow.

API:
- query.proto: new QueryMySQLData payload added to QueryData oneof
- realtimeanalytics.proto: ListServicesResponse now returns mysql services
- inventory agents.proto: new AGENT_TYPE_RTA_MYSQL_AGENT (20) and
  RTAMySQLAgent message; wired into List/Get agent responses

Agent:
- new agent/agents/mysql/realtimeanalytics collector that periodically
  reads currently running statements from sys.x$processlist and streams
  them to the server
- supervisor wiring for AGENT_TYPE_RTA_MYSQL_AGENT

Managed:
- RTAMySQLAgentType model + DSN/Files/compatibility/agent-type wiring
- realtimeanalytics service: ListServices/StartSession support MySQL,
  getRTAAgentTypeForServiceType maps MySQL service -> RTA MySQL agent
- rtaMySQLAgentConfig built-in agent state; converters + inventory grpc
  server handle the new agent type

UI:
- rta types: QueryMySQLData payload, mysql in available services
- QueryAndDetails renders MySQL-specific metrics (command, state,
  program name, rows examined/sent, full scan) and uses SQL highlighting
- overview query cell + syntax highlighter gain SQL language support
- selection requests MySQL services; disclaimer mentions MySQL
Addresses review feedback on the MySQL RTA:

- Raw data now mirrors the MongoDB agent: the collector selects the full
  sys.x$processlist row (SELECT *) and stores every column in
  query_raw_json, pretty-printed with json.MarshalIndent. Numeric columns
  are kept as numbers and SQL NULLs as null. The details view keeps a
  curated subset. This surfaces execution_engine, lock_latency, cpu_latency,
  rows_affected, tmp_tables, trx_state/latency, pid, current_memory, etc.
- Overview gains a "Hide COMMIT" toolbar toggle that filters bare
  transaction-control statements (COMMIT/ROLLBACK/BEGIN/START TRANSACTION),
  which can dominate the list under transactional workloads. Data is still
  collected; the toggle only affects the view.
- Added unit tests for the queryLanguage and isTransactionControl helpers.
Addresses code-review feedback on the MySQL RTA:

- Version gate (correctness): MySQL RTA is now gated on a dedicated
  MySQLRtaAgentSupportVersion (3.8.0), not the MongoDB 3.7.0 version.
  isRtaFeatureSupported takes the service type so ListServices/StartSession
  no longer enable MySQL RTA against agents in [3.7.0, 3.8.0) that lack the
  AGENT_TYPE_RTA_MYSQL_AGENT builtin and would dead-end in the supervisor.
  Disclaimer updated to "MongoDB (3.7.0+) and MySQL (3.8.0+)".

- Minimum-duration floor: the collector now filters
  statement_latency >= 10ms in SQL, mirroring the MongoDB collector's
  microsecs_running >= 10_000 and avoiding large buckets of sub-ms
  statements. (The Hide-COMMIT toggle remains, since durable commits
  exceed the floor.)

- Tests: added Go table tests for coerceValue/mapString/mapInt/mapFloat
  and buildQueryData (latency math, full_scan, NULL handling, raw JSON),
  plus a unit test for the per-type version gate.

- Nits: fixed shutdown race in the collector (WaitGroup before close),
  documented coerceValue's numeric-coercion caveat, corrected the stale
  "MongoDB only" comment and the proto doc (sys.x$processlist), reused the
  shared queryLanguage() helper in QueryAndDetails, and hardened
  isTransactionControl (trailing ';', WORK keyword, whitespace).
Drop the 10ms statement_latency filter from the MySQL RTA collector so all
currently-running statements are collected, not only those running >= 10ms.
Idle ("Sleep"/"Daemon") connections, the agent's own connection and rows
without a current statement are still excluded. The Hide-COMMIT view toggle
remains for filtering transaction-control noise.
Before reporting RUNNING, the MySQL RTA agent now verifies the instance can
actually serve Real-Time Analytics and fails with AGENT_STATUS_INITIALIZATION_ERROR
(surfaced as a session ERROR) otherwise, instead of looping silently with no data:

- reject MariaDB (its performance_schema/sys schema differ and have no compatible
  sys.x$processlist), detected via the shared version.GetMySQLVersion helper;
- require performance_schema to be enabled;
- require sys.x$processlist to be readable by the monitoring user (catches missing
  schema and insufficient privileges).

A connection failure is now also reported as INITIALIZATION_ERROR. This closes the
silent-failure gap noted in review for MariaDB, disabled performance_schema and
permission problems.
- Gate MySQL RTA on 3.9.0 (the release that ships the collector) instead of
  3.8.0; add V3_9_0 and update the disclaimer and gate test accordingly.
- isRtaFeatureSupported now returns false for service types that do not support
  RTA at all (e.g. Valkey/PostgreSQL) instead of falling back to the MongoDB
  version; rtaMinAgentVersion returns (version, ok).
- Reword the collector's query error: an empty processlist is not an error
  (QueryContext never returns ErrNoRows), so the catch-all
  "not available or permission denied" message becomes a neutral
  "failed to query sys.x$processlist" (availability/permissions are already
  validated by the startup preflight).
- Fix the misleading connection comment: the pool keeps a single long-lived,
  reused connection (ConnMaxLifetime=0), not a short-lived one.
… agent

Brings the MySQL RTA agent to parity with MongoDB:

- proto: AddRTAMySQLAgentParams / ChangeRTAMySQLAgentParams and the
  rta_mysql_agent entries in Add/ChangeAgentRequest/Response oneofs;
  regenerated Go + swagger spec/clients.
- managed: AgentsService.AddRTAMySQLAgent / ChangeRTAMySQLAgent and the
  inventory gRPC AddAgent/ChangeAgent wiring.
- pmm-admin: `inventory add agent rta-mysql-agent` and
  `inventory change agent rta-mysql-agent`, plus list-agents rendering.
- api-tests: TestRTAMySQLAgent (add/get/change, partial update, validation
  errors); AddAgent test helper handles the new agent type.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants