The health
library comes with a number of built-in checkers for well known
types of dependencies.
If a pre-built checker is not available, you can create your own checkers by
implementing the ICheckable
interface (which consists of a single method -
Status() (interface{}, error)
).
If you do create a custom-checker - consider opening a PR and adding it to the list of built-in checkers.
The HTTP checker is a generic HTTP call executor. To make use of it, instantiate and fill out a HTTPConfig
struct and pass it into checkers.NewHTTP(...)
.
The only required attribute is HTTPConfig.URL
(*url.URL
).
Refer to the source code for all available attributes on the struct.
The Redis checker allows you to test that your server is either available (by ping), is able to set a value, is able to get a value or all of the above.
To make use of it, instantiate and fill out a RedisConfig
struct and pass it to checkers.NewRedis(...)
.
The RedisConfig
must contain a valid RedisAuthConfig
and at least one check method (ping, set or get).
Refer to the godocs for additional info.
The SQL DB checker has implementations for the following interfaces:
SQLPinger
, which enclosesPingContext
insql.DB
andsql.Conn
SQLQueryer
, which enclosesQueryContext
insql.DB
,sql.Conn
,sql.Stmt
, andsql.Tx
SQLExecer
, which enclosesExecContext
insql.DB
,sql.Conn
,sql.Stmt
, andsql.Tx
The SQLConfig
struct is required when using the SQL DB health check. It must contain an inplementation of one of either SQLPinger
, SQLQueryer
, or SQLExecer
.
If SQLQueryer
or SQLExecer
are implemented, then Query
must be valid (len > 0).
Additionally, if SQLQueryer
or SQLExecer
are implemented, you have the option to also set either the QueryerResultHandler
or ExecerResultHandler
functions. These functions allow you to evaluate the result of a query or exec operation. If you choose not to implement these yourself, the default handlers are used.
The default ExecerResultHandler
is successful if the passed exec operation affected one and only one row.
The default QueryerResultHandler
is successful if the passed query operation returned one and only one row.
Use the SQLPinger
interface if your health check is only concerned with your application's database connectivity. All you need to do is set the Pinger
value in your SQLConfig
.
db, err := sql.Open("mysql", dsn)
if err != nil {
return err
}
sqlCheck, err := checkers.NewSQL(&checkers.SQLConfig{
Pinger: db
})
if err != nil {
return err
}
hc := health.New()
healthCheck.AddCheck(&health.Config{
Name: "sql-check",
Checker: sqlCheck,
Interval: time.Duration(3) * time.Second,
Fatal: true,
})
Use the SQLQueryer
interface if your health check requires you to read rows from your database. You can optionally supply a query result handler function. If you don't supply one, the default function will be used. The function signature for the handler is:
type SQLQueryerResultHandler func(rows *sql.Rows) (bool, error)
The default query handler returns true if there was exactly one row in the resultset:
func DefaultQueryHandler(rows *sql.Rows) (bool, error) {
defer rows.Close()
numRows := 0
for rows.Next() {
numRows++
}
return numRows == 1, nil
}
IMPORTANT: Note that your query handler is responsible for closing the passed *sql.Rows
value.
Sample SQLQueryer
implementation:
// this is our custom query row handler
func myQueryHandler(rows *sql.Rows) (bool, error) {
defer rows.Close()
var healthValue string
for rows.Next() {
// this query will ever return at most one row
if err := rows.Scan(&healthValue); err != nil {
return false, err
}
}
return healthValue == "ok", nil
}
db, err := sql.Open("mysql", dsn)
if err != nil {
return err
}
// we pass the id we are looking for inside the params value
sqlCheck, err := checkers.NewSQL(&checkers.SQLConfig{
Queryerer: db,
Query: "SELECT healthValue FROM some_table WHERE id = ?",
Params: []interface{}{1},
QueryerResultHandler: myQueryHandler
})
if err != nil {
return err
}
hc := health.New()
healthCheck.AddCheck(&health.Config{
Name: "sql-check",
Checker: sqlCheck,
Interval: time.Duration(3) * time.Second,
Fatal: true,
})
Use the SQLExecer
interface if your health check requires you to update or insert to your database. You can optionally supply an exec result handler function. If you don't supply one, the default function will be used. The function signature for the handler is:
type SQLExecerResultHandler func(result sql.Result) (bool, error)
The default exec handler returns true if there was exactly one affected row:
func DefaultExecHandler(result sql.Result) (bool, error) {
affectedRows, err := result.RowsAffected()
if err != nil {
return false, err
}
return affectedRows == int64(1), nil
}
Sample SQLExecer
implementation:
// this is our custom exec result handler
func myExecHandler(result sql.Result) (bool, error) {
insertId, err := result.LastInsertId()
if err != nil {
return false, err
}
// for this example, a check isn't valid
// until after the 100th iteration
return insertId > int64(100), nil
}
db, err := sql.Open("mysql", dsn)
if err != nil {
return err
}
sqlCheck, err := checkers.NewSQL(&checkers.SQLConfig{
Execer: db,
Query: "INSERT INTO checks (checkTS) VALUES (NOW())",
ExecerResultHandler: myExecHandler
})
if err != nil {
return err
}
hc := health.New()
healthCheck.AddCheck(&health.Config{
Name: "sql-check",
Checker: sqlCheck,
Interval: time.Duration(3) * time.Second,
Fatal: true,
})
Mongo checker allows you to test if an instance of MongoDB is available by using the underlying driver's ping method or check whether a collection exists or not.
To make use of it, initialize a MongoConfig
struct and pass it to checkers.NewMongo(...)
.
The MongoConfig
struct must specify either one or both of the Ping
or Collection
fields.
The reachable checker is a generic TCP/UDP checker. Use it to verify that a configured address can be contacted via a request over TCP or UDP. This is useful if you do not care about a response from the target and simply want to know if the URL is reachable.
The only required attribute is ReachableConfig.URL
(*url.URL
).
Refer to the source code for all available attributes on the struct.