Skip to content

Commit

Permalink
skip SPACE_TYPE column for MariaDB >=10.5 (#860)
Browse files Browse the repository at this point in the history
- to be able to scrape information_schema.innodb_sys_tablespaces
- https://jira.mariadb.org/browse/MDEV-19940

Signed-off-by: Vlad Gusev <[email protected]>
Co-authored-by: Birk Bohne <[email protected]>
  • Loading branch information
s10 and businessbean authored Aug 29, 2024
1 parent d65c5e6 commit 18bce7f
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 13 deletions.
56 changes: 45 additions & 11 deletions collector/info_schema_innodb_sys_tablespaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"errors"
"fmt"

"github.com/blang/semver/v4"
"github.com/go-kit/log"
"github.com/prometheus/client_golang/prometheus"
)
Expand All @@ -31,7 +32,8 @@ const innodbTablespacesTablenameQuery = `
WHERE table_name = 'INNODB_SYS_TABLESPACES'
OR table_name = 'INNODB_TABLESPACES'
`
const innodbTablespacesQuery = `

const innodbTablespacesQueryMySQL = `
SELECT
SPACE,
NAME,
Expand All @@ -46,6 +48,21 @@ const innodbTablespacesQuery = `
ALLOCATED_SIZE
FROM information_schema.` + "`%s`"

// SPACE_TYPE has been removed in MariaDB 10.5 https://jira.mariadb.org/browse/MDEV-19940
const innodbTablespacesQueryMariaDB = `
SELECT
SPACE,
NAME,
ifnull((SELECT column_name
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = 'information_schema'
AND TABLE_NAME = ` + "'%s'" + `
AND COLUMN_NAME = 'FILE_FORMAT' LIMIT 1), 'NONE') as FILE_FORMAT,
ifnull(ROW_FORMAT, 'NONE') as ROW_FORMAT,
FILE_SIZE,
ALLOCATED_SIZE
FROM information_schema.` + "`%s`"

// Metric descriptors.
var (
infoSchemaInnodbTablesspaceInfoDesc = prometheus.NewDesc(
Expand Down Expand Up @@ -88,14 +105,18 @@ func (ScrapeInfoSchemaInnodbTablespaces) Scrape(ctx context.Context, instance *i
var tablespacesTablename string
var query string
db := instance.getDB()

err := db.QueryRowContext(ctx, innodbTablespacesTablenameQuery).Scan(&tablespacesTablename)
if err != nil {
return err
}

switch tablespacesTablename {
case "INNODB_SYS_TABLESPACES", "INNODB_TABLESPACES":
query = fmt.Sprintf(innodbTablespacesQuery, tablespacesTablename, tablespacesTablename)
query = fmt.Sprintf(innodbTablespacesQueryMySQL, tablespacesTablename, tablespacesTablename)
if instance.flavor == FlavorMariaDB && instance.version.GTE(semver.MustParse("10.5.0")) {
query = fmt.Sprintf(innodbTablespacesQueryMariaDB, tablespacesTablename, tablespacesTablename)
}
default:
return errors.New("Couldn't find INNODB_SYS_TABLESPACES or INNODB_TABLESPACES in information_schema.")
}
Expand All @@ -117,15 +138,28 @@ func (ScrapeInfoSchemaInnodbTablespaces) Scrape(ctx context.Context, instance *i
)

for tablespacesRows.Next() {
err = tablespacesRows.Scan(
&tableSpace,
&tableName,
&fileFormat,
&rowFormat,
&spaceType,
&fileSize,
&allocatedSize,
)
var err error
if instance.flavor == FlavorMariaDB && instance.version.GTE(semver.MustParse("10.5.0")) {
err = tablespacesRows.Scan(
&tableSpace,
&tableName,
&fileFormat,
&rowFormat,
&fileSize,
&allocatedSize,
)
} else {
err = tablespacesRows.Scan(
&tableSpace,
&tableName,
&fileFormat,
&rowFormat,
&spaceType,
&fileSize,
&allocatedSize,
)
}

if err != nil {
return err
}
Expand Down
57 changes: 55 additions & 2 deletions collector/info_schema_innodb_sys_tablespaces_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"testing"

"github.com/DATA-DOG/go-sqlmock"
"github.com/blang/semver/v4"
"github.com/go-kit/log"
"github.com/prometheus/client_golang/prometheus"
dto "github.com/prometheus/client_model/go"
Expand All @@ -31,7 +32,10 @@ func TestScrapeInfoSchemaInnodbTablespaces(t *testing.T) {
t.Fatalf("error opening a stub database connection: %s", err)
}
defer db.Close()
inst := &instance{db: db}
inst := &instance{
db: db,
flavor: FlavorMySQL,
}

columns := []string{"TABLE_NAME"}
rows := sqlmock.NewRows(columns).
Expand All @@ -43,7 +47,7 @@ func TestScrapeInfoSchemaInnodbTablespaces(t *testing.T) {
rows = sqlmock.NewRows(columns).
AddRow(1, "sys/sys_config", "Barracuda", "Dynamic", "Single", 100, 100).
AddRow(2, "db/compressed", "Barracuda", "Compressed", "Single", 300, 200)
query := fmt.Sprintf(innodbTablespacesQuery, tablespacesTablename, tablespacesTablename)
query := fmt.Sprintf(innodbTablespacesQueryMySQL, tablespacesTablename, tablespacesTablename)
mock.ExpectQuery(sanitizeQuery(query)).WillReturnRows(rows)

ch := make(chan prometheus.Metric)
Expand All @@ -68,6 +72,55 @@ func TestScrapeInfoSchemaInnodbTablespaces(t *testing.T) {
convey.So(expect, convey.ShouldResemble, got)
}
})
}

func TestScrapeInfoSchemaInnodbTablespacesWithoutSpaceType(t *testing.T) {
db, mock, err := sqlmock.New()
if err != nil {
t.Fatalf("error opening a stub database connection: %s", err)
}
defer db.Close()
inst := &instance{
db: db,
flavor: FlavorMariaDB,
version: semver.MustParse("10.5.0"),
}

columns := []string{"TABLE_NAME"}
rows := sqlmock.NewRows(columns).
AddRow("INNODB_SYS_TABLESPACES")
mock.ExpectQuery(sanitizeQuery(innodbTablespacesTablenameQuery)).WillReturnRows(rows)

tablespacesTablename := "INNODB_SYS_TABLESPACES"
columns = []string{"SPACE", "NAME", "FILE_FORMAT", "ROW_FORMAT", "FILE_SIZE", "ALLOCATED_SIZE"}
rows = sqlmock.NewRows(columns).
AddRow(1, "sys/sys_config", "Barracuda", "Dynamic", 100, 100).
AddRow(2, "db/compressed", "Barracuda", "Compressed", 300, 200)
query := fmt.Sprintf(innodbTablespacesQueryMariaDB, tablespacesTablename, tablespacesTablename)
mock.ExpectQuery(sanitizeQuery(query)).WillReturnRows(rows)

ch := make(chan prometheus.Metric)
go func() {
if err = (ScrapeInfoSchemaInnodbTablespaces{}).Scrape(context.Background(), inst, ch, log.NewNopLogger()); err != nil {
t.Errorf("error calling function on test: %s", err)
}
close(ch)
}()

expected := []MetricResult{
{labels: labelMap{"tablespace_name": "sys/sys_config", "file_format": "Barracuda", "row_format": "Dynamic", "space_type": ""}, value: 1, metricType: dto.MetricType_GAUGE},
{labels: labelMap{"tablespace_name": "sys/sys_config"}, value: 100, metricType: dto.MetricType_GAUGE},
{labels: labelMap{"tablespace_name": "sys/sys_config"}, value: 100, metricType: dto.MetricType_GAUGE},
{labels: labelMap{"tablespace_name": "db/compressed", "file_format": "Barracuda", "row_format": "Compressed", "space_type": ""}, value: 2, metricType: dto.MetricType_GAUGE},
{labels: labelMap{"tablespace_name": "db/compressed"}, value: 300, metricType: dto.MetricType_GAUGE},
{labels: labelMap{"tablespace_name": "db/compressed"}, value: 200, metricType: dto.MetricType_GAUGE},
}
convey.Convey("Metrics comparison", t, func() {
for _, expect := range expected {
got := readMetric(<-ch)
convey.So(expect, convey.ShouldResemble, got)
}
})

// Ensure all SQL queries were executed
if err := mock.ExpectationsWereMet(); err != nil {
Expand Down

0 comments on commit 18bce7f

Please sign in to comment.