Skip to content

Commit

Permalink
Merge 0c17944 into 38148e7
Browse files Browse the repository at this point in the history
  • Loading branch information
Songmu committed Oct 25, 2015
2 parents 38148e7 + 0c17944 commit 88fb5e3
Show file tree
Hide file tree
Showing 4 changed files with 193 additions and 0 deletions.
32 changes: 32 additions & 0 deletions check-mysql/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# check-mysql

## Description

Checks for MySQL

## Sub Commands

- connection
- replication

## check-mysql connection

Checks the number of MySQL connections.

### Setting

```
[plugin.checks.mysql_connection]
command = "/path/to/check-mysql connection --host=127.0.0.1 --port=3306 --user=USER --password=PASSWORD --warning=250 --critical=280
```

## check-mysql replication

Checks MySQL replication status and its second behind master.

### Setting

```
[plugin.checks.mysql_replication]
command = "/path/to/check-mysql replication --host=127.0.0.1 --port=3306 --user=USER --password=PASSWORD --warning=5 --critical=10
```
53 changes: 53 additions & 0 deletions check-mysql/check-mysql.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package main

import (
"fmt"
"os"
"strings"

"github.com/mackerelio/checkers"
"github.com/ziutek/mymysql/mysql"
_ "github.com/ziutek/mymysql/native"
)

type mysqlSetting struct {
Host string `short:"h" long:"host" default:"localhost" description:"Hostname"`
Port string `short:"p" long:"port" default:"3306" description:"Port"`
User string `short:"u" long:"user" default:"root" description:"Username"`
Pass string `short:"P" long:"password" default:"" description:"Password"`
}

var commands = map[string](func([]string) *checkers.Checker){
"replication": checkReplication,
"connection": checkConnection,
}

func separateSub(argv []string) (string, []string) {
if len(argv) == 0 || strings.HasPrefix(argv[0], "-") {
return "", argv
}
return argv[0], argv[1:]
}

func main() {
subCmd, argv := separateSub(os.Args[1:])
fn, ok := commands[subCmd]
if !ok {
fmt.Println(`Usage:
check-mysql [subcommand] [OPTIONS]
SubCommands:`)
for k := range commands {
fmt.Printf(" %s\n", k)
}
os.Exit(1)
}
ckr := fn(argv)
ckr.Name = fmt.Sprintf("MySQL %s", strings.ToUpper(string(subCmd[0]))+subCmd[1:])
ckr.Exit()
}

func newMySQL(m mysqlSetting) mysql.Conn {
target := fmt.Sprintf("%s:%s", m.Host, m.Port)
return mysql.New("tcp", "", target, m.User, m.Pass, "")
}
48 changes: 48 additions & 0 deletions check-mysql/connection.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package main

import (
"fmt"
"os"

"github.com/jessevdk/go-flags"
"github.com/mackerelio/checkers"
)

type connectionOpts struct {
mysqlSetting
Crit int64 `short:"c" long:"critical" default:"250" description:"critical if the number of connection is over"`
Warn int64 `short:"w" long:"warning" default:"200" description:"warning if the number of connection is over"`
}

func checkConnection(args []string) *checkers.Checker {
opts := connectionOpts{}
psr := flags.NewParser(&opts, flags.Default)
psr.Usage = "connection [OPTIONS]"
_, err := psr.ParseArgs(args)
if err != nil {
os.Exit(1)
}
db := newMySQL(opts.mysqlSetting)
err = db.Connect()
if err != nil {
return checkers.Unknown("couldn't connect DB")
}
defer db.Close()

rows, res, err := db.Query("SHOW GLOBAL STATUS LIKE 'Threads_Connected'")
if err != nil {
return checkers.Unknown("couldn't execute query")
}

idxValue := res.Map("Value")
threadsConnected := rows[0].Int64(idxValue)

checkSt := checkers.OK
msg := fmt.Sprintf("%d connections", threadsConnected)
if threadsConnected > opts.Crit {
checkSt = checkers.CRITICAL
} else if threadsConnected > opts.Warn {
checkSt = checkers.WARNING
}
return checkers.NewChecker(checkSt, msg)
}
60 changes: 60 additions & 0 deletions check-mysql/replication.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package main

import (
"fmt"
"os"

"github.com/jessevdk/go-flags"
"github.com/mackerelio/checkers"
)

type replicationOpts struct {
mysqlSetting
Crit int64 `short:"c" long:"critical" default:"250" description:"critical if the seconds behind master is over"`
Warn int64 `short:"w" long:"warning" default:"200" description:"warning if the seconds behind master is over"`
}

func checkReplication(args []string) *checkers.Checker {
opts := replicationOpts{}
psr := flags.NewParser(&opts, flags.Default)
psr.Usage = "replication [OPTIONS]"
_, err := psr.ParseArgs(args)
if err != nil {
os.Exit(1)
}
db := newMySQL(opts.mysqlSetting)
err = db.Connect()
if err != nil {
return checkers.Unknown("couldn't connect DB")
}
defer db.Close()

rows, res, err := db.Query("SHOW SLAVE STATUS")
if err != nil {
return checkers.Unknown("couldn't execute query")
}

if len(rows) == 0 {
return checkers.Ok("MySQL is not slave")
}

idxIoThreadRunning := res.Map("Slave_IO_Running")
idxSQLThreadRunning := res.Map("Slave_SQL_Running")
idxSecondsBehindMaster := res.Map("Seconds_Behind_Master")
ioThreadStatus := rows[0].Str(idxIoThreadRunning)
sqlThreadStatus := rows[0].Str(idxSQLThreadRunning)
secondsBehindMaster := rows[0].Int64(idxSecondsBehindMaster)

if ioThreadStatus == "No" || sqlThreadStatus == "No" {
return checkers.Critical("MySQL replication has been stopped")
}

checkSt := checkers.OK
msg := fmt.Sprintf("MySQL replication behind master %d seconds", secondsBehindMaster)
if secondsBehindMaster > opts.Crit {
checkSt = checkers.CRITICAL
} else if secondsBehindMaster > opts.Warn {
checkSt = checkers.WARNING
}
return checkers.NewChecker(checkSt, msg)
}

0 comments on commit 88fb5e3

Please sign in to comment.