Skip to content

Commit 80e48b6

Browse files
committed
Merge pull request #51 from prometheus/bjk/table_schema
Add metrics from information_schema.tables
2 parents 6655128 + 524e5ab commit 80e48b6

File tree

2 files changed

+141
-1
lines changed

2 files changed

+141
-1
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ Name | Description
1717
collect.auto_increment.columns | Collect auto_increment columns and max values from information_schema.
1818
collect.binlog_size | Compute the size of all binlog files combined (as specified by "SHOW MASTER LOGS")
1919
collect.info_schema.userstats | If running with userstat=1, set to true to collect user statistics.
20+
collect.info_schema.tables | Collect metrics from information_schema.tables.
21+
collect.info_schema.tables.databases | The list of databases to collect table stats for, or '`*`' for all.
2022
collect.perf_schema.eventsstatements | Collect metrics from performance_schema.events_statements_summary_by_digest.
2123
collect.perf_schema.eventsstatements.limit | Limit the number of events statements digests by response time. (default: 250)
2224
collect.perf_schema.eventsstatements.digest_text_limit | Maximum length of the normalized statement text. (default: 120)

mysqld_exporter.go

Lines changed: 139 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,14 @@ var (
3030
"collect.info_schema.processlist", false,
3131
"Collect current thread state counts from the information_schema.processlist",
3232
)
33+
collectTableSchema = flag.Bool(
34+
"collect.info_schema.tables", true,
35+
"Collect metrics from information_schema.tables",
36+
)
37+
tableSchemaDatabases = flag.String(
38+
"collect.info_schema.tables.databases", "*",
39+
"The list of databases to collect table stats for, or '*' for all",
40+
)
3341
collectGlobalStatus = flag.Bool(
3442
"collect.global_status", true,
3543
"Collect from SHOW GLOBAL STATUS",
@@ -204,7 +212,29 @@ const (
204212
COUNT_MISC, SUM_TIMER_MISC
205213
FROM performance_schema.file_summary_by_event_name
206214
`
207-
userStatQuery = `SELECT * FROM information_schema.USER_STATISTICS`
215+
userStatQuery = `SELECT * FROM information_schema.USER_STATISTICS`
216+
tableSchemaQuery = `
217+
SELECT
218+
TABLE_SCHEMA,
219+
TABLE_NAME,
220+
TABLE_TYPE,
221+
ifnull(ENGINE, 'NONE') as ENGINE,
222+
ifnull(VERSION, '0') as VERSION,
223+
ifnull(ROW_FORMAT, 'NONE') as ROW_FORMAT,
224+
ifnull(TABLE_ROWS, '0') as TABLE_ROWS,
225+
ifnull(DATA_LENGTH, '0') as DATA_LENGTH,
226+
ifnull(INDEX_LENGTH, '0') as INDEX_LENGTH,
227+
ifnull(DATA_FREE, '0') as DATA_FREE,
228+
ifnull(CREATE_OPTIONS, 'NONE') as CREATE_OPTIONS
229+
FROM information_schema.tables
230+
WHERE TABLE_SCHEMA = '%s'
231+
`
232+
dbListQuery = `
233+
SELECT
234+
SCHEMA_NAME
235+
FROM information_schema.schemata
236+
WHERE SCHEMA_NAME NOT IN ('mysql', 'performance_schema', 'information_schema')
237+
`
208238
)
209239

210240
// landingPage contains the HTML served at '/'.
@@ -255,6 +285,21 @@ var (
255285
"The max value of an auto_increment column from information_schema.",
256286
[]string{"schema", "table", "column"}, nil,
257287
)
288+
infoSchemaTablesVersionDesc = prometheus.NewDesc(
289+
prometheus.BuildFQName(namespace, informationSchema, "table_version"),
290+
"The version number of the table's .frm file",
291+
[]string{"schema", "table", "type", "engine", "row_format", "create_options"}, nil,
292+
)
293+
infoSchemaTablesRowsDesc = prometheus.NewDesc(
294+
prometheus.BuildFQName(namespace, informationSchema, "table_rows"),
295+
"The estimated number of rows in the table from information_schema.tables",
296+
[]string{"schema", "table"}, nil,
297+
)
298+
infoSchemaTablesSizeDesc = prometheus.NewDesc(
299+
prometheus.BuildFQName(namespace, informationSchema, "table_size"),
300+
"The size of the table components from information_schema.tables",
301+
[]string{"schema", "table", "component"}, nil,
302+
)
258303
globalPerformanceSchemaLostDesc = prometheus.NewDesc(
259304
prometheus.BuildFQName(namespace, globalStatus, "performance_schema_lost_total"),
260305
"Total number of MySQL instrumentations that could not be loaded or created due to memory constraints.",
@@ -671,6 +716,12 @@ func (e *Exporter) scrape(ch chan<- prometheus.Metric) {
671716
return
672717
}
673718
}
719+
if *collectTableSchema {
720+
if err = scrapeTableSchema(db, ch); err != nil {
721+
log.Println("Error scraping table schema:", err)
722+
return
723+
}
724+
}
674725
if *collectAutoIncrementColumns {
675726
if err = scrapeInformationSchema(db, ch); err != nil {
676727
log.Println("Error scraping information schema:", err)
@@ -1448,6 +1499,93 @@ func scrapeProcesslist(db *sql.DB, ch chan<- prometheus.Metric) error {
14481499
return nil
14491500
}
14501501

1502+
func scrapeTableSchema(db *sql.DB, ch chan<- prometheus.Metric) error {
1503+
var dbList []string
1504+
if *tableSchemaDatabases == "*" {
1505+
dbListRows, err := db.Query(dbListQuery)
1506+
if err != nil {
1507+
return err
1508+
}
1509+
defer dbListRows.Close()
1510+
1511+
var database string
1512+
1513+
for dbListRows.Next() {
1514+
if err := dbListRows.Scan(
1515+
&database,
1516+
); err != nil {
1517+
return err
1518+
}
1519+
dbList = append(dbList, database)
1520+
}
1521+
} else {
1522+
dbList = strings.Split(*tableSchemaDatabases, ",")
1523+
}
1524+
1525+
for _, database := range dbList {
1526+
tableSchemaRows, err := db.Query(fmt.Sprintf(tableSchemaQuery, database))
1527+
if err != nil {
1528+
return err
1529+
}
1530+
defer tableSchemaRows.Close()
1531+
1532+
var (
1533+
tableSchema string
1534+
tableName string
1535+
tableType string
1536+
engine string
1537+
version uint64
1538+
rowFormat string
1539+
tableRows uint64
1540+
dataLength uint64
1541+
indexLength uint64
1542+
dataFree uint64
1543+
createOptions string
1544+
)
1545+
1546+
for tableSchemaRows.Next() {
1547+
err = tableSchemaRows.Scan(
1548+
&tableSchema,
1549+
&tableName,
1550+
&tableType,
1551+
&engine,
1552+
&version,
1553+
&rowFormat,
1554+
&tableRows,
1555+
&dataLength,
1556+
&indexLength,
1557+
&dataFree,
1558+
&createOptions,
1559+
)
1560+
if err != nil {
1561+
return err
1562+
}
1563+
ch <- prometheus.MustNewConstMetric(
1564+
infoSchemaTablesVersionDesc, prometheus.GaugeValue, float64(version),
1565+
tableSchema, tableName, tableType, engine, rowFormat, createOptions,
1566+
)
1567+
ch <- prometheus.MustNewConstMetric(
1568+
infoSchemaTablesRowsDesc, prometheus.GaugeValue, float64(tableRows),
1569+
tableSchema, tableName,
1570+
)
1571+
ch <- prometheus.MustNewConstMetric(
1572+
infoSchemaTablesSizeDesc, prometheus.GaugeValue, float64(dataLength),
1573+
tableSchema, tableName, "data_length",
1574+
)
1575+
ch <- prometheus.MustNewConstMetric(
1576+
infoSchemaTablesSizeDesc, prometheus.GaugeValue, float64(indexLength),
1577+
tableSchema, tableName, "index_length",
1578+
)
1579+
ch <- prometheus.MustNewConstMetric(
1580+
infoSchemaTablesSizeDesc, prometheus.GaugeValue, float64(dataFree),
1581+
tableSchema, tableName, "data_free",
1582+
)
1583+
}
1584+
}
1585+
1586+
return nil
1587+
}
1588+
14511589
func newDesc(subsystem, name, help string) *prometheus.Desc {
14521590
return prometheus.NewDesc(
14531591
prometheus.BuildFQName(namespace, subsystem, name),

0 commit comments

Comments
 (0)