telegraf/plugins/mysql/mysql.go

192 lines
3.2 KiB
Go

package mysql
import (
"database/sql"
"strconv"
"strings"
_ "github.com/go-sql-driver/mysql"
"github.com/influxdb/telegraf/plugins"
)
type Mysql struct {
Servers []string
}
var sampleConfig = `
# specify servers via a url matching:
# [username[:password]@][protocol[(address)]]/[?tls=[true|false|skip-verify]]
# e.g.
# root:root@http://10.0.0.18/?tls=false
# root:passwd@tcp(127.0.0.1:3036)/
#
# If no servers are specified, then localhost is used as the host.
servers = ["localhost"]
`
func (m *Mysql) SampleConfig() string {
return sampleConfig
}
func (m *Mysql) Description() string {
return "Read metrics from one or many mysql servers"
}
var localhost = ""
func (m *Mysql) Gather(acc plugins.Accumulator) error {
if len(m.Servers) == 0 {
// if we can't get stats in this case, thats fine, don't report
// an error.
m.gatherServer(localhost, acc)
return nil
}
for _, serv := range m.Servers {
err := m.gatherServer(serv, acc)
if err != nil {
return err
}
}
return nil
}
type mapping struct {
onServer string
inExport string
}
var mappings = []*mapping{
{
onServer: "Aborted_",
inExport: "aborted_",
},
{
onServer: "Bytes_",
inExport: "bytes_",
},
{
onServer: "Com_",
inExport: "commands_",
},
{
onServer: "Created_",
inExport: "created_",
},
{
onServer: "Handler_",
inExport: "handler_",
},
{
onServer: "Innodb_",
inExport: "innodb_",
},
{
onServer: "Key_",
inExport: "key_",
},
{
onServer: "Open_",
inExport: "open_",
},
{
onServer: "Opened_",
inExport: "opened_",
},
{
onServer: "Qcache_",
inExport: "qcache_",
},
{
onServer: "Table_",
inExport: "table_",
},
{
onServer: "Tokudb_",
inExport: "tokudb_",
},
{
onServer: "Threads_",
inExport: "threads_",
},
}
func (m *Mysql) gatherServer(serv string, acc plugins.Accumulator) error {
if serv == "localhost" {
serv = ""
}
db, err := sql.Open("mysql", serv)
if err != nil {
return err
}
defer db.Close()
rows, err := db.Query(`SHOW /*!50002 GLOBAL */ STATUS`)
if err != nil {
return err
}
for rows.Next() {
var name string
var val interface{}
err = rows.Scan(&name, &val)
if err != nil {
return err
}
var found bool
// Parse out user/password from server address tag if given
var servtag string
if strings.Contains(serv, "@") {
servtag = strings.Split(serv, "@")[1]
} else if serv == "" {
servtag = "localhost"
} else {
servtag = serv
}
tags := map[string]string{"server": servtag}
for _, mapped := range mappings {
if strings.HasPrefix(name, mapped.onServer) {
i, _ := strconv.Atoi(string(val.([]byte)))
acc.Add(mapped.inExport+name[len(mapped.onServer):], i, tags)
found = true
}
}
if found {
continue
}
switch name {
case "Queries":
i, err := strconv.ParseInt(string(val.([]byte)), 10, 64)
if err != nil {
return err
}
acc.Add("queries", i, tags)
case "Slow_queries":
i, err := strconv.ParseInt(string(val.([]byte)), 10, 64)
if err != nil {
return err
}
acc.Add("slow_queries", i, tags)
}
}
return nil
}
func init() {
plugins.Add("mysql", func() plugins.Plugin {
return &Mysql{}
})
}