Skip to content

Conversation

@sklochkov
Copy link

What & why

This PR adds two opt-in collectors that expose per-user statement activity from MySQL’s sys schema, and fixes a failure mode in the existing --collect.sys.user_summary on MySQL 8.x. It also includes unit tests, docs, and a Docker Compose harness to exercise collectors locally.

New collectors (opt-in)

  • --collect.sys.user_summary_by_statement_latency
    Scrapes sys.x$user_summary_by_statement_latency to expose per-user totals and latency aggregates.

  • --collect.sys.user_summary_by_statement_type
    Scrapes sys.x$user_summary_by_statement_type to expose per-user by statement type aggregates.

Requirements: MySQL ≥ 5.7 with performance_schema enabled and the sys schema available.

Harden existing collector

  • --collect.sys.user_summary
    Some MySQL 8.x installations occasionally surface negative values for current_memory / total_memory_allocated in the sys view, which previously caused a scan into uint64 to fail and the scrape to error. We now clamp these to ≥ 0 (via SQL), avoiding exporter errors while preserving metric semantics.

Flags & metrics

--collect.sys.user_summary_by_statement_latency

Labels: user
Emits:

  • mysql_sys_user_summary_by_statement_latency_total
  • mysql_sys_user_summary_by_statement_latency (seconds total)
  • mysql_sys_user_summary_by_statement_max_latency (seconds)
  • mysql_sys_user_summary_by_statement_lock_latency (seconds total)
  • mysql_sys_user_summary_by_statement_cpu_latency (seconds total)
  • mysql_sys_user_summary_by_statement_rows_sent_total
  • mysql_sys_user_summary_by_statement_rows_examined_total
  • mysql_sys_user_summary_by_statement_rows_affected_total
  • mysql_sys_user_summary_by_statement_full_scans_total

--collect.sys.user_summary_by_statement_type

Labels: user, statement
Emits:

  • mysql_sys_user_summary_by_statement_type_total
  • mysql_sys_user_summary_by_statement_type_latency (seconds total)
  • mysql_sys_user_summary_by_statement_type_max_latency (seconds)
  • mysql_sys_user_summary_by_statement_type_lock_latency (seconds total)
  • mysql_sys_user_summary_by_statement_type_cpu_latency (seconds total)
  • mysql_sys_user_summary_by_statement_type_rows_sent_total
  • mysql_sys_user_summary_by_statement_type_rows_examined_total
  • mysql_sys_user_summary_by_statement_type_rows_affected_total
  • mysql_sys_user_summary_by_statement_type_full_scans_total

Implementation notes

  • Metric names follow the existing sys_user_summary.go style (namespace mysql, subsystem sys, metric stem user_summary_by_*).
  • Latencies are converted from picoseconds → seconds using the shared picoSeconds constant.
  • Exported as gauges, in line with other sys collectors.

Behavior change in --collect.sys.user_summary

  • Query uses GREATEST(current_memory, 0) and GREATEST(total_memory_allocated, 0) to avoid negative values in 8.x. No metric name/type changes.

Testing

Unit tests

  • New: sys_user_summary_by_statement_latency_test.go
  • New: sys_user_summary_by_statement_type_test.go
  • Updated: sys_user_summary_test.go (robust SQL matcher, guard channel reads, fix column name, align with clamping)

Each test uses sqlmock and the repo’s MetricResult/readMetric helpers to verify:

  • SQL is issued against the correct sys.x$… view,
  • label sets and value order,
  • latency ps→seconds conversion,
  • metric types (gauges).

Run:

go test ./collector -run UserSummary go test ./...

Docker Compose integration harness (developer convenience)

A self-contained script to validate collectors against a local MySQL:

  • docker-compose.yml (fixed network mysql-test)

  • mysql/conf.d/perf-schema.cnf (ensures Performance Schema/consumers on)

  • mysql/initdb/01-users.sql (creates/grants exporter and app; caching_sha2_password)

  • seed/seed.sh (simple INSERT/SELECT/UPDATE/SLEEP to populate sys views)

  • test_compose_collectors.sh

    • builds local exporter image
    • ensures users/grants if the data dir is reused
    • starts exporter per --collect.* flag (inside the Docker network; no host port binding)
    • fetches /metrics from inside the network
    • writes per-flag logs to _testlogs/
    • includes a broad TESTS set (plus optional auto-discovery of flags from --help)

Run:

./test_compose_collectors.sh

Backwards compatibility & perf

  • New collectors are disabled by default; no changes for existing users unless flags are set.
  • The user_summary clamp only affects rare negative values; otherwise behavior and types are unchanged.
  • Queries are single simple SELECTs over sys.x$… views; expected to be inexpensive with Performance Schema enabled.

How to review

Key files:

  • collector/sys_user_summary_by_statement_latency.go
  • collector/sys_user_summary_by_statement_type.go
  • collector/sys_user_summary.go (clamp)
  • collector/*_test.go (new + updated tests)
  • README.md (docs for new flags + integration test)
  • docker-compose.yml, mysql/, seed/, test_compose_collectors.sh (integration harness)

Happy to split the test harness/docs into a separate PR if you prefer, but they’re isolated from runtime code.

@sklochkov sklochkov force-pushed the main branch 2 times, most recently from 4141e24 to c889bec Compare September 11, 2025 15:46
…p negative memory; unit tests Add two new collectors: - --collect.sys.user_summary_by_statement_latency - --collect.sys.user_summary_by_statement_type Both follow the existing sys collector patterns: - metric names: mysql_sys_user_summary_by_statement_{latency|type}_* - label sets: {user} and {user,statement} - latencies converted from picoseconds to seconds (picoSeconds) - exported as gauges Also harden --collect.sys.user_summary against negative memory values observed on MySQL 8.x by clamping: GREATEST(current_memory, 0) AS current_memory GREATEST(total_memory_allocated, 0) AS total_memory_allocated Tests: - Update sys_user_summary_test.go: * robust SQL regex match * channel-read guard (no nil deref) * column name typo fixed ("statements") * expected values aligned with SQL-side clamping - Add sys_user_summary_by_statement_latency_test.go - Add sys_user_summary_by_statement_type_test.go Notes: - No changes to default enablement; flags must be passed explicitly. - Metric help strings note seconds for latency metrics. Verification: - go test ./collector -run UserSummary - go test ./... (full) Signed-off-by: Sergei Klochkov <sklochko@thousandeyes.com>
… runner; docs Add a self-contained integration test that spins up MySQL 8.4 with performance_schema, seeds a small workload, and validates collectors via a locally-built exporter image. What's included: - docker-compose.yml (fixed network name: mysql-test) - mysql/conf.d/perf-schema.cnf - mysql/initdb/01-users.sql (exporter/app users, grants) - seed/seed.sh (INSERT/SELECT/UPDATE/SLEEP loop) - test_compose_collectors.sh: * builds mysqld-exporter:local * ensures users (caching_sha2_password) * runs exporter per --collect.* flag (no host port binding) * curls /metrics from inside the network * per-flag log files under ./_testlogs/ * robust readiness + failure diagnostics * optional auto-discovery of collector flags from --help Docs (README.md): - Document new flags: --collect.sys.user_summary_by_statement_latency --collect.sys.user_summary_by_statement_type * list emitted metric families and units - Note clamping behavior in --collect.sys.user_summary - Add "Docker Compose integration test" section with usage Usage: ./test_compose_collectors.sh Artifacts: _testlogs/exporter_<flag>.log License: Added the mandatory license comments to the newly-committed source files. This commit touches only test infra and docs; no exporter runtime code changes. Signed-off-by: Sergei Klochkov <sklochko@thousandeyes.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

1 participant