|
78 | 78 | "collect.perf_schema.eventsstatements.digest_text_limit", 120, |
79 | 79 | "Maximum length of the normalized statement text", |
80 | 80 | ) |
| 81 | + collectPerfEventsWaits = flag.Bool( |
| 82 | + "collect.perf_schema.eventswaits", false, |
| 83 | + "Collect metrics from performance_schema.events_waits_summary_global_by_event_name", |
| 84 | + ) |
| 85 | + collectPerfFileEvents = flag.Bool( |
| 86 | + "collect.perf_schema.file_events", false, |
| 87 | + "Collect metrics from performance_schema.file_summary_by_event_name", |
| 88 | + ) |
81 | 89 | collectUserStat = flag.Bool("collect.info_schema.userstats", false, |
82 | 90 | "If running with userstat=1, set to true to collect user statistics", |
83 | 91 | ) |
@@ -184,6 +192,18 @@ const ( |
184 | 192 | ORDER BY SUM_TIMER_WAIT DESC |
185 | 193 | LIMIT %d |
186 | 194 | ` |
| 195 | + perfEventsWaitsQuery = ` |
| 196 | + SELECT EVENT_NAME, COUNT_STAR, SUM_TIMER_WAIT |
| 197 | + FROM performance_schema.events_waits_summary_global_by_event_name |
| 198 | + ` |
| 199 | + perfFileEventsQuery = ` |
| 200 | + SELECT |
| 201 | + EVENT_NAME, |
| 202 | + COUNT_READ, SUM_TIMER_READ, SUM_NUMBER_OF_BYTES_READ, |
| 203 | + COUNT_WRITE, SUM_TIMER_WRITE, SUM_NUMBER_OF_BYTES_WRITE, |
| 204 | + COUNT_MISC, SUM_TIMER_MISC |
| 205 | + FROM performance_schema.file_summary_by_event_name |
| 206 | + ` |
187 | 207 | userStatQuery = `SELECT * FROM information_schema.USER_STATISTICS` |
188 | 208 | ) |
189 | 209 |
|
@@ -330,6 +350,31 @@ var ( |
330 | 350 | "The total tmp disk tables of events statements by digest.", |
331 | 351 | []string{"schema", "digest"}, nil, |
332 | 352 | ) |
| 353 | + performanceSchemaEventsWaitsDesc = prometheus.NewDesc( |
| 354 | + prometheus.BuildFQName(namespace, performanceSchema, "events_waits_total"), |
| 355 | + "The total events waits by event name.", |
| 356 | + []string{"event_name"}, nil, |
| 357 | + ) |
| 358 | + performanceSchemaEventsWaitsTimeDesc = prometheus.NewDesc( |
| 359 | + prometheus.BuildFQName(namespace, performanceSchema, "events_waits_seconds_total"), |
| 360 | + "The total seconds of events waits by event name.", |
| 361 | + []string{"event_name"}, nil, |
| 362 | + ) |
| 363 | + performanceSchemaFileEventsDesc = prometheus.NewDesc( |
| 364 | + prometheus.BuildFQName(namespace, performanceSchema, "file_events_total"), |
| 365 | + "The total file events by event name/mode.", |
| 366 | + []string{"event_name", "mode"}, nil, |
| 367 | + ) |
| 368 | + performanceSchemaFileEventsTimeDesc = prometheus.NewDesc( |
| 369 | + prometheus.BuildFQName(namespace, performanceSchema, "file_events_seconds_total"), |
| 370 | + "The total seconds of file events by event name/mode.", |
| 371 | + []string{"event_name", "mode"}, nil, |
| 372 | + ) |
| 373 | + performanceSchemaFileEventsBytesDesc = prometheus.NewDesc( |
| 374 | + prometheus.BuildFQName(namespace, performanceSchema, "file_events_bytes_total"), |
| 375 | + "The total bytes of file events by event name/mode.", |
| 376 | + []string{"event_name", "mode"}, nil, |
| 377 | + ) |
333 | 378 | // Map known user-statistics values to types. Unknown types will be mapped as |
334 | 379 | // untyped. |
335 | 380 | informationSchemaUserStatisticsTypes = map[string]struct { |
@@ -667,6 +712,18 @@ func (e *Exporter) scrape(ch chan<- prometheus.Metric) { |
667 | 712 | return |
668 | 713 | } |
669 | 714 | } |
| 715 | + if *collectPerfEventsWaits { |
| 716 | + if err = scrapePerfEventsWaits(db, ch); err != nil { |
| 717 | + log.Println("Error scraping performance schema:", err) |
| 718 | + return |
| 719 | + } |
| 720 | + } |
| 721 | + if *collectPerfFileEvents { |
| 722 | + if err = scrapePerfFileEvents(db, ch); err != nil { |
| 723 | + log.Println("Error scraping performance schema:", err) |
| 724 | + return |
| 725 | + } |
| 726 | + } |
670 | 727 | if *collectUserStat { |
671 | 728 | if err = scrapeUserStat(db, ch); err != nil { |
672 | 729 | log.Println("Error scraping user stat:", err) |
@@ -1200,6 +1257,97 @@ func scrapePerfEventsStatements(db *sql.DB, ch chan<- prometheus.Metric) error { |
1200 | 1257 | return nil |
1201 | 1258 | } |
1202 | 1259 |
|
| 1260 | +func scrapePerfEventsWaits(db *sql.DB, ch chan<- prometheus.Metric) error { |
| 1261 | + // Timers here are returned in picoseconds. |
| 1262 | + perfSchemaEventsWaitsRows, err := db.Query(perfEventsWaitsQuery) |
| 1263 | + if err != nil { |
| 1264 | + return err |
| 1265 | + } |
| 1266 | + defer perfSchemaEventsWaitsRows.Close() |
| 1267 | + |
| 1268 | + var ( |
| 1269 | + eventName string |
| 1270 | + count, time uint64 |
| 1271 | + ) |
| 1272 | + |
| 1273 | + for perfSchemaEventsWaitsRows.Next() { |
| 1274 | + if err := perfSchemaEventsWaitsRows.Scan( |
| 1275 | + &eventName, &count, &time, |
| 1276 | + ); err != nil { |
| 1277 | + return err |
| 1278 | + } |
| 1279 | + ch <- prometheus.MustNewConstMetric( |
| 1280 | + performanceSchemaEventsWaitsDesc, prometheus.CounterValue, float64(count), |
| 1281 | + eventName, |
| 1282 | + ) |
| 1283 | + ch <- prometheus.MustNewConstMetric( |
| 1284 | + performanceSchemaEventsWaitsTimeDesc, prometheus.CounterValue, float64(time)/picoSeconds, |
| 1285 | + eventName, |
| 1286 | + ) |
| 1287 | + } |
| 1288 | + return nil |
| 1289 | +} |
| 1290 | + |
| 1291 | +func scrapePerfFileEvents(db *sql.DB, ch chan<- prometheus.Metric) error { |
| 1292 | + // Timers here are returned in picoseconds. |
| 1293 | + perfSchemaFileEventsRows, err := db.Query(perfFileEventsQuery) |
| 1294 | + if err != nil { |
| 1295 | + return err |
| 1296 | + } |
| 1297 | + defer perfSchemaFileEventsRows.Close() |
| 1298 | + |
| 1299 | + var ( |
| 1300 | + eventName string |
| 1301 | + countRead, timeRead, bytesRead uint64 |
| 1302 | + countWrite, timeWrite, bytesWrite uint64 |
| 1303 | + countMisc, timeMisc uint64 |
| 1304 | + ) |
| 1305 | + |
| 1306 | + for perfSchemaFileEventsRows.Next() { |
| 1307 | + if err := perfSchemaFileEventsRows.Scan( |
| 1308 | + &eventName, |
| 1309 | + &countRead, &timeRead, &bytesRead, |
| 1310 | + &countWrite, &timeWrite, &bytesWrite, |
| 1311 | + &countMisc, &timeMisc, |
| 1312 | + ); err != nil { |
| 1313 | + return err |
| 1314 | + } |
| 1315 | + ch <- prometheus.MustNewConstMetric( |
| 1316 | + performanceSchemaFileEventsDesc, prometheus.CounterValue, float64(countRead), |
| 1317 | + eventName, "read", |
| 1318 | + ) |
| 1319 | + ch <- prometheus.MustNewConstMetric( |
| 1320 | + performanceSchemaFileEventsTimeDesc, prometheus.CounterValue, float64(timeRead)/picoSeconds, |
| 1321 | + eventName, "read", |
| 1322 | + ) |
| 1323 | + ch <- prometheus.MustNewConstMetric( |
| 1324 | + performanceSchemaFileEventsBytesDesc, prometheus.CounterValue, float64(bytesRead), |
| 1325 | + eventName, "read", |
| 1326 | + ) |
| 1327 | + ch <- prometheus.MustNewConstMetric( |
| 1328 | + performanceSchemaFileEventsDesc, prometheus.CounterValue, float64(countWrite), |
| 1329 | + eventName, "write", |
| 1330 | + ) |
| 1331 | + ch <- prometheus.MustNewConstMetric( |
| 1332 | + performanceSchemaFileEventsTimeDesc, prometheus.CounterValue, float64(timeWrite)/picoSeconds, |
| 1333 | + eventName, "write", |
| 1334 | + ) |
| 1335 | + ch <- prometheus.MustNewConstMetric( |
| 1336 | + performanceSchemaFileEventsBytesDesc, prometheus.CounterValue, float64(bytesWrite), |
| 1337 | + eventName, "write", |
| 1338 | + ) |
| 1339 | + ch <- prometheus.MustNewConstMetric( |
| 1340 | + performanceSchemaFileEventsDesc, prometheus.CounterValue, float64(countMisc), |
| 1341 | + eventName, "misc", |
| 1342 | + ) |
| 1343 | + ch <- prometheus.MustNewConstMetric( |
| 1344 | + performanceSchemaFileEventsTimeDesc, prometheus.CounterValue, float64(timeMisc)/picoSeconds, |
| 1345 | + eventName, "misc", |
| 1346 | + ) |
| 1347 | + } |
| 1348 | + return nil |
| 1349 | +} |
| 1350 | + |
1203 | 1351 | func scrapeUserStat(db *sql.DB, ch chan<- prometheus.Metric) error { |
1204 | 1352 | informationSchemaUserStatisticsRows, err := db.Query(userStatQuery) |
1205 | 1353 | if err != nil { |
|
0 commit comments