Skip to content

Commit

Permalink
Merge 0bb65bc into beeea68
Browse files Browse the repository at this point in the history
  • Loading branch information
itchyny committed Jul 23, 2018
2 parents beeea68 + 0bb65bc commit f6f6678
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 20 deletions.
68 changes: 59 additions & 9 deletions mackerel-plugin-mysql/lib/mysql.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package mpmysql

import (
"errors"
"flag"
"fmt"
"log"
Expand Down Expand Up @@ -157,6 +158,36 @@ func (m *MySQLPlugin) MetricKeyPrefix() string {
return m.prefix
}

func (m *MySQLPlugin) fetchVersion(db mysql.Conn) (version [3]int, err error) {
rows, _, err := db.Query("SHOW VARIABLES WHERE VARIABLE_NAME = 'VERSION'")
if err != nil {
return
}
for _, row := range rows {
if len(row) > 1 {
versionString := string(row[1].([]byte))
if i := strings.IndexRune(versionString, '-'); i >= 0 {
// Trim -log or -debug, -MariaDB-...
versionString = versionString[:i]
}
xs := strings.Split(versionString, ".")
if len(xs) >= 2 {
version[0], _ = strconv.Atoi(xs[0])
version[1], _ = strconv.Atoi(xs[1])
if len(xs) >= 3 {
version[2], _ = strconv.Atoi(xs[2])
}
}
break
}
}
if version[0] == 0 {
err = errors.New("failed to get mysql version")
return
}
return
}

func (m *MySQLPlugin) fetchShowStatus(db mysql.Conn, stat map[string]float64) error {
rows, _, err := db.Query("show /*!50002 global */ status")
if err != nil {
Expand Down Expand Up @@ -186,8 +217,23 @@ func (m *MySQLPlugin) fetchShowInnodbStatus(db mysql.Conn, stat map[string]float
log.Fatalln("Hint: If you don't use InnoDB and see InnoDB Status error, you should set -disable_innodb")
}

var trxIDHexFormat bool
v, err := m.fetchVersion(db)
if err != nil {
log.Println(err)
}
// Transaction IDs are printed in hex format in version < 5.6.4.
// Ref: https://github.com/mysql/mysql-server/commit/3420dc52b68c9afcee0a19ba7c19a73c2fbb2913
// https://github.com/mysql/mysql-server/blob/mysql-5.6.3/storage/innobase/include/trx0types.h#L32
// https://github.com/mysql/mysql-server/blob/mysql-5.6.4/storage/innobase/include/trx0types.h#L32
// MariaDB 10.x is recognized as newer than 5.6.4, which should be correct.
// Ref: https://github.com/MariaDB/server/blob/mariadb-10.0.0/storage/innobase/include/trx0types.h#L32
if v[0] < 5 || v[0] == 5 && v[1] < 6 || v[0] == 5 && v[1] == 6 && v[2] < 4 {
trxIDHexFormat = true
}

if len(row) > 0 {
parseInnodbStatus(string(row[len(row)-1].([]byte)), &stat)
parseInnodbStatus(string(row[len(row)-1].([]byte)), trxIDHexFormat, &stat)
} else {
return fmt.Errorf("row length is too small: %d", len(row))
}
Expand Down Expand Up @@ -699,7 +745,7 @@ func setIfEmpty(p *map[string]float64, key string, val float64) {
}
}

func parseInnodbStatus(str string, p *map[string]float64) {
func parseInnodbStatus(str string, trxIDHexFormat bool, p *map[string]float64) {
isTransaction := false
prevLine := ""

Expand Down Expand Up @@ -748,7 +794,7 @@ func parseInnodbStatus(str string, p *map[string]float64) {
if len(record) >= 5 {
loVal = record[4]
}
val := makeBigint(record[3], loVal)
val := makeBigint(record[3], loVal, trxIDHexFormat)
increaseMap(p, "innodb_transactions", fmt.Sprintf("%d", val))
isTransaction = true
continue
Expand All @@ -757,7 +803,7 @@ func parseInnodbStatus(str string, p *map[string]float64) {
if record[7] == "undo" {
record[7] = ""
}
val := makeBigint(record[6], record[7])
val := makeBigint(record[6], record[7], trxIDHexFormat)
trx := (*p)["innodb_transactions"] - float64(val)
increaseMap(p, "unpurged_txns", fmt.Sprintf("%.f", trx))
continue
Expand Down Expand Up @@ -867,23 +913,23 @@ func parseInnodbStatus(str string, p *map[string]float64) {
if strings.Index(line, "Log sequence number") == 0 {
val, _ := atof(record[3])
if len(record) >= 5 {
val = float64(makeBigint(record[3], record[4]))
val = float64(makeBigint(record[3], record[4], false))
}
(*p)["log_bytes_written"] = val
continue
}
if strings.Index(line, "Log flushed up to") == 0 {
val, _ := atof(record[4])
if len(record) >= 6 {
val = float64(makeBigint(record[4], record[5]))
val = float64(makeBigint(record[4], record[5], false))
}
(*p)["log_bytes_flushed"] = val
continue
}
if strings.Index(line, "Last checkpoint at") == 0 {
val, _ := atof(record[3])
if len(record) >= 5 {
val = float64(makeBigint(record[3], record[4]))
val = float64(makeBigint(record[3], record[4], false))
}
(*p)["last_checkpoint"] = val
continue
Expand Down Expand Up @@ -992,9 +1038,13 @@ func increaseMap(p *map[string]float64, key string, src string) {
(*p)[key] = (*p)[key] + val
}

func makeBigint(hi string, lo string) int64 {
func makeBigint(hi string, lo string, hexFormat bool) int64 {
if lo == "" {
val, _ := strconv.ParseInt(hi, 16, 64)
if hexFormat {
val, _ := strconv.ParseInt(hi, 16, 64)
return val
}
val, _ := strconv.ParseInt(hi, 10, 64)
return val
}

Expand Down
22 changes: 11 additions & 11 deletions mackerel-plugin-mysql/lib/mysql_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,16 +154,16 @@ Number of rows inserted 3089, updated 220, deleted 212, read 2099881
END OF INNODB MONITOR OUTPUT`
stat := make(map[string]float64)

parseInnodbStatus(stub, &stat)
parseInnodbStatus(stub, false, &stat)
// Innodb Semaphores
assert.EqualValues(t, stat["spin_waits"], 947)
assert.EqualValues(t, stat["spin_rounds"], 9442)
assert.EqualValues(t, stat["os_waits"], 222)
assert.EqualValues(t, stat["innodb_sem_wait"], 0) // empty
assert.EqualValues(t, stat["innodb_sem_wait_time_ms"], 0) // empty
// Innodb Transactions
assert.EqualValues(t, stat["innodb_transactions"], 71194252676)
assert.EqualValues(t, stat["unpurged_txns"], 49185)
assert.EqualValues(t, stat["innodb_transactions"], 1093821584)
assert.EqualValues(t, stat["unpurged_txns"], 6021)
assert.EqualValues(t, stat["history_list"], 649)
assert.EqualValues(t, stat["current_transactions"], 6)
assert.EqualValues(t, stat["active_transactions"], 0)
Expand Down Expand Up @@ -324,7 +324,7 @@ END OF INNODB MONITOR OUTPUT
============================`
stat := make(map[string]float64)

parseInnodbStatus(stub, &stat)
parseInnodbStatus(stub, true, &stat)
// Innodb Semaphores
assert.EqualValues(t, stat["spin_waits"], 5020565400)
assert.EqualValues(t, stat["spin_rounds"], 3687067031)
Expand Down Expand Up @@ -497,7 +497,7 @@ END OF INNODB MONITOR OUTPUT
============================`
stat := make(map[string]float64)

parseInnodbStatus(stub, &stat)
parseInnodbStatus(stub, true, &stat)
// Innodb Semaphores
assert.EqualValues(t, stat["spin_waits"], 180466733)
assert.EqualValues(t, stat["spin_rounds"], 142931556)
Expand Down Expand Up @@ -632,7 +632,7 @@ END OF INNODB MONITOR OUTPUT
============================`
stat := make(map[string]float64)

parseInnodbStatus(stub, &stat)
parseInnodbStatus(stub, true, &stat)
// Innodb Semaphores
assert.EqualValues(t, stat["spin_waits"], 1762)
assert.EqualValues(t, stat["spin_rounds"], 30300)
Expand Down Expand Up @@ -864,16 +864,16 @@ END OF INNODB MONITOR OUTPUT
============================
`
stat := make(map[string]float64)
parseInnodbStatus(stub, &stat)
parseInnodbStatus(stub, false, &stat)
// Innodb Semaphores
assert.EqualValues(t, stat["spin_waits"], 0)
assert.EqualValues(t, stat["spin_rounds"], 0) // empty
assert.EqualValues(t, stat["os_waits"], 39)
assert.EqualValues(t, stat["innodb_sem_wait"], 0) // empty
assert.EqualValues(t, stat["innodb_sem_wait_time_ms"], 0) // empty
// Innodb Transactions
assert.EqualValues(t, stat["innodb_transactions"], 299348) // empty
assert.EqualValues(t, stat["unpurged_txns"], 19167)
assert.EqualValues(t, stat["innodb_transactions"], 49154) // empty
assert.EqualValues(t, stat["unpurged_txns"], 4479)
assert.EqualValues(t, stat["history_list"], 775)
assert.EqualValues(t, stat["current_transactions"], 1)
assert.EqualValues(t, stat["active_transactions"], 0)
Expand Down Expand Up @@ -1054,15 +1054,15 @@ MySQL thread id 2, OS thread handle 0x7efe7cba4700, query id 35 localhost root
END OF INNODB MONITOR OUTPUT
============================`
stat := make(map[string]float64)
parseInnodbStatus(stub, &stat)
parseInnodbStatus(stub, false, &stat)
// Innodb Semaphores
assert.EqualValues(t, stat["spin_waits"], 12)
assert.EqualValues(t, stat["spin_rounds"], 180)
assert.EqualValues(t, stat["os_waits"], 12)
assert.EqualValues(t, stat["innodb_sem_wait"], 0) // empty
assert.EqualValues(t, stat["innodb_sem_wait_time_ms"], 0) // empty
// Innodb Transactions
assert.EqualValues(t, stat["innodb_transactions"], 1287)
assert.EqualValues(t, stat["innodb_transactions"], 507)
assert.EqualValues(t, stat["unpurged_txns"], 2)
assert.EqualValues(t, stat["history_list"], 1)
assert.EqualValues(t, stat["current_transactions"], 3)
Expand Down

0 comments on commit f6f6678

Please sign in to comment.